]> Dogcows Code - chaz/tint2/commitdiff
*add* autohide
authorAndreas Fink <andreas.fink85@googlemail.com>
Tue, 5 Jan 2010 20:38:49 +0000 (20:38 +0000)
committerAndreas Fink <andreas.fink85@googlemail.com>
Tue, 5 Jan 2010 20:38:49 +0000 (20:38 +0000)
*fix* issue 182 by using select instead of pselect

18 files changed:
sample/black_single_desktop.tint2rc
sample/default.tint2rc
sample/horizontal_icon_only.tint2rc
sample/rounded_multi_desktop.tint2rc
sample/tint2rc
sample/vertical_icon_only.tint2rc
sample/white_single_desktop.tint2rc
src/battery/battery.c
src/clock/clock.c
src/config.c
src/panel.c
src/panel.h
src/taskbar/task.c
src/tint.c
src/tooltip/tooltip.c
src/tooltip/tooltip.h
src/util/timer.c
src/util/timer.h

index 8eb245cac4e9c8039f86cc4ff826df17cb1f74e4..8aab308f8b39c8741fc17e1a15f0cf37c657d05e 100644 (file)
@@ -100,4 +100,13 @@ mouse_right = close
 mouse_scroll_up = toggle
 mouse_scroll_down = iconify
 
+#---------------------------------------------
+# AUTOHIDE OPTIONS
+#---------------------------------------------
+autohide = 0
+autohide_show_timeout = 0.3
+autohide_hide_timeout = 2
+autohide_height = 4
+strut_policy = minimum
+
 
index 3fbd73cf5fc38f12b92bd7fc597782f642d4d7f1..0def646aa5770f73fa893f6b012f134566b155f3 100644 (file)
@@ -127,3 +127,12 @@ mouse_right = close
 mouse_scroll_up = toggle
 mouse_scroll_down = iconify
 
+#---------------------------------------------
+# AUTOHIDE OPTIONS
+#---------------------------------------------
+autohide = 0
+autohide_show_timeout = 0.3
+autohide_hide_timeout = 2
+autohide_height = 4
+strut_policy = minimum
+
index a8ca31338f9dc1cc2d220987c14815ccfcf11a89..39e48121bb4d2e42ed01681622a394082f62f485 100644 (file)
@@ -125,3 +125,12 @@ mouse_right = close
 mouse_scroll_up = toggle
 mouse_scroll_down = iconify
 
+#---------------------------------------------
+# AUTOHIDE OPTIONS
+#---------------------------------------------
+autohide = 0
+autohide_show_timeout = 0.3
+autohide_hide_timeout = 2
+autohide_height = 4
+strut_policy = minimum
+
index 50a78d05471449b94da3300eb7109b302bc91e5e..c181a05946c069e7e1cb84f5606d05cf2c5ece60 100644 (file)
@@ -105,3 +105,12 @@ mouse_right = close
 mouse_scroll_up = toggle
 mouse_scroll_down = iconify
 
+#---------------------------------------------
+# AUTOHIDE OPTIONS
+#---------------------------------------------
+autohide = 0
+autohide_show_timeout = 0.3
+autohide_hide_timeout = 2
+autohide_height = 4
+strut_policy = minimum
+
index 124cca0b3778120676a610d72080101618d7bc8a..ff991e7578180afcb8cfa46cbedd4a5ce140fb4d 100644 (file)
@@ -115,3 +115,12 @@ mouse_right = close
 mouse_scroll_up = toggle
 mouse_scroll_down = iconify
 
+#---------------------------------------------
+# AUTOHIDE OPTIONS
+#---------------------------------------------
+autohide = 0
+autohide_show_timeout = 0.3
+autohide_hide_timeout = 2
+autohide_height = 4
+strut_policy = minimum
+
index 1c8342b98b72f0aaa0d4a0d6cf059e463c0bc2b0..6376b1574649624ad79de80ce05a861a125bce8d 100644 (file)
@@ -114,3 +114,13 @@ mouse_middle = none
 mouse_right = close
 mouse_scroll_up = toggle
 mouse_scroll_down = iconify
+
+#---------------------------------------------
+# AUTOHIDE OPTIONS
+#---------------------------------------------
+autohide = 0
+autohide_show_timeout = 0.3
+autohide_hide_timeout = 2
+autohide_height = 4
+strut_policy = minimum
+
index 4d62cf9da9b1c77d4c7c6aa9208e06929842d5fe..a6cd9641f3e10edaf4360cb7d7cfe4d27a8bb337 100644 (file)
@@ -122,3 +122,12 @@ mouse_right = close
 mouse_scroll_up = toggle
 mouse_scroll_down = iconify
 
+#---------------------------------------------
+# AUTOHIDE OPTIONS
+#---------------------------------------------
+autohide = 0
+autohide_show_timeout = 0.3
+autohide_hide_timeout = 2
+autohide_height = 4
+strut_policy = minimum
+
index 4db696e4d73ea977e723133024bb66394518c610..99e5aee84d7de7247e2848d7b76441e220a13ff4 100644 (file)
@@ -50,7 +50,7 @@ char *path_energy_full=0;
 char *path_current_now=0;
 char *path_status=0;
 
-void update_batterys()
+void update_batterys(void* arg)
 {
        int i;
        update_battery();
@@ -133,7 +133,7 @@ void init_battery()
        g_free(battery_dir);
 
        if (battery_enabled && battery_timeout==0)
-               battery_timeout = add_timeout(10, 5000, update_batterys);
+               battery_timeout = add_timeout(10, 5000, update_batterys, 0);
 }
 
 
index 115ba9fe1bf5a4794984f1db33e0863147249142..3eef5a427b61b11ea919dc3e000219090ca97b0f 100644 (file)
@@ -53,7 +53,7 @@ int clock_enabled;
 static const struct timeout* clock_timeout=0;
 
 
-void update_clocks()
+void update_clocks(void* arg)
 {
        gettimeofday(&time_clock, 0);
        int i;
@@ -87,9 +87,9 @@ void init_clock()
 {
        if(time1_format && clock_timeout==0) {
                if (strchr(time1_format, 'S') || strchr(time1_format, 'T') || strchr(time1_format, 'r'))
-                       clock_timeout = add_timeout(10, 1000, update_clocks);
+                       clock_timeout = add_timeout(10, 1000, update_clocks, 0);
                else
-                       clock_timeout = add_timeout(10, 60000, update_clocks);
+                       clock_timeout = add_timeout(10, 60000, update_clocks, 0);
        }
 }
 
@@ -282,9 +282,9 @@ void clock_action(int button)
                pid = fork();
                if (pid == 0) {
                        // change for the fork the signal mask
-                       sigset_t sigset;
-                       sigprocmask(SIG_SETMASK, &sigset, 0);
-                       sigprocmask(SIG_UNBLOCK, &sigset, 0);
+//                     sigset_t sigset;
+//                     sigprocmask(SIG_SETMASK, &sigset, 0);
+//                     sigprocmask(SIG_UNBLOCK, &sigset, 0);
                        execl("/bin/sh", "/bin/sh", "-c", command, NULL);
                        _exit(0);
                }
index 62a8c585e6aaab32fbb350dec0cbe242be5d8664..814bc5d2ff3fcba5f03d24d43a8f9da737edeee7 100644 (file)
@@ -607,6 +607,22 @@ void add_entry (char *key, char *value)
        else if (strcmp (key, "mouse_scroll_down") == 0)
                get_action (value, &mouse_scroll_down);
 
+       /* autohide options */
+       else if (strcmp(key, "autohide") == 0)
+               panel_autohide = atoi(value);
+       else if (strcmp(key, "autohide_show_timeout") == 0)
+               panel_autohide_show_timeout = 1000*atof(value);
+       else if (strcmp(key, "autohide_hide_timeout") == 0)
+               panel_autohide_hide_timeout = 1000*atof(value);
+       else if (strcmp(key, "strut_policy") == 0) {
+               if (strcmp(value, "follow_size") == 0)
+                       panel_strut_policy = STRUT_FOLLOW_SIZE;
+               else
+                       panel_strut_policy = STRUT_MINIMUM;
+       }
+       else if (strcmp(key, "autohide_height") == 0)
+               panel_autohide_height = atoi(value);
+
 
        /* Read tint-0.6 config for backward compatibility */
        else if (strcmp (key, "panel_mode") == 0) {
index e61fe19332eed4135805390f444b2ab9dcd73508..9b8ff748f0fd96239e997125c4913ba2069ebe8e 100644 (file)
@@ -51,6 +51,12 @@ int panel_position;
 int panel_horizontal;
 int panel_refresh;
 
+int panel_autohide = 0;
+int panel_autohide_show_timeout = 0;
+int panel_autohide_hide_timeout = 0;
+int panel_autohide_height = 5;  // for vertical panels this is of course the width
+int panel_strut_policy = STRUT_MINIMUM;
+
 Task *task_active;
 Task *task_drag;
 int  max_tick_urgent;
@@ -64,6 +70,9 @@ int  nb_panel = 0;
 Imlib_Image default_icon = NULL;
 
 
+void autohide_hide(void* p);
+void autohide_show(void* p);
+
 
 void init_panel()
 {
@@ -152,6 +161,8 @@ void init_panel()
                        long event_mask = ExposureMask|ButtonPressMask|ButtonReleaseMask;
                        if (g_tooltip.enabled)
                                event_mask |= PointerMotionMask|LeaveWindowMask;
+                       if (panel_autohide)
+                               event_mask |= LeaveWindowMask|EnterWindowMask;
                        XSetWindowAttributes att = { .event_mask=event_mask, .colormap=server.colormap, .background_pixel=0, .border_pixel=0 };
                        unsigned long mask = CWEventMask|CWColormap|CWBackPixel|CWBorderPixel;
                        p->main_win = XCreateWindow(server.dsp, server.root_win, p->posx, p->posy, p->area.width, p->area.height, 0, server.depth, InputOutput, server.visual, mask, &att);
@@ -172,6 +183,9 @@ void init_panel()
                        // map new panel
                        XMapWindow (server.dsp, p->main_win);
                }
+
+               if (panel_autohide)
+                       add_timeout(panel_autohide_hide_timeout, 0, autohide_hide, p);
        }
 
        panel1 = new_panel;
@@ -234,6 +248,18 @@ void init_panel_size_and_position(Panel *panel)
                        panel->posy = server.monitor[panel->monitor].y + ((server.monitor[panel->monitor].height - panel->area.height) / 2);
                }
        }
+
+       if (panel_autohide) {
+               int diff = (panel_horizontal ? panel->area.height : panel->area.width) - panel_autohide_height;
+               if (panel_horizontal) {
+                       panel->hidden_width = panel->area.width;
+                       panel->hidden_height = panel->area.height - diff;
+               }
+               else {
+                       panel->hidden_width = panel->area.width - diff;
+                       panel->hidden_height = panel->area.height;
+               }
+       }
        // printf("panel : posx %d, posy %d, width %d, height %d\n", panel->posx, panel->posy, panel->area.width, panel->area.height);
 }
 
@@ -258,6 +284,9 @@ void cleanup_panel()
                        XFreePixmap(server.dsp, p->temp_pmap);
                        p->temp_pmap = 0;
                }
+               if (p->hidden_pixmap)
+                       XFreePixmap(server.dsp, p->hidden_pixmap);
+               p->hidden_pixmap = 0;
                if (p->main_win) {
                        XDestroyWindow(server.dsp, p->main_win);
                        p->main_win = 0;
@@ -378,6 +407,54 @@ void visible_object()
        panel_refresh = 1;
 }
 
+void update_strut(Panel* p)
+{
+       // Reserved space
+       unsigned int d1, screen_width, screen_height;
+       Window d2;
+       int d3;
+       XGetGeometry(server.dsp, server.root_win, &d2, &d3, &d3, &screen_width, &screen_height, &d1, &d1);
+       Monitor monitor = server.monitor[p->monitor];
+       long   struts [12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+       if (panel_horizontal) {
+               int height = p->area.height + p->marginy;
+               if (panel_autohide && (panel_strut_policy == STRUT_MINIMUM || (panel_strut_policy == STRUT_FOLLOW_SIZE && p->is_hidden)) )
+                       height = p->hidden_height;
+               if (panel_position & TOP) {
+                       struts[2] = height + monitor.y;
+                       struts[8] = p->posx;
+                       // p->area.width - 1 allowed full screen on monitor 2
+                       struts[9] = p->posx + p->area.width - 1;
+               }
+               else {
+                       struts[3] = height + screen_height - monitor.y - monitor.height;
+                       struts[10] = p->posx;
+                       // p->area.width - 1 allowed full screen on monitor 2
+                       struts[11] = p->posx + p->area.width - 1;
+               }
+       }
+       else {
+               int width = p->area.width + p->marginx;
+               if (panel_autohide && (panel_strut_policy == STRUT_MINIMUM || (panel_strut_policy == STRUT_FOLLOW_SIZE && p->is_hidden)) )
+                       width = p->hidden_width;
+               if (panel_position & LEFT) {
+                       struts[0] = width + monitor.x;
+                       struts[4] = p->posy;
+                       // p->area.width - 1 allowed full screen on monitor 2
+                       struts[5] = p->posy + p->area.height - 1;
+               }
+               else {
+                       struts[1] = width + screen_width - monitor.x - monitor.width;
+                       struts[6] = p->posy;
+                       // p->area.width - 1 allowed full screen on monitor 2
+                       struts[7] = p->posy + p->area.height - 1;
+               }
+       }
+       // Old specification : fluxbox need _NET_WM_STRUT.
+       XChangeProperty (server.dsp, p->main_win, server.atom._NET_WM_STRUT, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &struts, 4);
+       XChangeProperty (server.dsp, p->main_win, server.atom._NET_WM_STRUT_PARTIAL, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &struts, 12);
+}
+
 
 void set_panel_properties(Panel *p)
 {
@@ -402,7 +479,8 @@ void set_panel_properties(Panel *p)
        state[1] = server.atom._NET_WM_STATE_SKIP_TASKBAR;
        state[2] = server.atom._NET_WM_STATE_STICKY;
        state[3] = panel_layer == BOTTOM_LAYER ? server.atom._NET_WM_STATE_BELOW : server.atom._NET_WM_STATE_ABOVE;
-       XChangeProperty (server.dsp, p->main_win, server.atom._NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *) state, panel_layer == NORMAL_LAYER ? 3 : 4);
+       int nb_atoms = panel_layer == NORMAL_LAYER ? 3 : 4;
+       XChangeProperty (server.dsp, p->main_win, server.atom._NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *) state, nb_atoms);
 
        // Unfocusable
        XWMHints wmhints;
@@ -425,51 +503,18 @@ void set_panel_properties(Panel *p)
        int version=5;
        XChangeProperty(server.dsp, p->main_win, server.atom.XdndAware, XA_ATOM, 32, PropModeReplace, (unsigned char*)&version, 1);
 
-       // Reserved space
-       unsigned int d1, screen_width, screen_height;
-       Window d2;
-       int d3;
-       XGetGeometry(server.dsp, server.root_win, &d2, &d3, &d3, &screen_width, &screen_height, &d1, &d1);
-       Monitor monitor = server.monitor[p->monitor];
-       long   struts [12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-       if (panel_horizontal) {
-               if (panel_position & TOP) {
-                       struts[2] = p->area.height + p->marginy + monitor.y;
-                       struts[8] = p->posx;
-                       // p->area.width - 1 allowed full screen on monitor 2
-                       struts[9] = p->posx + p->area.width - 1;
-               }
-               else {
-                       struts[3] = p->area.height + p->marginy + screen_height - monitor.y - monitor.height;
-                       struts[10] = p->posx;
-                       // p->area.width - 1 allowed full screen on monitor 2
-                       struts[11] = p->posx + p->area.width - 1;
-               }
-       }
-       else {
-               if (panel_position & LEFT) {
-                       struts[0] = p->area.width + p->marginx + monitor.x;
-                       struts[4] = p->posy;
-                       // p->area.width - 1 allowed full screen on monitor 2
-                       struts[5] = p->posy + p->area.height - 1;
-               }
-               else {
-                       struts[1] = p->area.width + p->marginx + screen_width - monitor.x - monitor.width;
-                       struts[6] = p->posy;
-                       // p->area.width - 1 allowed full screen on monitor 2
-                       struts[7] = p->posy + p->area.height - 1;
-               }
-       }
-       // Old specification : fluxbox need _NET_WM_STRUT.
-       XChangeProperty (server.dsp, p->main_win, server.atom._NET_WM_STRUT, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &struts, 4);
-       XChangeProperty (server.dsp, p->main_win, server.atom._NET_WM_STRUT_PARTIAL, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &struts, 12);
+       update_strut(p);
 
        // Fixed position and non-resizable window
        // Allow panel move and resize when tint2 reload config file
+       int minwidth = panel_autohide ? p->hidden_width : p->area.width;
+       int minheight = panel_autohide ? p->hidden_height : p->area.height;
        XSizeHints size_hints;
        size_hints.flags = PPosition|PMinSize|PMaxSize;
-       size_hints.min_width = size_hints.max_width = p->area.width;
-       size_hints.min_height = size_hints.max_height = p->area.height;
+       size_hints.min_width = minwidth;
+       size_hints.max_width = p->area.width;
+       size_hints.min_height = minheight;
+       size_hints.max_height = p->area.height;
        XSetWMNormalHints(server.dsp, p->main_win, &size_hints);
 
        // Set WM_CLASS
@@ -504,12 +549,21 @@ void set_panel_background(Panel *p)
        cairo_t *c;
        cs = cairo_xlib_surface_create (server.dsp, p->area.pix.pmap, server.visual, p->area.width, p->area.height);
        c = cairo_create (cs);
-
        draw_background(&p->area, c, 0);
-
        cairo_destroy (c);
        cairo_surface_destroy (cs);
 
+       if (panel_autohide) {
+               if (p->hidden_pixmap) XFreePixmap(server.dsp, p->hidden_pixmap);
+               p->hidden_pixmap = XCreatePixmap(server.dsp, server.root_win, p->hidden_width, p->hidden_height, server.depth);
+               int xoff=0, yoff=0;
+               if (panel_horizontal && panel_position & BOTTOM)
+                       yoff = p->area.height-p->hidden_height;
+               else if (!panel_horizontal && panel_position & RIGHT)
+                       xoff = p->area.width-p->hidden_width;
+               XCopyArea(server.dsp, p->area.pix.pmap, p->hidden_pixmap, server.gc, xoff, yoff, p->hidden_width, p->hidden_height, 0, 0);
+       }
+
        // redraw panel's object
        GSList *l0;
        Area *a;
@@ -637,3 +691,92 @@ Area* click_area(Panel *panel, int x, int y)
        } while (new_result != result);
        return result;
 }
+
+
+void stop_autohide_timeout(Panel* p)
+{
+       if (p->autohide_timeout) {
+               stop_timeout(p->autohide_timeout);
+               p->autohide_timeout = 0;
+       }
+}
+
+
+void autohide_show(void* p)
+{
+       Panel* panel = p;
+       stop_autohide_timeout(panel);
+       panel->is_hidden = 0;
+       if (panel_strut_policy == STRUT_FOLLOW_SIZE)
+               update_strut(p);
+
+       XMapSubwindows(server.dsp, panel->main_win);
+       if (panel_horizontal) {
+               if (panel_position & TOP)
+                       XResizeWindow(server.dsp, panel->main_win, panel->area.width, panel->area.height);
+               else
+                       XMoveResizeWindow(server.dsp, panel->main_win, panel->posx, panel->posy, panel->area.width, panel->area.height);
+       }
+       else {
+               if (panel_position & LEFT)
+                       XResizeWindow(server.dsp, panel->main_win, panel->area.width, panel->area.height);
+               else
+                       XMoveResizeWindow(server.dsp, panel->main_win, panel->posx, panel->posy, panel->area.width, panel->area.height);
+       }
+       panel_refresh = 1;
+}
+
+
+void autohide_hide(void* p)
+{
+       Panel* panel = p;
+       stop_autohide_timeout(panel);
+       panel->is_hidden = 1;
+       if (panel_strut_policy == STRUT_FOLLOW_SIZE)
+               update_strut(p);
+
+       XUnmapSubwindows(server.dsp, panel->main_win);
+       int diff = (panel_horizontal ? panel->area.height : panel->area.width) - panel_autohide_height;
+       if (panel_horizontal) {
+               if (panel_position & TOP)
+                       XResizeWindow(server.dsp, panel->main_win, panel->hidden_width, panel->hidden_height);
+               else
+                       XMoveResizeWindow(server.dsp, panel->main_win, panel->posx, panel->posy+diff, panel->hidden_width, panel->hidden_height);
+       }
+       else {
+               if (panel_position & LEFT)
+                       XResizeWindow(server.dsp, panel->main_win, panel->hidden_width, panel->hidden_height);
+               else
+                       XMoveResizeWindow(server.dsp, panel->main_win, panel->posx+diff, panel->posy, panel->hidden_width, panel->hidden_height);
+       }
+       panel_refresh = 1;
+}
+
+
+void autohide_trigger_show(Panel* p)
+{
+       if (!p)
+               return;
+       if (p->autohide_timeout)
+               change_timeout(p->autohide_timeout, panel_autohide_show_timeout, 0, autohide_show, p);
+       else
+               p->autohide_timeout = add_timeout(panel_autohide_show_timeout, 0, autohide_show, p);
+}
+
+
+void autohide_trigger_hide(Panel* p)
+{
+       if (!p)
+               return;
+
+       Window root, child;
+       int xr, yr, xw, yw;
+       unsigned int mask;
+       if (XQueryPointer(server.dsp, p->main_win, &root, &child, &xr, &yr, &xw, &yw, &mask))
+               if (child) return;  // mouse over one of the system tray icons
+
+       if (p->autohide_timeout)
+               change_timeout(p->autohide_timeout, panel_autohide_hide_timeout, 0, autohide_hide, p);
+       else
+               p->autohide_timeout = add_timeout(panel_autohide_hide_timeout, 0, autohide_hide, p);
+}
index 52665cd19f09003eee62639abed69b32e3c4d07d..a53bc458bb7add6ac33d993a2c1ab55be10b497d 100644 (file)
@@ -50,6 +50,14 @@ extern int panel_horizontal;
 
 extern int panel_refresh;
 
+//panel autohide
+enum { STRUT_MINIMUM, STRUT_FOLLOW_SIZE };
+extern int panel_autohide;
+extern int panel_autohide_show_timeout;
+extern int panel_autohide_hide_timeout;
+extern int panel_autohide_height;  // for vertical panels this is of course the width
+extern int panel_strut_policy;
+
 extern Task *task_active;
 extern Task *task_drag;
 extern int  max_tick_urgent;
@@ -97,6 +105,10 @@ typedef struct {
 #ifdef ENABLE_BATTERY
        Battery battery;
 #endif
+       int is_hidden;
+       int hidden_width, hidden_height;
+       Pixmap hidden_pixmap;
+       const struct timeout* autohide_timeout;
 } Panel;
 
 
@@ -127,4 +139,7 @@ int click_padding(Panel *panel, int x, int y);
 int click_clock(Panel *panel, int x, int y);
 Area* click_area(Panel *panel, int x, int y);
 
+void autohide_trigger_show();
+void autohide_trigger_hide();
+
 #endif
index 98c943aa0ddcdc6f13f606dcaea4f364acc8c2c1..98590431da7a01a455f8c50cc9275f63140738c0 100644 (file)
@@ -469,7 +469,7 @@ void active_task()
 }
 
 
-void blink_urgent()
+void blink_urgent(void* arg)
 {
        GSList* urgent_task = urgent_list;
        while (urgent_task) {
@@ -510,7 +510,7 @@ void add_urgent(Task *tsk)
        urgent_list = g_slist_concat(urgent_add, urgent_list);
 
        if (urgent_timeout == 0)
-               urgent_timeout = add_timeout(10, 1000, blink_urgent);
+               urgent_timeout = add_timeout(10, 1000, blink_urgent, 0);
 }
 
 
index 01db88cc73ce580f179c522151e7a6ccff0ef741..7c167d8ef3d9f9f8ed3c7ae3c95863c1c27d8b54 100644 (file)
@@ -80,13 +80,16 @@ 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()
+
+       // 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);
+//     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));
@@ -681,7 +684,7 @@ int main (int argc, char *argv[])
        int x11_fd, i;
        Panel *panel;
        GSList *it;
-       const struct timespec* timeout;
+       struct timeval* timeout;
 
        init (argc, argv);
        init_config();
@@ -710,8 +713,8 @@ int main (int argc, char *argv[])
        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) {
@@ -725,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.
@@ -748,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;
 
@@ -780,7 +797,8 @@ int main (int argc, char *argv[])
                                        }
 
                                        case LeaveNotify:
-                                               tooltip_trigger_hide();
+                                               if (g_tooltip.enabled)
+                                                       tooltip_trigger_hide();
                                                break;
 
                                        case Expose:
index 6c3662542ffe436b86ef2aba933bc2aa3d33cd76..3eadda417c86aadf55a1955aeae9038f1ed04d8a 100644 (file)
@@ -74,7 +74,7 @@ void init_tooltip()
 void cleanup_tooltip()
 {
        stop_tooltip_timeout();
-       tooltip_hide();
+       tooltip_hide(0);
        g_tooltip.enabled = False;
        tooltip_copy_text(0);
        if (g_tooltip.window) {
@@ -104,7 +104,7 @@ void tooltip_trigger_show(Area* area, Panel* p, int x_root, int y_root)
 }
 
 
-void tooltip_show()
+void tooltip_show(void* arg)
 {
   int mx, my;
   Window w;
@@ -200,7 +200,7 @@ void tooltip_adjust_geometry()
 void tooltip_update()
 {
        if (!g_tooltip.tooltip_text) {
-               tooltip_hide();
+               tooltip_hide(0);
                return;
        }
 
@@ -265,7 +265,7 @@ void tooltip_trigger_hide(Tooltip* tooltip)
 }
 
 
-void tooltip_hide()
+void tooltip_hide(void* arg)
 {
        stop_tooltip_timeout();
        if (g_tooltip.mapped) {
@@ -279,18 +279,18 @@ void tooltip_hide()
 void start_show_timeout()
 {
        if (g_tooltip.timeout)
-               change_timeout(g_tooltip.timeout, g_tooltip.show_timeout_msec, 0, tooltip_show);
+               change_timeout(g_tooltip.timeout, g_tooltip.show_timeout_msec, 0, tooltip_show, 0);
        else
-               g_tooltip.timeout = add_timeout(g_tooltip.show_timeout_msec, 0, tooltip_show);
+               g_tooltip.timeout = add_timeout(g_tooltip.show_timeout_msec, 0, tooltip_show, 0);
 }
 
 
 void start_hide_timeout()
 {
        if (g_tooltip.timeout)
-               change_timeout(g_tooltip.timeout, g_tooltip.hide_timeout_msec, 0, tooltip_hide);
+               change_timeout(g_tooltip.timeout, g_tooltip.hide_timeout_msec, 0, tooltip_hide, 0);
        else
-               g_tooltip.timeout = add_timeout(g_tooltip.hide_timeout_msec, 0, tooltip_hide);
+               g_tooltip.timeout = add_timeout(g_tooltip.hide_timeout_msec, 0, tooltip_hide, 0);
 }
 
 
index 0559e4d4c52497e8b5e42e43ae64386ff2200c03..0aa965f2635232f06d29e4ddfc142f410a7b17d2 100644 (file)
@@ -46,9 +46,9 @@ extern Tooltip g_tooltip;
 void init_tooltip();
 void cleanup_tooltip();
 void tooltip_trigger_show(Area* area, Panel* p, int x, int y);
-void tooltip_show();
+void tooltip_show(void* /*arg*/);
 void tooltip_update();
 void tooltip_trigger_hide();
-void tooltip_hide();
+void tooltip_hide(void* /*arg*/);
 
 #endif // TOOLTIP_H
index 8ffadc88d829b9d05453c7bea2c7efd615ec96bd..6bb757837861e187d7007466bd4584b4f03789c8 100644 (file)
@@ -21,9 +21,9 @@
 #include "timer.h"
 
 GSList* timeout_list = 0;
-struct timespec next_timeout;
+struct timeval next_timeout;
 
-void add_timeout_intern(int value_msec, int interval_msec, void(*_callback)(), struct timeout* t);
+void add_timeout_intern(int value_msec, int interval_msec, void(*_callback)(void*), void* arg, struct timeout* t);
 gint compare_timeouts(gconstpointer t1, gconstpointer t2);
 gint compare_timespecs(const struct timespec* t1, const struct timespec* t2);
 int timespec_subtract(struct timespec* result, struct timespec* x, struct timespec* y);
@@ -36,20 +36,27 @@ int timespec_subtract(struct timespec* result, struct timespec* x, struct timesp
        * is in the past to the current time.
        * As time measurement we use clock_gettime(CLOCK_MONOTONIC) because this refers to a timer, which
        * reference point lies somewhere in the past and cannot be changed, but just queried.
+       * If a single shot timer is installed it will be automatically deleted. I.e. the returned value
+       * of add_timeout will not be valid anymore. You do not need to call stop_timeout for these timeouts,
+       * however it's save to call it.
 **/
 
-const struct timeout* add_timeout(int value_msec, int interval_msec, void (*_callback)())
+const struct timeout* add_timeout(int value_msec, int interval_msec, void (*_callback)(void*), void* arg)
 {
        struct timeout* t = malloc(sizeof(struct timeout));
-       add_timeout_intern(value_msec, interval_msec, _callback, t);
+       add_timeout_intern(value_msec, interval_msec, _callback, arg, t);
        return t;
 }
 
 
-void change_timeout(const struct timeout *t, int value_msec, int interval_msec, void(*_callback)())
+void change_timeout(const struct timeout *t, int value_msec, int interval_msec, void(*_callback)(), void* arg)
 {
-       timeout_list = g_slist_remove(timeout_list, t);
-       add_timeout_intern(value_msec, interval_msec, _callback, (struct timeout*)t);
+       if ( g_slist_find(timeout_list, t) == 0 )
+               printf("timeout already deleted...");
+       else {
+               timeout_list = g_slist_remove(timeout_list, t);
+               add_timeout_intern(value_msec, interval_msec, _callback, arg, (struct timeout*)t);
+       }
 }
 
 
@@ -58,10 +65,15 @@ void update_next_timeout()
        if (timeout_list) {
                struct timeout* t = timeout_list->data;
                struct timespec cur_time;
+               struct timespec next_timeout2 = { .tv_sec=next_timeout.tv_sec, .tv_nsec=next_timeout.tv_usec*1000 };
                clock_gettime(CLOCK_MONOTONIC, &cur_time);
-               if (timespec_subtract(&next_timeout, &t->timeout_expires, &cur_time)) {
+               if (timespec_subtract(&next_timeout2, &t->timeout_expires, &cur_time)) {
                        next_timeout.tv_sec = 0;
-                       next_timeout.tv_nsec = 0;
+                       next_timeout.tv_usec = 0;
+               }
+               else {
+                       next_timeout.tv_sec = next_timeout2.tv_sec;
+                       next_timeout.tv_usec = next_timeout2.tv_nsec/1000;
                }
        }
        else
@@ -78,12 +90,12 @@ void callback_timeout_expired()
                t = timeout_list->data;
                if (compare_timespecs(&t->timeout_expires, &cur_time) <= 0) {
                        // it's time for the callback function
-                       t->_callback();
+                       t->_callback(t->arg);
                        if (g_slist_find(timeout_list, t)) {
                                // if _callback() calls stop_timeout(t) the timeout 't' was freed and is not in the timeout_list
                                timeout_list = g_slist_remove(timeout_list, t);
                                if (t->interval_msec > 0)
-                                       add_timeout_intern(t->interval_msec, t->interval_msec, t->_callback, t);
+                                       add_timeout_intern(t->interval_msec, t->interval_msec, t->_callback, t->arg, t);
                                else
                                        free(t);
                        }
@@ -113,10 +125,11 @@ void stop_all_timeouts()
 }
 
 
-void add_timeout_intern(int value_msec, int interval_msec, void(*_callback)(), struct timeout *t)
+void add_timeout_intern(int value_msec, int interval_msec, void(*_callback)(), void* arg, struct timeout *t)
 {
        t->interval_msec = interval_msec;
        t->_callback = _callback;
+       t->arg = arg;
        struct timespec expire;
        clock_gettime(CLOCK_MONOTONIC, &expire);
        expire.tv_sec += value_msec / 1000;
index 23aea08d53b32406de5d6320f84bd70d90a495c1..b8169180dffe81aef50a89f671f7c53e1daae462 100644 (file)
 #include <glib.h>
 
 extern GSList* timeout_list;
-extern struct timespec next_timeout;
+extern struct timeval next_timeout;
 
 
 struct timeout {
        int interval_msec;
        struct timespec timeout_expires;
        void (*_callback)();
+       void* arg;
 };
 
 
@@ -36,9 +37,9 @@ struct timeout {
 /** installs a timeout with the first timeout of 'value_msec' and then a periodic timeout with
        * 'interval_msec'. '_callback' is the callback function when the timer reaches the timeout.
        * returns a pointer to the timeout, which is needed for stopping it again **/
-const struct timeout* add_timeout(int value_msec, int interval_msec, void (*_callback)());
+const struct timeout* add_timeout(int value_msec, int interval_msec, void (*_callback)(void*), void* arg);
 
-void change_timeout(const struct timeout* t, int value_msec, int interval_msec, void (*_callback)());
+void change_timeout(const struct timeout* t, int value_msec, int interval_msec, void (*_callback)(void*), void* arg);
 
 /** stops the timeout 't' **/
 void stop_timeout(const struct timeout* t);
This page took 0.056088 seconds and 4 git commands to generate.