*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_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_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_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_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_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_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

View file

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

View file

@ -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 @@ void init_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);
}

View file

@ -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 @@ void clock_action(int button)
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);
}

View file

@ -607,6 +607,22 @@ void add_entry (char *key, char *value)
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) {

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

View file

@ -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 @@ typedef struct {
#ifdef ENABLE_BATTERY
Battery battery;
#endif
int is_hidden;
int hidden_width, hidden_height;
Pixmap hidden_pixmap;
const struct timeout* autohide_timeout;
} Panel;
@ -127,4 +139,7 @@ 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

View file

@ -469,7 +469,7 @@ void active_task()
}
void blink_urgent()
void blink_urgent(void* arg)
{
GSList* urgent_task = urgent_list;
while (urgent_task) {
@ -510,7 +510,7 @@ void add_urgent(Task *tsk)
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);
}

View file

@ -80,13 +80,16 @@ void init (int argc, char *argv[])
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 @@ int main (int argc, char *argv[])
int x11_fd, i;
Panel *panel;
GSList *it;
const struct timespec* timeout;
struct timeval* timeout;
init (argc, argv);
init_config();
@ -710,8 +713,8 @@ int main (int argc, char *argv[])
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 @@ int main (int argc, char *argv[])
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 @@ int main (int argc, char *argv[])
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 @@ int main (int argc, char *argv[])
}
case LeaveNotify:
tooltip_trigger_hide();
if (g_tooltip.enabled)
tooltip_trigger_hide();
break;
case Expose:

View file

@ -74,7 +74,7 @@ void init_tooltip()
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_trigger_show(Area* area, Panel* p, int x_root, int y_root)
}
void tooltip_show()
void tooltip_show(void* arg)
{
int mx, my;
Window w;
@ -200,7 +200,7 @@ void tooltip_adjust_geometry()
void tooltip_update()
{
if (!g_tooltip.tooltip_text) {
tooltip_hide();
tooltip_hide(0);
return;
}
@ -265,7 +265,7 @@ void tooltip_trigger_hide(Tooltip* tooltip)
}
void tooltip_hide()
void tooltip_hide(void* arg)
{
stop_tooltip_timeout();
if (g_tooltip.mapped) {
@ -279,18 +279,18 @@ void tooltip_hide()
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);
}

View file

@ -46,9 +46,9 @@ extern Tooltip g_tooltip;
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

View file

@ -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 @@ int timespec_subtract(struct timespec* result, struct timespec* x, struct timesp
* 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 @@ void update_next_timeout()
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 @@ void callback_timeout_expired()
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 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->_callback = _callback;
t->arg = arg;
struct timespec expire;
clock_gettime(CLOCK_MONOTONIC, &expire);
expire.tv_sec += value_msec / 1000;

View file

@ -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 @@ struct timeout {
/** 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);