]> Dogcows Code - chaz/tint2/blobdiff - src/panel.c
*add* autohide
[chaz/tint2] / src / panel.c
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);
+}
This page took 0.032703 seconds and 4 git commands to generate.