*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:
Andreas.Fink85
2010-01-05 20:38:49 +00:00
parent 755d6672fe
commit adb784a859
18 changed files with 367 additions and 97 deletions

View 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);
}