]> Dogcows Code - chaz/tint2/blobdiff - src/tint.c
*add* render finitely often systray icons (at most every 50 ms)
[chaz/tint2] / src / tint.c
index 987003cacd9a75ee0ae430dca78a9769d625dcbf..0d7865726eb8ace74668d69d17df3928eb14a8be 100644 (file)
@@ -27,6 +27,7 @@
 #include <X11/Xutil.h>
 #include <X11/Xatom.h>
 #include <X11/Xlocale.h>
+#include <X11/extensions/Xdamage.h>
 #include <Imlib2.h>
 #include <signal.h>
 
@@ -61,7 +62,7 @@ void init (int argc, char *argv[])
                        printf("tint2 version 0.8\n");
                        exit(0);
                }
-               if (!strcmp(argv[i], "-c"))     {
+               if (!strcmp(argv[i], "-c")) {
                        i++;
                        if (i < argc)
                                config_path = strdup(argv[i]);
@@ -72,7 +73,6 @@ void init (int argc, char *argv[])
                                snapshot_path = strdup(argv[i]);
                }
        }
-
        // Set signal handler
        struct sigaction sa = { .sa_handler = signal_handler };
        sigaction(SIGUSR1, &sa, 0);
@@ -80,19 +80,24 @@ void init (int argc, char *argv[])
        sigaction(SIGTERM, &sa, 0);
        sigaction(SIGHUP, &sa, 0);
        signal(SIGCHLD, SIG_IGN);               // don't have to wait() after fork()
-       // 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);
 
+       // BSD is too stupid to support pselect(), therefore we have to use select and hope that we do not
+       // end up in a race condition there
+       // 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));
        memset(&systray, 0, sizeof(Systraybar));
+}
 
+void init_X11()
+{
        server.dsp = XOpenDisplay (NULL);
        if (!server.dsp) {
                fprintf(stderr, "tint2 exit : could not open display.\n");
@@ -118,6 +123,7 @@ void init (int argc, char *argv[])
        gchar *path;
        const gchar * const *data_dirs;
        data_dirs = g_get_system_data_dirs ();
+       int i;
        for (i = 0; data_dirs[i] != NULL; i++)  {
                path = g_build_filename(data_dirs[i], "tint2", "default_icon.png", NULL);
                if (g_file_test (path, G_FILE_TEST_EXISTS))
@@ -609,9 +615,10 @@ void event_configure_notify (Window win)
        GSList *l;
        for (l = systray.list_icons; l ; l = l->next) {
                traywin = (TrayWindow*)l->data;
-               if (traywin->id == win) {
+               if (traywin->tray_id == win) {
                        //printf("move tray %d\n", traywin->x);
                        XMoveResizeWindow(server.dsp, traywin->id, traywin->x, traywin->y, traywin->width, traywin->height);
+                       XResizeWindow(server.dsp, traywin->tray_id, traywin->width, traywin->height);
                        panel_refresh = 1;
                        return;
                }
@@ -677,12 +684,11 @@ int main (int argc, char *argv[])
        int x11_fd, i;
        Panel *panel;
        GSList *it;
-       const struct timespec* timeout;
+       struct timeval* timeout;
 
        init (argc, argv);
-
-       i = 0;
        init_config();
+       i = 0;
        if (config_path)
                i = config_read_file (config_path);
        else
@@ -692,6 +698,8 @@ int main (int argc, char *argv[])
                cleanup();
                exit(1);
        }
+
+       init_X11();
        init_panel();
        cleanup_config();
        if (snapshot_path) {
@@ -700,11 +708,13 @@ int main (int argc, char *argv[])
                exit(0);
        }
 
+       int damage_event, damage_error;
+       XDamageQueryExtension(server.dsp, &damage_event, &damage_error);
        x11_fd = ConnectionNumber(server.dsp);
        XSync(server.dsp, False);
 
-       sigset_t empty_mask;
-       sigemptyset(&empty_mask);
+//     sigset_t empty_mask;
+//     sigemptyset(&empty_mask);
 
        while (1) {
                if (panel_refresh) {
@@ -718,15 +728,19 @@ int main (int argc, char *argv[])
                        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);
+                               if (panel->is_hidden)
+                                       XCopyArea(server.dsp, panel->hidden_pixmap, panel->main_win, server.gc, 0, 0, panel->hidden_width, panel->hidden_height, 0, 0);
+                               else {
+                                       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) {
+                       panel = (Panel*)systray.area.panel;
+                       if (refresh_systray && !panel->is_hidden) {
                                refresh_systray = 0;
                                panel = (Panel*)systray.area.panel;
                                // tint2 doen't draw systray icons. it just redraw background.
@@ -741,19 +755,29 @@ int main (int argc, char *argv[])
                FD_ZERO (&fdset);
                FD_SET (x11_fd, &fdset);
                update_next_timeout();
-               if (next_timeout.tv_sec >= 0 && next_timeout.tv_nsec >= 0)
+               if (next_timeout.tv_sec >= 0 && next_timeout.tv_usec >= 0)
                        timeout = &next_timeout;
                else
                        timeout = 0;
 
                // Wait for X Event or a Timer
-               if (pselect(x11_fd+1, &fdset, 0, 0, timeout, &empty_mask) > 0) {
+               if (select(x11_fd+1, &fdset, 0, 0, timeout) > 0) {
                        while (XPending (server.dsp)) {
                                XNextEvent(server.dsp, &e);
 
+                               panel = get_panel(e.xany.window);
+                               if (panel && panel_autohide) {
+                                       if (e.type == EnterNotify)
+                                               autohide_trigger_show(panel);
+                                       else if (e.type == LeaveNotify)
+                                               autohide_trigger_hide(panel);
+                                       if (panel->is_hidden)
+                                               continue;   // discard further processing of this event because the panel is not visible yet
+                               }
+
                                switch (e.type) {
                                        case ButtonPress:
-                                               tooltip_hide();
+                                               tooltip_hide(0);
                                                event_button_press (&e);
                                                break;
 
@@ -773,7 +797,8 @@ int main (int argc, char *argv[])
                                        }
 
                                        case LeaveNotify:
-                                               tooltip_trigger_hide();
+                                               if (g_tooltip.enabled)
+                                                       tooltip_trigger_hide();
                                                break;
 
                                        case Expose:
@@ -806,7 +831,7 @@ int main (int argc, char *argv[])
                                                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) {
+                                                       if (((TrayWindow*)it->data)->tray_id == e.xany.window) {
                                                                remove_icon((TrayWindow*)it->data);
                                                                break;
                                                        }
@@ -822,6 +847,20 @@ int main (int argc, char *argv[])
                                                        dnd_message(&e.xclient);
                                                }
                                                break;
+
+                                       default:
+                                               if (e.type == XDamageNotify+damage_event) {
+                                                       TrayWindow *traywin;
+                                                       GSList *l;
+                                                       XDamageNotifyEvent* de = (XDamageNotifyEvent*)&e;
+                                                       for (l = systray.list_icons; l ; l = l->next) {
+                                                               traywin = (TrayWindow*)l->data;
+                                                               if ( traywin->id == de->drawable && !de->more ) {
+                                                                       systray_render_icon(traywin);
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
                                }
                        }
                }
This page took 0.02719 seconds and 4 git commands to generate.