X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Ftint.c;h=9e64ed37ac3c54e03a7077b1814d02ab9355cd67;hb=77088c4602bb9cbbb71b84f1dc24a30790ce283f;hp=ece6dbc5f4655996caf1e3a169ae2a8f90e33c76;hpb=7a0fc200e711dea262ccabd7d07d53aa6d91c9df;p=chaz%2Ftint2 diff --git a/src/tint.c b/src/tint.c index ece6dbc..9e64ed3 100644 --- a/src/tint.c +++ b/src/tint.c @@ -19,10 +19,10 @@ **************************************************************************/ #include -#include #include #include #include +#include #include #include #include @@ -38,7 +38,7 @@ #include "systraybar.h" #include "panel.h" #include "tooltip.h" - +#include "timer.h" void signal_handler(int sig) { @@ -58,7 +58,7 @@ void init (int argc, char *argv[]) exit(0); } if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) { - printf("tint2 version 0.7.svn\n"); + printf("tint2 version 0.8\n"); exit(0); } if (!strcmp(argv[i], "-c")) { @@ -74,12 +74,20 @@ void init (int argc, char *argv[]) } // Set signal handler - signal(SIGUSR1, signal_handler); - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); - signal(SIGHUP, signal_handler); + struct sigaction sa = { .sa_handler = signal_handler }; + sigaction(SIGUSR1, &sa, 0); + sigaction(SIGINT, &sa, 0); + sigaction(SIGTERM, &sa, 0); + sigaction(SIGHUP, &sa, 0); signal(SIGCHLD, SIG_IGN); // don't have to wait() after fork() - signal(SIGALRM, tooltip_sighandler); + // block all signals, such that no race conditions occur before pselect in our main loop + sigset_t block_mask; + sigaddset(&block_mask, SIGINT); + sigaddset(&block_mask, SIGTERM); + sigaddset(&block_mask, SIGHUP); + sigaddset(&block_mask, SIGUSR1); + sigprocmask(SIG_BLOCK, &block_mask, 0); + // set global data memset(&server, 0, sizeof(Server_global)); @@ -111,7 +119,7 @@ void init (int argc, char *argv[]) setlocale (LC_ALL, ""); // load default icon - char *path; + gchar *path; const gchar * const *data_dirs; data_dirs = g_get_system_data_dirs (); for (i = 0; data_dirs[i] != NULL; i++) { @@ -170,86 +178,6 @@ void get_snapshot(const char *path) } -Taskbar *click_taskbar (Panel *panel, int x, int y) -{ - Taskbar *tskbar; - int i; - - if (panel_horizontal) { - for (i=0; i < panel->nb_desktop ; i++) { - tskbar = &panel->taskbar[i]; - if (tskbar->area.on_screen && x >= tskbar->area.posx && x <= (tskbar->area.posx + tskbar->area.width)) - return tskbar; - } - } - else { - for (i=0; i < panel->nb_desktop ; i++) { - tskbar = &panel->taskbar[i]; - if (tskbar->area.on_screen && y >= tskbar->area.posy && y <= (tskbar->area.posy + tskbar->area.height)) - return tskbar; - } - } - return NULL; -} - - -Task *click_task (Panel *panel, int x, int y) -{ - GSList *l0; - Taskbar *tskbar; - - if ( (tskbar = click_taskbar(panel, x, y)) ) { - if (panel_horizontal) { - Task *tsk; - for (l0 = tskbar->area.list; l0 ; l0 = l0->next) { - tsk = l0->data; - if (tsk->area.on_screen && x >= tsk->area.posx && x <= (tsk->area.posx + tsk->area.width)) { - return tsk; - } - } - } - else { - Task *tsk; - for (l0 = tskbar->area.list; l0 ; l0 = l0->next) { - tsk = l0->data; - if (tsk->area.on_screen && y >= tsk->area.posy && y <= (tsk->area.posy + tsk->area.height)) { - return tsk; - } - } - } - } - return NULL; -} - - -int click_padding(Panel *panel, int x, int y) -{ - if (panel_horizontal) { - if (x < panel->area.paddingxlr || x > panel->area.width-panel->area.paddingxlr) - return 1; - } - else { - if (y < panel->area.paddingxlr || y > panel->area.height-panel->area.paddingxlr) - return 1; - } - return 0; -} - - -int click_clock(Panel *panel, int x, int y) -{ - Clock clk = panel->clock; - if (panel_horizontal) { - if (clk.area.on_screen && x >= clk.area.posx && x <= (clk.area.posx + clk.area.width)) - return TRUE; - } else { - if (clk.area.on_screen && y >= clk.area.posy && y <= (clk.area.posy + clk.area.height)) - return TRUE; - } - return FALSE; -} - - void window_action (Task *tsk, int action) { if (!tsk) return; @@ -295,6 +223,20 @@ void window_action (Task *tsk, int action) windows_set_desktop(tsk->win, desk); if (desk == server.desktop) set_active(tsk->win); + break; + case NEXT_TASK: + if (task_active) { + Task *tsk1; + tsk1 = next_task(task_active); + set_active(tsk1->win); + } + break; + case PREV_TASK: + if (task_active) { + Task *tsk1; + tsk1 = prev_task(task_active); + set_active(tsk1->win); + } } } @@ -480,12 +422,19 @@ void event_property_notify (XEvent *e) else { tsk = task_get_task (win); if (!tsk) { - // some stupid wm send _NET_WM_STATE after the window was minimized to tray??? if (at != server.atom._NET_WM_STATE) return; - else if (!window_is_skip_taskbar(win)) { - if (tsk = add_task(win)) - panel_refresh = 1; + else { + // xfce4 sends _NET_WM_STATE after minimized to tray, so we need to check if window is mapped + // if it is mapped and not set as skip_taskbar, we must add it to our task list + XWindowAttributes wa; + XGetWindowAttributes(server.dsp, win, &wa); + if (wa.map_state == IsViewable && !window_is_skip_taskbar(win)) { + if ( (tsk = add_task(win)) ) + panel_refresh = 1; + else + return; + } else return; } @@ -514,9 +463,7 @@ void event_property_notify (XEvent *e) // Demand attention else if (at == server.atom._NET_WM_STATE) { if (window_is_urgent (win)) { - task_urgent = tsk; - tick_urgent = 0; - time_precision = 1; + add_urgent(tsk); } if (window_is_skip_taskbar(win)) { remove_task( tsk ); @@ -587,9 +534,7 @@ void event_property_notify (XEvent *e) else if (at == server.atom.WM_HINTS) { XWMHints* wmhints = XGetWMHints(server.dsp, win); if (wmhints && wmhints->flags & XUrgencyHint) { - task_urgent = tsk; - tick_urgent = 0; - time_precision = 1; + add_urgent(tsk); } XFree(wmhints); } @@ -601,15 +546,11 @@ void event_property_notify (XEvent *e) void event_expose (XEvent *e) { - if (e->xany.window == g_tooltip.window) - tooltip_update(); - else { - Panel *panel; - panel = get_panel(e->xany.window); - if (!panel) return; - // TODO : one panel_refresh per panel ? - panel_refresh = 1; - } + Panel *panel; + panel = get_panel(e->xany.window); + if (!panel) return; + // TODO : one panel_refresh per panel ? + panel_refresh = 1; } @@ -657,44 +598,6 @@ void event_configure_notify (Window win) } -void event_timer() -{ - struct timeval stv; - int i; - - if (gettimeofday(&stv, 0)) return; - - if (abs(stv.tv_sec - time_clock.tv_sec) < time_precision) return; - time_clock.tv_sec = stv.tv_sec; - time_clock.tv_sec -= time_clock.tv_sec % time_precision; - - // urgent task - if (task_urgent) { - if (tick_urgent < max_tick_urgent) { - task_urgent->area.is_active = !task_urgent->area.is_active; - task_urgent->area.redraw = 1; - tick_urgent++; - } - } - - // update battery -#ifdef ENABLE_BATTERY - if (battery_enabled) { - update_battery(); - for (i=0 ; i < nb_panel ; i++) - panel1[i].battery.area.resize = 1; - } -#endif - - // update clock - if (time1_format) { - for (i=0 ; i < nb_panel ; i++) - panel1[i].clock.area.resize = 1; - } - panel_refresh = 1; -} - - void dnd_message(XClientMessageEvent *e) { Panel *panel = get_panel(e->window); @@ -728,11 +631,12 @@ void dnd_message(XClientMessageEvent *e) int main (int argc, char *argv[]) { XEvent e; - fd_set fd; + fd_set fdset; int x11_fd, i; - struct timeval tv; Panel *panel; GSList *it; + GSList* timer_iter; + struct timer* timer; init (argc, argv); @@ -758,17 +662,66 @@ int main (int argc, char *argv[]) x11_fd = ConnectionNumber(server.dsp); XSync(server.dsp, False); + sigset_t empty_mask; + sigemptyset(&empty_mask); + while (1) { - // thanks to AngryLlama for the timer - // Create a File Description Set containing x11_fd - FD_ZERO (&fd); - FD_SET (x11_fd, &fd); + if (panel_refresh) { + panel_refresh = 0; + + if (refresh_systray) { + panel = (Panel*)systray.area.panel; + XSetWindowBackgroundPixmap (server.dsp, panel->main_win, None); + } + for (i=0 ; i < nb_panel ; i++) { + panel = &panel1[i]; + + if (panel->temp_pmap) XFreePixmap(server.dsp, panel->temp_pmap); + panel->temp_pmap = XCreatePixmap(server.dsp, server.root_win, panel->area.width, panel->area.height, server.depth); + + refresh(&panel->area); + XCopyArea(server.dsp, panel->temp_pmap, panel->main_win, server.gc, 0, 0, panel->area.width, panel->area.height, 0, 0); + } + XFlush (server.dsp); - tv.tv_usec = 500000; - tv.tv_sec = 0; + if (refresh_systray) { + refresh_systray = 0; + panel = (Panel*)systray.area.panel; + // tint2 doen't draw systray icons. it just redraw background. + XSetWindowBackgroundPixmap (server.dsp, panel->main_win, panel->temp_pmap); + // force icon's refresh + refresh_systray_icon(); + } + } + + // thanks to AngryLlama for the timer + // Create a File Description Set containing x11_fd, and every timer_fd + FD_ZERO (&fdset); + FD_SET (x11_fd, &fdset); + int max_fd = x11_fd; + timer_iter = timer_list; + while (timer_iter) { + timer = timer_iter->data; + max_fd = timer->id > max_fd ? timer->id : max_fd; + FD_SET(timer->id, &fdset); + timer_iter = timer_iter->next; + } // Wait for X Event or a Timer - if (select(x11_fd+1, &fd, 0, 0, &tv)) { + if (pselect(max_fd+1, &fdset, 0, 0, 0, &empty_mask) > 0) { + // we need to iterate over the whole timer list, since fd_set can only be checked with the + // brute force method FD_ISSET for every possible timer + timer_iter = timer_list; + while (timer_iter) { + timer = timer_iter->data; + if (FD_ISSET(timer->id, &fdset)) { + uint64_t dummy; + if ( -1 != read(timer->id, &dummy, sizeof(uint64_t)) ) + timer->_callback(); + } + timer_iter = timer_iter->next; + } + while (XPending (server.dsp)) { XNextEvent(server.dsp, &e); @@ -785,9 +738,9 @@ int main (int argc, char *argv[]) case MotionNotify: { if (!g_tooltip.enabled) break; Panel* panel = get_panel(e.xmotion.window); - Task* task = click_task(panel, e.xmotion.x, e.xmotion.y); - if (task) - tooltip_trigger_show(task, e.xmotion.x_root, e.xmotion.y_root); + Area* area = click_area(panel, e.xmotion.x, e.xmotion.y); + if (area->_get_tooltip_text) + tooltip_trigger_show(area, panel, e.xmotion.x_root, e.xmotion.y_root); else tooltip_trigger_hide(); break; @@ -801,6 +754,11 @@ int main (int argc, char *argv[]) event_expose(&e); break; + case MapNotify: + if (e.xany.window == g_tooltip.window) + tooltip_update(); + break; + case PropertyNotify: event_property_notify(&e); break; @@ -819,7 +777,7 @@ int main (int argc, char *argv[]) break; case UnmapNotify: case DestroyNotify: - if (!systray.area.on_screen) + if (e.xany.window == g_tooltip.window || !systray.area.on_screen) break; for (it = systray.list_icons; it; it = g_slist_next(it)) { if (((TrayWindow*)it->data)->id == e.xany.window) { @@ -841,49 +799,20 @@ int main (int argc, char *argv[]) } } } - event_timer(); switch (signal_pending) { - case SIGUSR1: // reload config file - signal_pending = 0; - init_config(); - config_read_file (config_path); - init_panel(); - cleanup_config(); - break; - case SIGINT: - case SIGTERM: - case SIGHUP: - cleanup (); - return 0; - } - - if (panel_refresh) { - panel_refresh = 0; - - if (refresh_systray) { - panel = (Panel*)systray.area.panel; - XSetWindowBackgroundPixmap (server.dsp, panel->main_win, None); - } - for (i=0 ; i < nb_panel ; i++) { - panel = &panel1[i]; - - if (panel->temp_pmap) XFreePixmap(server.dsp, panel->temp_pmap); - panel->temp_pmap = XCreatePixmap(server.dsp, server.root_win, panel->area.width, panel->area.height, server.depth); - - refresh(&panel->area); - XCopyArea(server.dsp, panel->temp_pmap, panel->main_win, server.gc, 0, 0, panel->area.width, panel->area.height, 0, 0); - } - XFlush (server.dsp); - - if (refresh_systray) { - refresh_systray = 0; - panel = (Panel*)systray.area.panel; - // tint2 doen't draw systray icons. it just redraw background. - XSetWindowBackgroundPixmap (server.dsp, panel->main_win, panel->temp_pmap); - // force icon's refresh - refresh_systray_icon(); - } + case SIGUSR1: // reload config file + signal_pending = 0; + init_config(); + config_read_file (config_path); + init_panel(); + cleanup_config(); + break; + case SIGINT: + case SIGTERM: + case SIGHUP: + cleanup (); + return 0; } } }