*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

@ -100,4 +100,13 @@ mouse_right = close
mouse_scroll_up = toggle mouse_scroll_up = toggle
mouse_scroll_down = iconify mouse_scroll_down = iconify
#---------------------------------------------
# AUTOHIDE OPTIONS
#---------------------------------------------
autohide = 0
autohide_show_timeout = 0.3
autohide_hide_timeout = 2
autohide_height = 4
strut_policy = minimum

View file

@ -127,3 +127,12 @@ mouse_right = close
mouse_scroll_up = toggle mouse_scroll_up = toggle
mouse_scroll_down = iconify mouse_scroll_down = iconify
#---------------------------------------------
# AUTOHIDE OPTIONS
#---------------------------------------------
autohide = 0
autohide_show_timeout = 0.3
autohide_hide_timeout = 2
autohide_height = 4
strut_policy = minimum

View file

@ -125,3 +125,12 @@ mouse_right = close
mouse_scroll_up = toggle mouse_scroll_up = toggle
mouse_scroll_down = iconify mouse_scroll_down = iconify
#---------------------------------------------
# AUTOHIDE OPTIONS
#---------------------------------------------
autohide = 0
autohide_show_timeout = 0.3
autohide_hide_timeout = 2
autohide_height = 4
strut_policy = minimum

View file

@ -105,3 +105,12 @@ mouse_right = close
mouse_scroll_up = toggle mouse_scroll_up = toggle
mouse_scroll_down = iconify mouse_scroll_down = iconify
#---------------------------------------------
# AUTOHIDE OPTIONS
#---------------------------------------------
autohide = 0
autohide_show_timeout = 0.3
autohide_hide_timeout = 2
autohide_height = 4
strut_policy = minimum

View file

@ -115,3 +115,12 @@ mouse_right = close
mouse_scroll_up = toggle mouse_scroll_up = toggle
mouse_scroll_down = iconify mouse_scroll_down = iconify
#---------------------------------------------
# AUTOHIDE OPTIONS
#---------------------------------------------
autohide = 0
autohide_show_timeout = 0.3
autohide_hide_timeout = 2
autohide_height = 4
strut_policy = minimum

View file

@ -114,3 +114,13 @@ mouse_middle = none
mouse_right = close mouse_right = close
mouse_scroll_up = toggle mouse_scroll_up = toggle
mouse_scroll_down = iconify mouse_scroll_down = iconify
#---------------------------------------------
# AUTOHIDE OPTIONS
#---------------------------------------------
autohide = 0
autohide_show_timeout = 0.3
autohide_hide_timeout = 2
autohide_height = 4
strut_policy = minimum

View file

@ -122,3 +122,12 @@ mouse_right = close
mouse_scroll_up = toggle mouse_scroll_up = toggle
mouse_scroll_down = iconify mouse_scroll_down = iconify
#---------------------------------------------
# AUTOHIDE OPTIONS
#---------------------------------------------
autohide = 0
autohide_show_timeout = 0.3
autohide_hide_timeout = 2
autohide_height = 4
strut_policy = minimum

View file

@ -50,7 +50,7 @@ char *path_energy_full=0;
char *path_current_now=0; char *path_current_now=0;
char *path_status=0; char *path_status=0;
void update_batterys() void update_batterys(void* arg)
{ {
int i; int i;
update_battery(); update_battery();
@ -133,7 +133,7 @@ void init_battery()
g_free(battery_dir); g_free(battery_dir);
if (battery_enabled && battery_timeout==0) if (battery_enabled && battery_timeout==0)
battery_timeout = add_timeout(10, 5000, update_batterys); battery_timeout = add_timeout(10, 5000, update_batterys, 0);
} }

View file

@ -53,7 +53,7 @@ int clock_enabled;
static const struct timeout* clock_timeout=0; static const struct timeout* clock_timeout=0;
void update_clocks() void update_clocks(void* arg)
{ {
gettimeofday(&time_clock, 0); gettimeofday(&time_clock, 0);
int i; int i;
@ -87,9 +87,9 @@ void init_clock()
{ {
if(time1_format && clock_timeout==0) { if(time1_format && clock_timeout==0) {
if (strchr(time1_format, 'S') || strchr(time1_format, 'T') || strchr(time1_format, 'r')) 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 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(); pid = fork();
if (pid == 0) { if (pid == 0) {
// change for the fork the signal mask // change for the fork the signal mask
sigset_t sigset; // sigset_t sigset;
sigprocmask(SIG_SETMASK, &sigset, 0); // sigprocmask(SIG_SETMASK, &sigset, 0);
sigprocmask(SIG_UNBLOCK, &sigset, 0); // sigprocmask(SIG_UNBLOCK, &sigset, 0);
execl("/bin/sh", "/bin/sh", "-c", command, NULL); execl("/bin/sh", "/bin/sh", "-c", command, NULL);
_exit(0); _exit(0);
} }

View file

@ -607,6 +607,22 @@ void add_entry (char *key, char *value)
else if (strcmp (key, "mouse_scroll_down") == 0) else if (strcmp (key, "mouse_scroll_down") == 0)
get_action (value, &mouse_scroll_down); 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 */ /* Read tint-0.6 config for backward compatibility */
else if (strcmp (key, "panel_mode") == 0) { else if (strcmp (key, "panel_mode") == 0) {

View file

@ -51,6 +51,12 @@ int panel_position;
int panel_horizontal; int panel_horizontal;
int panel_refresh; 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_active;
Task *task_drag; Task *task_drag;
int max_tick_urgent; int max_tick_urgent;
@ -64,6 +70,9 @@ int nb_panel = 0;
Imlib_Image default_icon = NULL; Imlib_Image default_icon = NULL;
void autohide_hide(void* p);
void autohide_show(void* p);
void init_panel() void init_panel()
{ {
@ -152,6 +161,8 @@ void init_panel()
long event_mask = ExposureMask|ButtonPressMask|ButtonReleaseMask; long event_mask = ExposureMask|ButtonPressMask|ButtonReleaseMask;
if (g_tooltip.enabled) if (g_tooltip.enabled)
event_mask |= PointerMotionMask|LeaveWindowMask; 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 }; XSetWindowAttributes att = { .event_mask=event_mask, .colormap=server.colormap, .background_pixel=0, .border_pixel=0 };
unsigned long mask = CWEventMask|CWColormap|CWBackPixel|CWBorderPixel; 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); 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 // map new panel
XMapWindow (server.dsp, p->main_win); XMapWindow (server.dsp, p->main_win);
} }
if (panel_autohide)
add_timeout(panel_autohide_hide_timeout, 0, autohide_hide, p);
} }
panel1 = new_panel; 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); 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); // 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); XFreePixmap(server.dsp, p->temp_pmap);
p->temp_pmap = 0; p->temp_pmap = 0;
} }
if (p->hidden_pixmap)
XFreePixmap(server.dsp, p->hidden_pixmap);
p->hidden_pixmap = 0;
if (p->main_win) { if (p->main_win) {
XDestroyWindow(server.dsp, p->main_win); XDestroyWindow(server.dsp, p->main_win);
p->main_win = 0; p->main_win = 0;
@ -378,6 +407,54 @@ void visible_object()
panel_refresh = 1; 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) 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[1] = server.atom._NET_WM_STATE_SKIP_TASKBAR;
state[2] = server.atom._NET_WM_STATE_STICKY; 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; 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 // Unfocusable
XWMHints wmhints; XWMHints wmhints;
@ -425,51 +503,18 @@ void set_panel_properties(Panel *p)
int version=5; int version=5;
XChangeProperty(server.dsp, p->main_win, server.atom.XdndAware, XA_ATOM, 32, PropModeReplace, (unsigned char*)&version, 1); XChangeProperty(server.dsp, p->main_win, server.atom.XdndAware, XA_ATOM, 32, PropModeReplace, (unsigned char*)&version, 1);
// Reserved space update_strut(p);
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);
// Fixed position and non-resizable window // Fixed position and non-resizable window
// Allow panel move and resize when tint2 reload config file // 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; XSizeHints size_hints;
size_hints.flags = PPosition|PMinSize|PMaxSize; size_hints.flags = PPosition|PMinSize|PMaxSize;
size_hints.min_width = size_hints.max_width = p->area.width; size_hints.min_width = minwidth;
size_hints.min_height = size_hints.max_height = p->area.height; 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); XSetWMNormalHints(server.dsp, p->main_win, &size_hints);
// Set WM_CLASS // Set WM_CLASS
@ -504,12 +549,21 @@ void set_panel_background(Panel *p)
cairo_t *c; cairo_t *c;
cs = cairo_xlib_surface_create (server.dsp, p->area.pix.pmap, server.visual, p->area.width, p->area.height); cs = cairo_xlib_surface_create (server.dsp, p->area.pix.pmap, server.visual, p->area.width, p->area.height);
c = cairo_create (cs); c = cairo_create (cs);
draw_background(&p->area, c, 0); draw_background(&p->area, c, 0);
cairo_destroy (c); cairo_destroy (c);
cairo_surface_destroy (cs); 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 // redraw panel's object
GSList *l0; GSList *l0;
Area *a; Area *a;
@ -637,3 +691,92 @@ Area* click_area(Panel *panel, int x, int y)
} while (new_result != result); } while (new_result != result);
return 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);
}

View file

@ -50,6 +50,14 @@ extern int panel_horizontal;
extern int panel_refresh; 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_active;
extern Task *task_drag; extern Task *task_drag;
extern int max_tick_urgent; extern int max_tick_urgent;
@ -97,6 +105,10 @@ typedef struct {
#ifdef ENABLE_BATTERY #ifdef ENABLE_BATTERY
Battery battery; Battery battery;
#endif #endif
int is_hidden;
int hidden_width, hidden_height;
Pixmap hidden_pixmap;
const struct timeout* autohide_timeout;
} Panel; } Panel;
@ -127,4 +139,7 @@ int click_padding(Panel *panel, int x, int y);
int click_clock(Panel *panel, int x, int y); int click_clock(Panel *panel, int x, int y);
Area* click_area(Panel *panel, int x, int y); Area* click_area(Panel *panel, int x, int y);
void autohide_trigger_show();
void autohide_trigger_hide();
#endif #endif

View file

@ -469,7 +469,7 @@ void active_task()
} }
void blink_urgent() void blink_urgent(void* arg)
{ {
GSList* urgent_task = urgent_list; GSList* urgent_task = urgent_list;
while (urgent_task) { while (urgent_task) {
@ -510,7 +510,7 @@ void add_urgent(Task *tsk)
urgent_list = g_slist_concat(urgent_add, urgent_list); urgent_list = g_slist_concat(urgent_add, urgent_list);
if (urgent_timeout == 0) if (urgent_timeout == 0)
urgent_timeout = add_timeout(10, 1000, blink_urgent); urgent_timeout = add_timeout(10, 1000, blink_urgent, 0);
} }

View file

@ -80,13 +80,16 @@ void init (int argc, char *argv[])
sigaction(SIGTERM, &sa, 0); sigaction(SIGTERM, &sa, 0);
sigaction(SIGHUP, &sa, 0); sigaction(SIGHUP, &sa, 0);
signal(SIGCHLD, SIG_IGN); // don't have to wait() after fork() 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 // block all signals, such that no race conditions occur before pselect in our main loop
sigset_t block_mask; // sigset_t block_mask;
sigaddset(&block_mask, SIGINT); // sigaddset(&block_mask, SIGINT);
sigaddset(&block_mask, SIGTERM); // sigaddset(&block_mask, SIGTERM);
sigaddset(&block_mask, SIGHUP); // sigaddset(&block_mask, SIGHUP);
sigaddset(&block_mask, SIGUSR1); // sigaddset(&block_mask, SIGUSR1);
sigprocmask(SIG_BLOCK, &block_mask, 0); // sigprocmask(SIG_BLOCK, &block_mask, 0);
// set global data // set global data
memset(&server, 0, sizeof(Server_global)); memset(&server, 0, sizeof(Server_global));
@ -681,7 +684,7 @@ int main (int argc, char *argv[])
int x11_fd, i; int x11_fd, i;
Panel *panel; Panel *panel;
GSList *it; GSList *it;
const struct timespec* timeout; struct timeval* timeout;
init (argc, argv); init (argc, argv);
init_config(); init_config();
@ -710,8 +713,8 @@ int main (int argc, char *argv[])
x11_fd = ConnectionNumber(server.dsp); x11_fd = ConnectionNumber(server.dsp);
XSync(server.dsp, False); XSync(server.dsp, False);
sigset_t empty_mask; // sigset_t empty_mask;
sigemptyset(&empty_mask); // sigemptyset(&empty_mask);
while (1) { while (1) {
if (panel_refresh) { if (panel_refresh) {
@ -725,15 +728,19 @@ int main (int argc, char *argv[])
for (i=0 ; i < nb_panel ; i++) { for (i=0 ; i < nb_panel ; i++) {
panel = &panel1[i]; panel = &panel1[i];
if (panel->temp_pmap) XFreePixmap(server.dsp, panel->temp_pmap); if (panel->is_hidden)
panel->temp_pmap = XCreatePixmap(server.dsp, server.root_win, panel->area.width, panel->area.height, server.depth); XCopyArea(server.dsp, panel->hidden_pixmap, panel->main_win, server.gc, 0, 0, panel->hidden_width, panel->hidden_height, 0, 0);
else {
refresh(&panel->area); if (panel->temp_pmap) XFreePixmap(server.dsp, panel->temp_pmap);
XCopyArea(server.dsp, panel->temp_pmap, panel->main_win, server.gc, 0, 0, panel->area.width, panel->area.height, 0, 0); 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); XFlush (server.dsp);
if (refresh_systray) { panel = (Panel*)systray.area.panel;
if (refresh_systray && !panel->is_hidden) {
refresh_systray = 0; refresh_systray = 0;
panel = (Panel*)systray.area.panel; panel = (Panel*)systray.area.panel;
// tint2 doen't draw systray icons. it just redraw background. // tint2 doen't draw systray icons. it just redraw background.
@ -748,19 +755,29 @@ int main (int argc, char *argv[])
FD_ZERO (&fdset); FD_ZERO (&fdset);
FD_SET (x11_fd, &fdset); FD_SET (x11_fd, &fdset);
update_next_timeout(); 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; timeout = &next_timeout;
else else
timeout = 0; timeout = 0;
// Wait for X Event or a Timer // 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)) { while (XPending (server.dsp)) {
XNextEvent(server.dsp, &e); 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) { switch (e.type) {
case ButtonPress: case ButtonPress:
tooltip_hide(); tooltip_hide(0);
event_button_press (&e); event_button_press (&e);
break; break;
@ -780,7 +797,8 @@ int main (int argc, char *argv[])
} }
case LeaveNotify: case LeaveNotify:
tooltip_trigger_hide(); if (g_tooltip.enabled)
tooltip_trigger_hide();
break; break;
case Expose: case Expose:

View file

@ -74,7 +74,7 @@ void init_tooltip()
void cleanup_tooltip() void cleanup_tooltip()
{ {
stop_tooltip_timeout(); stop_tooltip_timeout();
tooltip_hide(); tooltip_hide(0);
g_tooltip.enabled = False; g_tooltip.enabled = False;
tooltip_copy_text(0); tooltip_copy_text(0);
if (g_tooltip.window) { 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; int mx, my;
Window w; Window w;
@ -200,7 +200,7 @@ void tooltip_adjust_geometry()
void tooltip_update() void tooltip_update()
{ {
if (!g_tooltip.tooltip_text) { if (!g_tooltip.tooltip_text) {
tooltip_hide(); tooltip_hide(0);
return; return;
} }
@ -265,7 +265,7 @@ void tooltip_trigger_hide(Tooltip* tooltip)
} }
void tooltip_hide() void tooltip_hide(void* arg)
{ {
stop_tooltip_timeout(); stop_tooltip_timeout();
if (g_tooltip.mapped) { if (g_tooltip.mapped) {
@ -279,18 +279,18 @@ void tooltip_hide()
void start_show_timeout() void start_show_timeout()
{ {
if (g_tooltip.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 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() void start_hide_timeout()
{ {
if (g_tooltip.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 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);
} }

View file

@ -46,9 +46,9 @@ extern Tooltip g_tooltip;
void init_tooltip(); void init_tooltip();
void cleanup_tooltip(); void cleanup_tooltip();
void tooltip_trigger_show(Area* area, Panel* p, int x, int y); 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_update();
void tooltip_trigger_hide(); void tooltip_trigger_hide();
void tooltip_hide(); void tooltip_hide(void* /*arg*/);
#endif // TOOLTIP_H #endif // TOOLTIP_H

View file

@ -21,9 +21,9 @@
#include "timer.h" #include "timer.h"
GSList* timeout_list = 0; 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_timeouts(gconstpointer t1, gconstpointer t2);
gint compare_timespecs(const struct timespec* t1, const struct timespec* t2); gint compare_timespecs(const struct timespec* t1, const struct timespec* t2);
int timespec_subtract(struct timespec* result, struct timespec* x, struct timespec* y); 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. * is in the past to the current time.
* As time measurement we use clock_gettime(CLOCK_MONOTONIC) because this refers to a timer, which * 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. * 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)); 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; 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); if ( g_slist_find(timeout_list, t) == 0 )
add_timeout_intern(value_msec, interval_msec, _callback, (struct timeout*)t); 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) { if (timeout_list) {
struct timeout* t = timeout_list->data; struct timeout* t = timeout_list->data;
struct timespec cur_time; 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); 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_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 else
@ -78,12 +90,12 @@ void callback_timeout_expired()
t = timeout_list->data; t = timeout_list->data;
if (compare_timespecs(&t->timeout_expires, &cur_time) <= 0) { if (compare_timespecs(&t->timeout_expires, &cur_time) <= 0) {
// it's time for the callback function // it's time for the callback function
t->_callback(); t->_callback(t->arg);
if (g_slist_find(timeout_list, t)) { 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 // 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); timeout_list = g_slist_remove(timeout_list, t);
if (t->interval_msec > 0) 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 else
free(t); 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->interval_msec = interval_msec;
t->_callback = _callback; t->_callback = _callback;
t->arg = arg;
struct timespec expire; struct timespec expire;
clock_gettime(CLOCK_MONOTONIC, &expire); clock_gettime(CLOCK_MONOTONIC, &expire);
expire.tv_sec += value_msec / 1000; expire.tv_sec += value_msec / 1000;

View file

@ -22,13 +22,14 @@
#include <glib.h> #include <glib.h>
extern GSList* timeout_list; extern GSList* timeout_list;
extern struct timespec next_timeout; extern struct timeval next_timeout;
struct timeout { struct timeout {
int interval_msec; int interval_msec;
struct timespec timeout_expires; struct timespec timeout_expires;
void (*_callback)(); 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 /** 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. * '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 **/ * 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' **/ /** stops the timeout 't' **/
void stop_timeout(const struct timeout* t); void stop_timeout(const struct timeout* t);