]> Dogcows Code - chaz/tint2/blobdiff - src/tint.c
*add* interval timeouts are aligned to each other
[chaz/tint2] / src / tint.c
index fc471def24f2a9bfcefa87a8b5a9e8d551da914a..5c4ee1693c670dfca81ba8f44d706277fd7375f7 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");
@@ -101,17 +106,13 @@ void init (int argc, char *argv[])
        server_init_atoms ();
        server.screen = DefaultScreen (server.dsp);
        server.root_win = RootWindow(server.dsp, server.screen);
-       server.depth = DefaultDepth (server.dsp, server.screen);
-       server.visual = DefaultVisual (server.dsp, server.screen);
        server.desktop = server_get_current_desktop ();
-       XGCValues  gcv;
-       server.gc = XCreateGC (server.dsp, server.root_win, (unsigned long)0, &gcv);
-
+       server_init_visual();
        XSetErrorHandler ((XErrorHandler) server_catch_error);
 
        imlib_context_set_display (server.dsp);
        imlib_context_set_visual (server.visual);
-       imlib_context_set_colormap (DefaultColormap (server.dsp, server.screen));
+       imlib_context_set_colormap (server.colormap);
 
        /* Catch events */
        XSelectInput (server.dsp, server.root_win, PropertyChangeMask|StructureNotifyMask);
@@ -122,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))
@@ -137,6 +139,7 @@ void init (int argc, char *argv[])
 
 void cleanup()
 {
+       stop_all_timeouts();
        cleanup_systray();
        stop_net();
        cleanup_panel();
@@ -153,8 +156,7 @@ void cleanup()
        if (config_path) g_free(config_path);
        if (snapshot_path) g_free(snapshot_path);
 
-       if (server.monitor) free(server.monitor);
-       XFreeGC(server.dsp, server.gc);
+       cleanup_server();
        XCloseDisplay(server.dsp);
 }
 
@@ -400,6 +402,7 @@ void event_property_notify (XEvent *e)
                                panel1[i].area.resize = 1;
                        }
                        task_refresh_tasklist();
+                       active_task();
                        panel_refresh = 1;
                }
                // Change desktop
@@ -410,8 +413,11 @@ void event_property_notify (XEvent *e)
                                Panel *panel = &panel1[i];
                                if (panel_mode == MULTI_DESKTOP && panel->g_taskbar.use_active) {
                                        // redraw both taskbar
-                                       panel->taskbar[old_desktop].area.is_active = 0;
-                                       panel->taskbar[old_desktop].area.resize = 1;
+                                       if (server.nb_desktop > old_desktop) {
+                                               // can happen if last desktop is deleted and we've been on the last desktop
+                                               panel->taskbar[old_desktop].area.is_active = 0;
+                                               panel->taskbar[old_desktop].area.resize = 1;
+                                       }
                                        panel->taskbar[server.desktop].area.is_active = 1;
                                        panel->taskbar[server.desktop].area.resize = 1;
                                        panel_refresh = 1;
@@ -420,13 +426,15 @@ void event_property_notify (XEvent *e)
                                Taskbar *tskbar;
                                Task *tsk;
                                GSList *l;
-                               tskbar = &panel->taskbar[old_desktop];
-                               for (l = tskbar->area.list; l ; l = l->next) {
-                                       tsk = l->data;
-                                       if (tsk->desktop == ALLDESKTOP) {
-                                               tsk->area.on_screen = 0;
-                                               tskbar->area.resize = 1;
-                                               panel_refresh = 1;
+                               if (server.nb_desktop > old_desktop) {
+                                       tskbar = &panel->taskbar[old_desktop];
+                                       for (l = tskbar->area.list; l ; l = l->next) {
+                                               tsk = l->data;
+                                               if (tsk->desktop == ALLDESKTOP) {
+                                                       tsk->area.on_screen = 0;
+                                                       tskbar->area.resize = 1;
+                                                       panel_refresh = 1;
+                                               }
                                        }
                                }
                                tskbar = &panel->taskbar[server.desktop];
@@ -559,16 +567,12 @@ void event_property_notify (XEvent *e)
                // Window desktop changed
                else if (at == server.atom._NET_WM_DESKTOP) {
                        int desktop = window_get_desktop (win);
-                       int active = tsk->area.is_active;
                        //printf("  Window desktop changed %d, %d\n", tsk->desktop, desktop);
                        // bug in windowmaker : send unecessary 'desktop changed' when focus changed
                        if (desktop != tsk->desktop) {
                                remove_task (tsk);
                                tsk = add_task (win);
-                               if (tsk && active) {
-                                       tsk->area.is_active = 1;
-                                       task_active = tsk;
-                               }
+                               active_task();
                                panel_refresh = 1;
                        }
                }
@@ -612,9 +616,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;
                }
@@ -630,9 +635,13 @@ void event_configure_notify (Window win)
                remove_task (tsk);
                add_task (win);
                if (win == window_get_active ()) {
-                       Task *tsk = task_get_task (win);
-                       tsk->area.is_active = 1;
-                       task_active = tsk;
+                       GSList* task_list = task_get_tasks(win);
+                       while (task_list) {
+                               Task *tsk = task_list->data;
+                               tsk->area.is_active = 1;
+                               task_active = tsk;
+                               task_list = task_list->next;
+                       }
                }
                panel_refresh = 1;
        }
@@ -676,12 +685,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
@@ -691,6 +699,8 @@ int main (int argc, char *argv[])
                cleanup();
                exit(1);
        }
+
+       init_X11();
        init_panel();
        cleanup_config();
        if (snapshot_path) {
@@ -699,16 +709,19 @@ 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) {
                        panel_refresh = 0;
 
+                       // QUESTION: do we need this first refresh_systray, because we check refresh_systray once again later...
                        if (refresh_systray) {
                                panel = (Panel*)systray.area.panel;
                                XSetWindowBackgroundPixmap (server.dsp, panel->main_win, None);
@@ -716,15 +729,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.
@@ -739,19 +756,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;
 
@@ -771,7 +798,8 @@ int main (int argc, char *argv[])
                                        }
 
                                        case LeaveNotify:
-                                               tooltip_trigger_hide();
+                                               if (g_tooltip.enabled)
+                                                       tooltip_trigger_hide();
                                                break;
 
                                        case Expose:
@@ -804,7 +832,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;
                                                        }
@@ -820,6 +848,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.032699 seconds and 4 git commands to generate.