X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fpanel.c;h=9b8ff748f0fd96239e997125c4913ba2069ebe8e;hb=ad50533aef71e9697fe78bb636e64079f198f985;hp=e61fe19332eed4135805390f444b2ab9dcd73508;hpb=0063d936c925d1be1eac389f710dfc65460f5520;p=chaz%2Ftint2 diff --git a/src/panel.c b/src/panel.c index e61fe19..9b8ff74 100644 --- a/src/panel.c +++ b/src/panel.c @@ -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); +}