]> Dogcows Code - chaz/tint2/blobdiff - src/tint.c
gcc 4.3.2 confusused when var_name identical to type
[chaz/tint2] / src / tint.c
index 163fd9ea223e8a2b2e649ebda61dd93cad6fac09..44b6d9e8952702855230b7c4d92f418191b4435a 100644 (file)
 **************************************************************************/
 
 #include <sys/stat.h>
-#include <sys/time.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <string.h>
 #include <X11/Xutil.h>
 #include <X11/Xatom.h>
@@ -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++)  {
@@ -265,8 +273,10 @@ void window_action (Task *tsk, int action)
                        XIconifyWindow (server.dsp, tsk->win, server.screen);
                        break;
                case TOGGLE_ICONIFY:
-                       if (tsk == task_active) XIconifyWindow (server.dsp, tsk->win, server.screen);
-                       else set_active (tsk->win);
+                       if (task_active && tsk->win == task_active->win)
+                               XIconifyWindow (server.dsp, tsk->win, server.screen);
+                       else
+                               set_active (tsk->win);
                        break;
                case SHADE:
                        window_toggle_shade (tsk->win);
@@ -478,10 +488,20 @@ void event_property_notify (XEvent *e)
        else {
                tsk = task_get_task (win);
                if (!tsk) {
-                       if ( at != server.atom._NET_WM_STATE)
-                               return;
-                       else if ( !(tsk = add_task(win)) )
+                       if (at != server.atom._NET_WM_STATE)
                                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);
 
@@ -507,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 );
@@ -580,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);
                }
@@ -652,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;
 }
 
 
@@ -721,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);
 
@@ -751,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);
 
@@ -833,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) {
This page took 0.025612 seconds and 4 git commands to generate.