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
+
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
+
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
+
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
+
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
+
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
+
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
+
char *path_current_now=0;
char *path_status=0;
-void update_batterys()
+void update_batterys(void* arg)
{
int i;
update_battery();
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);
}
static const struct timeout* clock_timeout=0;
-void update_clocks()
+void update_clocks(void* arg)
{
gettimeofday(&time_clock, 0);
int i;
{
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);
}
}
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);
}
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) {
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;
Imlib_Image default_icon = NULL;
+void autohide_hide(void* p);
+void autohide_show(void* p);
+
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);
// 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;
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);
}
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;
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)
{
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;
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
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;
} 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);
+}
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;
#ifdef ENABLE_BATTERY
Battery battery;
#endif
+ int is_hidden;
+ int hidden_width, hidden_height;
+ Pixmap hidden_pixmap;
+ const struct timeout* autohide_timeout;
} Panel;
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
}
-void blink_urgent()
+void blink_urgent(void* arg)
{
GSList* urgent_task = urgent_list;
while (urgent_task) {
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);
}
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));
int x11_fd, i;
Panel *panel;
GSList *it;
- const struct timespec* timeout;
+ struct timeval* timeout;
init (argc, argv);
init_config();
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) {
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.
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;
}
case LeaveNotify:
- tooltip_trigger_hide();
+ if (g_tooltip.enabled)
+ tooltip_trigger_hide();
break;
case Expose:
void cleanup_tooltip()
{
stop_tooltip_timeout();
- tooltip_hide();
+ tooltip_hide(0);
g_tooltip.enabled = False;
tooltip_copy_text(0);
if (g_tooltip.window) {
}
-void tooltip_show()
+void tooltip_show(void* arg)
{
int mx, my;
Window w;
void tooltip_update()
{
if (!g_tooltip.tooltip_text) {
- tooltip_hide();
+ tooltip_hide(0);
return;
}
}
-void tooltip_hide()
+void tooltip_hide(void* arg)
{
stop_tooltip_timeout();
if (g_tooltip.mapped) {
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);
}
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
#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);
* 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);
+ }
}
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
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);
}
}
-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;
#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;
};
/** 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);