]> Dogcows Code - chaz/tint2/blobdiff - src/tint.c
*fix* issue 175
[chaz/tint2] / src / tint.c
index fd30d39f2f606e032dfa1b37c5df3970e53d4ff5..01db88cc73ce580f179c522151e7a6ccff0ef741 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>
 
@@ -58,10 +59,10 @@ 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"))     {
+               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);
@@ -88,11 +88,13 @@ void init (int argc, char *argv[])
        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 +103,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 +120,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))
@@ -153,8 +152,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);
 }
 
@@ -241,26 +239,61 @@ void window_action (Task *tsk, int action)
 }
 
 
+int tint2_handles_click(Panel* panel, XButtonEvent* e)
+{
+       Task* task = click_task(panel, e->x, e->y);
+       if (task) {
+               if(   (e->button == 1)
+                        || (e->button == 2 && mouse_middle != 0)
+                        || (e->button == 3 && mouse_right != 0)
+                        || (e->button == 4 && mouse_scroll_up != 0)
+                        || (e->button == 5 && mouse_scroll_down !=0) )
+               {
+                       return 1;
+               }
+               else
+                       return 0;
+       }
+       // no task clicked --> check if taskbar clicked
+       Taskbar *tskbar = click_taskbar(panel, e->x, e->y);
+       if (tskbar && e->button == 1 && panel_mode == MULTI_DESKTOP)
+               return 1;
+       if (click_clock(panel, e->x, e->y)) {
+               if ( (e->button == 1 && clock_lclick_command) || (e->button == 2 && clock_rclick_command) )
+                       return 1;
+               else
+                       return 0;
+       }
+       return 0;
+}
+
+
+void forward_click(XEvent* e)
+{
+       // forward the click to the desktop window (thanks conky)
+       XUngrabPointer(server.dsp, e->xbutton.time);
+       e->xbutton.window = server.root_win;
+       // icewm doesn't open under the mouse.
+       // and xfce doesn't open at all.
+       e->xbutton.x = e->xbutton.x_root;
+       e->xbutton.y = e->xbutton.y_root;
+       //printf("**** %d, %d\n", e->xbutton.x, e->xbutton.y);
+       //XSetInputFocus(server.dsp, e->xbutton.window, RevertToParent, e->xbutton.time);
+       XSendEvent(server.dsp, e->xbutton.window, False, ButtonPressMask, e);
+}
+
+
 void event_button_press (XEvent *e)
 {
        Panel *panel = get_panel(e->xany.window);
        if (!panel) return;
 
-       task_drag = click_task(panel, e->xbutton.x, e->xbutton.y);
 
-       if (wm_menu && !task_drag && !click_clock(panel, e->xbutton.x, e->xbutton.y) && (e->xbutton.button != 1) ) {
-               // forward the click to the desktop window (thanks conky)
-               XUngrabPointer(server.dsp, e->xbutton.time);
-               e->xbutton.window = server.root_win;
-               // icewm doesn't open under the mouse.
-               // and xfce doesn't open at all.
-               e->xbutton.x = e->xbutton.x_root;
-               e->xbutton.y = e->xbutton.y_root;
-               //printf("**** %d, %d\n", e->xbutton.x, e->xbutton.y);
-               //XSetInputFocus(server.dsp, e->xbutton.window, RevertToParent, e->xbutton.time);
-               XSendEvent(server.dsp, e->xbutton.window, False, ButtonPressMask, e);
+       if (wm_menu && !tint2_handles_click(panel, &e->xbutton) ) {
+               forward_click(e);
                return;
        }
+       task_drag = click_task(panel, e->xbutton.x, e->xbutton.y);
 
        XLowerWindow (server.dsp, panel->main_win);
 }
@@ -271,6 +304,12 @@ void event_button_release (XEvent *e)
        Panel *panel = get_panel(e->xany.window);
        if (!panel) return;
 
+       if (wm_menu && !tint2_handles_click(panel, &e->xbutton)) {
+               forward_click(e);
+               task_drag = 0;
+               return;
+       }
+
        int action = TOGGLE_ICONIFY;
        switch (e->xbutton.button) {
                case 2:
@@ -359,6 +398,7 @@ void event_property_notify (XEvent *e)
                                panel1[i].area.resize = 1;
                        }
                        task_refresh_tasklist();
+                       active_task();
                        panel_refresh = 1;
                }
                // Change desktop
@@ -369,8 +409,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;
@@ -379,13 +422,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];
@@ -518,16 +563,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;
                        }
                }
@@ -571,9 +612,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;
                }
@@ -589,9 +631,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;
        }
@@ -635,13 +681,11 @@ int main (int argc, char *argv[])
        int x11_fd, i;
        Panel *panel;
        GSList *it;
-       GSList* timer_iter;
-       struct timer* timer;
+       const struct timespec* timeout;
 
        init (argc, argv);
-
-       i = 0;
        init_config();
+       i = 0;
        if (config_path)
                i = config_read_file (config_path);
        else
@@ -651,6 +695,8 @@ int main (int argc, char *argv[])
                cleanup();
                exit(1);
        }
+
+       init_X11();
        init_panel();
        cleanup_config();
        if (snapshot_path) {
@@ -659,6 +705,8 @@ 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);
 
@@ -669,6 +717,7 @@ int main (int argc, char *argv[])
                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);
@@ -695,33 +744,17 @@ int main (int argc, char *argv[])
                }
 
                // thanks to AngryLlama for the timer
-               // Create a File Description Set containing x11_fd, and every timer_fd
+               // Create a File Description Set containing x11_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;
-               }
+               update_next_timeout();
+               if (next_timeout.tv_sec >= 0 && next_timeout.tv_nsec >= 0)
+                       timeout = &next_timeout;
+               else
+                       timeout = 0;
 
                // Wait for X Event or a Timer
-               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;
-                       }
-
+               if (pselect(x11_fd+1, &fdset, 0, 0, timeout, &empty_mask) > 0) {
                        while (XPending (server.dsp)) {
                                XNextEvent(server.dsp, &e);
 
@@ -780,7 +813,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;
                                                        }
@@ -796,10 +829,17 @@ int main (int argc, char *argv[])
                                                        dnd_message(&e.xclient);
                                                }
                                                break;
+
+                                       default:
+                                               if (e.type == XDamageNotify+damage_event)
+                                                       // TODO: update only the damaged icon, not all of them
+                                                       systray.area.redraw = 1;
                                }
                        }
                }
 
+               callback_timeout_expired();
+
                switch (signal_pending) {
                case SIGUSR1: // reload config file
                        signal_pending = 0;
This page took 0.03409 seconds and 4 git commands to generate.