X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Ftint.c;h=44b6d9e8952702855230b7c4d92f418191b4435a;hb=bef508d2e43e3fb90e3f4e31ec36ba1d7cd6b8bc;hp=ece6dbc5f4655996caf1e3a169ae2a8f90e33c76;hpb=7a0fc200e711dea262ccabd7d07d53aa6d91c9df;p=chaz%2Ftint2 diff --git a/src/tint.c b/src/tint.c index ece6dbc..44b6d9e 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) { @@ -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++) { @@ -480,14 +488,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 - return; + 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; + } } } //printf("atom root_win = %s, %s\n", XGetAtomName(server.dsp, at), tsk->title); @@ -514,9 +527,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 +598,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); } @@ -659,39 +668,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; } @@ -728,11 +704,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 +735,25 @@ 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); - - tv.tv_usec = 500000; - tv.tv_sec = 0; + // 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) { while (XPending (server.dsp)) { XNextEvent(server.dsp, &e); @@ -840,22 +825,34 @@ int main (int argc, char *argv[]) break; } } + + // 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; + read(timer->id, &dummy, sizeof(uint64_t)); + timer->_callback(); + } + timer_iter = timer_iter->next; + } } - 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; + 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) {