all repos — tint2 @ adb784a85994b839c19ceb0189ceedde20ba6c28

fork of the tint2 desktop panel for my custom setup - only minimized windows across all desktops for the taskbar

*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
Andreas.Fink85 Andreas.Fink85@121b4492-b84c-0410-8b4c-0d4edfb3f3cc
commit

adb784a85994b839c19ceb0189ceedde20ba6c28

parent

755d6672fea9d7023f8451bb0196c574e8732c15

M sample/black_single_desktop.tint2rcsample/black_single_desktop.tint2rc

@@ -100,4 +100,13 @@ mouse_right = close

mouse_scroll_up = toggle mouse_scroll_down = iconify +#--------------------------------------------- +# AUTOHIDE OPTIONS +#--------------------------------------------- +autohide = 0 +autohide_show_timeout = 0.3 +autohide_hide_timeout = 2 +autohide_height = 4 +strut_policy = minimum +
M sample/default.tint2rcsample/default.tint2rc

@@ -127,3 +127,12 @@ mouse_right = close

mouse_scroll_up = toggle mouse_scroll_down = iconify +#--------------------------------------------- +# AUTOHIDE OPTIONS +#--------------------------------------------- +autohide = 0 +autohide_show_timeout = 0.3 +autohide_hide_timeout = 2 +autohide_height = 4 +strut_policy = minimum +
M sample/horizontal_icon_only.tint2rcsample/horizontal_icon_only.tint2rc

@@ -125,3 +125,12 @@ mouse_right = close

mouse_scroll_up = toggle mouse_scroll_down = iconify +#--------------------------------------------- +# AUTOHIDE OPTIONS +#--------------------------------------------- +autohide = 0 +autohide_show_timeout = 0.3 +autohide_hide_timeout = 2 +autohide_height = 4 +strut_policy = minimum +
M sample/rounded_multi_desktop.tint2rcsample/rounded_multi_desktop.tint2rc

@@ -105,3 +105,12 @@ mouse_right = close

mouse_scroll_up = toggle mouse_scroll_down = iconify +#--------------------------------------------- +# AUTOHIDE OPTIONS +#--------------------------------------------- +autohide = 0 +autohide_show_timeout = 0.3 +autohide_hide_timeout = 2 +autohide_height = 4 +strut_policy = minimum +
M sample/tint2rcsample/tint2rc

@@ -115,3 +115,12 @@ mouse_right = close

mouse_scroll_up = toggle mouse_scroll_down = iconify +#--------------------------------------------- +# AUTOHIDE OPTIONS +#--------------------------------------------- +autohide = 0 +autohide_show_timeout = 0.3 +autohide_hide_timeout = 2 +autohide_height = 4 +strut_policy = minimum +
M sample/vertical_icon_only.tint2rcsample/vertical_icon_only.tint2rc

@@ -114,3 +114,13 @@ mouse_middle = none

mouse_right = close mouse_scroll_up = toggle mouse_scroll_down = iconify + +#--------------------------------------------- +# AUTOHIDE OPTIONS +#--------------------------------------------- +autohide = 0 +autohide_show_timeout = 0.3 +autohide_hide_timeout = 2 +autohide_height = 4 +strut_policy = minimum +
M sample/white_single_desktop.tint2rcsample/white_single_desktop.tint2rc

@@ -122,3 +122,12 @@ mouse_right = close

mouse_scroll_up = toggle mouse_scroll_down = iconify +#--------------------------------------------- +# AUTOHIDE OPTIONS +#--------------------------------------------- +autohide = 0 +autohide_show_timeout = 0.3 +autohide_hide_timeout = 2 +autohide_height = 4 +strut_policy = minimum +
M src/battery/battery.csrc/battery/battery.c

@@ -50,7 +50,7 @@ char *path_energy_full=0;

char *path_current_now=0; char *path_status=0; -void update_batterys() +void update_batterys(void* arg) { int i; update_battery();

@@ -133,7 +133,7 @@ g_free(path1);

g_free(battery_dir); if (battery_enabled && battery_timeout==0) - battery_timeout = add_timeout(10, 5000, update_batterys); + battery_timeout = add_timeout(10, 5000, update_batterys, 0); }
M src/clock/clock.csrc/clock/clock.c

@@ -53,7 +53,7 @@ int clock_enabled;

static const struct timeout* clock_timeout=0; -void update_clocks() +void update_clocks(void* arg) { gettimeofday(&time_clock, 0); int i;

@@ -87,9 +87,9 @@ void init_clock()

{ if(time1_format && clock_timeout==0) { 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 - clock_timeout = add_timeout(10, 60000, update_clocks); + clock_timeout = add_timeout(10, 60000, update_clocks, 0); } }

@@ -282,9 +282,9 @@ pid_t pid;

pid = fork(); if (pid == 0) { // change for the fork the signal mask - sigset_t sigset; - sigprocmask(SIG_SETMASK, &sigset, 0); - sigprocmask(SIG_UNBLOCK, &sigset, 0); +// sigset_t sigset; +// sigprocmask(SIG_SETMASK, &sigset, 0); +// sigprocmask(SIG_UNBLOCK, &sigset, 0); execl("/bin/sh", "/bin/sh", "-c", command, NULL); _exit(0); }
M src/config.csrc/config.c

@@ -607,6 +607,22 @@ get_action (value, &mouse_scroll_up);

else if (strcmp (key, "mouse_scroll_down") == 0) 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 */ else if (strcmp (key, "panel_mode") == 0) {
M src/panel.csrc/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 @@

Imlib_Image default_icon = NULL; +void autohide_hide(void* p); +void autohide_show(void* p); + void init_panel() {

@@ -152,6 +161,8 @@ // new panel : catch some events

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 @@ if (i >= old_nb_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 @@ else {

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 @@ if (p->temp_pmap) {

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 @@ }

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 @@ state[0] = server.atom._NET_WM_STATE_SKIP_PAGER;

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 @@ // XdndAware - Register for Xdnd events

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,11 +549,20 @@ cairo_surface_t *cs;

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;

@@ -637,3 +691,92 @@ }

} 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); +}
M src/panel.hsrc/panel.h

@@ -50,6 +50,14 @@ extern int panel_horizontal;

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_drag; extern int max_tick_urgent;

@@ -97,6 +105,10 @@ // battery

#ifdef ENABLE_BATTERY Battery battery; #endif + int is_hidden; + int hidden_width, hidden_height; + Pixmap hidden_pixmap; + const struct timeout* autohide_timeout; } Panel;

@@ -126,5 +138,8 @@ Task *click_task (Panel *panel, int x, int y);

int click_padding(Panel *panel, int x, int y); int click_clock(Panel *panel, int x, int y); Area* click_area(Panel *panel, int x, int y); + +void autohide_trigger_show(); +void autohide_trigger_hide(); #endif
M src/taskbar/task.csrc/taskbar/task.c

@@ -469,7 +469,7 @@ }

} -void blink_urgent() +void blink_urgent(void* arg) { GSList* urgent_task = urgent_list; while (urgent_task) {

@@ -510,7 +510,7 @@ // not yet in the list, so we have to add it

urgent_list = g_slist_concat(urgent_add, urgent_list); if (urgent_timeout == 0) - urgent_timeout = add_timeout(10, 1000, blink_urgent); + urgent_timeout = add_timeout(10, 1000, blink_urgent, 0); }
M src/tint.csrc/tint.c

@@ -80,13 +80,16 @@ sigaction(SIGINT, &sa, 0);

sigaction(SIGTERM, &sa, 0); sigaction(SIGHUP, &sa, 0); 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 - sigset_t block_mask; - sigaddset(&block_mask, SIGINT); - sigaddset(&block_mask, SIGTERM); - sigaddset(&block_mask, SIGHUP); - sigaddset(&block_mask, SIGUSR1); - sigprocmask(SIG_BLOCK, &block_mask, 0); +// sigset_t block_mask; +// sigaddset(&block_mask, SIGINT); +// sigaddset(&block_mask, SIGTERM); +// sigaddset(&block_mask, SIGHUP); +// sigaddset(&block_mask, SIGUSR1); +// sigprocmask(SIG_BLOCK, &block_mask, 0); // set global data memset(&server, 0, sizeof(Server_global));

@@ -681,7 +684,7 @@ fd_set fdset;

int x11_fd, i; Panel *panel; GSList *it; - const struct timespec* timeout; + struct timeval* timeout; init (argc, argv); init_config();

@@ -710,8 +713,8 @@ XDamageQueryExtension(server.dsp, &damage_event, &damage_error);

x11_fd = ConnectionNumber(server.dsp); XSync(server.dsp, False); - sigset_t empty_mask; - sigemptyset(&empty_mask); +// sigset_t empty_mask; +// sigemptyset(&empty_mask); while (1) { if (panel_refresh) {

@@ -725,15 +728,19 @@ }

for (i=0 ; i < nb_panel ; i++) { panel = &panel1[i]; - if (panel->temp_pmap) XFreePixmap(server.dsp, panel->temp_pmap); - 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); + if (panel->is_hidden) + XCopyArea(server.dsp, panel->hidden_pixmap, panel->main_win, server.gc, 0, 0, panel->hidden_width, panel->hidden_height, 0, 0); + else { + if (panel->temp_pmap) XFreePixmap(server.dsp, panel->temp_pmap); + 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); - if (refresh_systray) { + panel = (Panel*)systray.area.panel; + if (refresh_systray && !panel->is_hidden) { refresh_systray = 0; panel = (Panel*)systray.area.panel; // tint2 doen't draw systray icons. it just redraw background.

@@ -748,19 +755,29 @@ // Create a File Description Set containing x11_fd

FD_ZERO (&fdset); FD_SET (x11_fd, &fdset); 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; else timeout = 0; // 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)) { 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) { case ButtonPress: - tooltip_hide(); + tooltip_hide(0); event_button_press (&e); break;

@@ -780,7 +797,8 @@ break;

} case LeaveNotify: - tooltip_trigger_hide(); + if (g_tooltip.enabled) + tooltip_trigger_hide(); break; case Expose:
M src/tooltip/tooltip.csrc/tooltip/tooltip.c

@@ -74,7 +74,7 @@

void cleanup_tooltip() { stop_tooltip_timeout(); - tooltip_hide(); + tooltip_hide(0); g_tooltip.enabled = False; tooltip_copy_text(0); if (g_tooltip.window) {

@@ -104,7 +104,7 @@ }

} -void tooltip_show() +void tooltip_show(void* arg) { int mx, my; Window w;

@@ -200,7 +200,7 @@

void tooltip_update() { if (!g_tooltip.tooltip_text) { - tooltip_hide(); + tooltip_hide(0); return; }

@@ -265,7 +265,7 @@ }

} -void tooltip_hide() +void tooltip_hide(void* arg) { stop_tooltip_timeout(); if (g_tooltip.mapped) {

@@ -279,18 +279,18 @@

void start_show_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 - 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() { 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 - 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); }
M src/tooltip/tooltip.hsrc/tooltip/tooltip.h

@@ -46,9 +46,9 @@

void init_tooltip(); void cleanup_tooltip(); 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_trigger_hide(); -void tooltip_hide(); +void tooltip_hide(void* /*arg*/); #endif // TOOLTIP_H
M src/util/timer.csrc/util/timer.c

@@ -21,9 +21,9 @@

#include "timer.h" 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_timespecs(const struct timespec* t1, const struct timespec* t2); int timespec_subtract(struct timespec* result, struct timespec* x, struct timespec* y);

@@ -36,20 +36,27 @@ * and callback_timeout_expired() only have to consider the timeouts as long as the expiration 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 * 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)); - add_timeout_intern(value_msec, interval_msec, _callback, t); + add_timeout_intern(value_msec, interval_msec, _callback, arg, 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); - add_timeout_intern(value_msec, interval_msec, _callback, (struct timeout*)t); + if ( g_slist_find(timeout_list, t) == 0 ) + 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 @@ {

if (timeout_list) { struct timeout* t = timeout_list->data; 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); - 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_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

@@ -78,12 +90,12 @@ clock_gettime(CLOCK_MONOTONIC, &cur_time);

t = timeout_list->data; if (compare_timespecs(&t->timeout_expires, &cur_time) <= 0) { // it's time for the callback function - t->_callback(); + t->_callback(t->arg); 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 timeout_list = g_slist_remove(timeout_list, t); 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 free(t); }

@@ -113,10 +125,11 @@ }

} -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->_callback = _callback; + t->arg = arg; struct timespec expire; clock_gettime(CLOCK_MONOTONIC, &expire); expire.tv_sec += value_msec / 1000;
M src/util/timer.hsrc/util/timer.h

@@ -22,13 +22,14 @@

#include <glib.h> extern GSList* timeout_list; -extern struct timespec next_timeout; +extern struct timeval next_timeout; struct timeout { int interval_msec; struct timespec timeout_expires; void (*_callback)(); + void* arg; };

@@ -36,9 +37,9 @@ // timer functions

/** 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. * 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' **/ void stop_timeout(const struct timeout* t);