*add* autohide
*fix* issue 182 by using select instead of pselect git-svn-id: http://tint2.googlecode.com/svn/trunk@321 121b4492-b84c-0410-8b4c-0d4edfb3f3cc
This commit is contained in:
229
src/panel.c
229
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user