only add timeout when it hits before any existing timeout

This commit is contained in:
Sascha Kruse 2013-03-08 07:27:19 +01:00
parent 3127bb9198
commit 9931512315
3 changed files with 68 additions and 26 deletions

69
dunst.c
View File

@ -57,9 +57,6 @@ typedef struct _x11_source {
bool pause_display = false; bool pause_display = false;
GMainLoop *mainloop = NULL; GMainLoop *mainloop = NULL;
bool timer_active = false;
bool force_redraw = false;
/* notification lists */ /* notification lists */
GQueue *queue = NULL; /* all new notifications get into here */ GQueue *queue = NULL; /* all new notifications get into here */
@ -92,7 +89,6 @@ void check_timeouts(void)
/* remove old message */ /* remove old message */
if (difftime(time(NULL), n->start) > n->timeout) { if (difftime(time(NULL), n->start) > n->timeout) {
force_redraw = true;
/* close_notification may conflict with iter, so restart */ /* close_notification may conflict with iter, so restart */
notification_close(n, 1); notification_close(n, 1);
check_timeouts(); check_timeouts();
@ -133,8 +129,6 @@ void update_lists()
break; break;
} }
force_redraw = true;
notification *n = g_queue_pop_head(queue); notification *n = g_queue_pop_head(queue);
if (!n) if (!n)
@ -181,38 +175,70 @@ void history_pop(void)
void wake_up(void) void wake_up(void)
{ {
force_redraw = true;
run(NULL); run(NULL);
} }
static int get_sleep_time(void) static int get_sleep_time(void)
{ {
int sleep = 0;
if (settings.show_age_threshold == 0) {
/* we need to update every second */
return 1000;
}
bool have_ttl = false;
int min_ttl = 0;
int max_age = 0;
for (GList *iter = g_queue_peek_head_link(displayed); iter; for (GList *iter = g_queue_peek_head_link(displayed); iter;
iter = iter->next) { iter = iter->next) {
notification *n = iter->data; notification *n = iter->data;
if (sleep == 0) { max_age = MAX(max_age, notification_get_age(n));
sleep = notification_get_ttl(n); int ttl = notification_get_ttl(n);
if (ttl > 0) {
if (have_ttl) {
min_ttl = MIN(min_ttl, ttl);
} else { } else {
sleep = MIN(sleep, notification_get_ttl(n)); min_ttl = ttl;
have_ttl = true;
}
} }
} }
sleep = MIN(sleep, settings.show_age_threshold); int min_timeout;
int show_age_timeout = settings.show_age_threshold - max_age;
sleep = sleep * 1000; if (show_age_timeout < 1) {
return 1000;
}
if (!have_ttl) {
min_timeout = show_age_timeout;
} else {
min_timeout = MIN(show_age_timeout, min_ttl);
}
/* show_age_timeout might be negative */
if (min_timeout < 1) {
return 1000;
} else {
/* add 501 milliseconds to make sure we wake are in the second /* add 501 milliseconds to make sure we wake are in the second
* after the next notification times out. Otherwise we'll wake * after the next notification times out. Otherwise we'll wake
* up, but the notification won't get closed until we get woken * up, but the notification won't get closed until we get woken
* up again (which might be multiple seconds later */ * up again (which might be multiple seconds later */
return sleep + 501; return min_timeout * 1000 + 501;
}
} }
gboolean run(void *data) gboolean run(void *data)
{ {
update_lists(); update_lists();
static int timeout_cnt = 0;
static int next_timeout = 0;
if (data) {
timeout_cnt--;
}
if (displayed->length > 0 && !xctx.visible) { if (displayed->length > 0 && !xctx.visible) {
x_win_show(); x_win_show();
@ -222,15 +248,22 @@ gboolean run(void *data)
x_win_hide(); x_win_hide();
} }
if (xctx.visible && force_redraw) { if (xctx.visible) {
x_win_draw(); x_win_draw();
force_redraw = false;
} }
if (xctx.visible && !timer_active) { if (xctx.visible) {
int now = time(NULL) * 1000;
int sleep = get_sleep_time(); int sleep = get_sleep_time();
if (sleep > 0)
if (sleep > 0) {
int timeout_at = now + sleep;
if (timeout_cnt == 0 || timeout_at < next_timeout) {
g_timeout_add(sleep, run, mainloop); g_timeout_add(sleep, run, mainloop);
next_timeout = timeout_at;
timeout_cnt++;
}
}
} }
/* always return false to delete timers */ /* always return false to delete timers */

View File

@ -466,6 +466,14 @@ void notification_update_text_to_render(notification *n)
} }
int notification_get_ttl(notification *n) { int notification_get_ttl(notification *n) {
if (n->timeout == 0) {
return 0;
} else {
return n->timeout - (time(NULL) - n->start); return n->timeout - (time(NULL) - n->start);
} }
}
int notification_get_age(notification *n) {
return time(NULL) - n->timestamp;
}
/* vim: set ts=8 sw=8 tw=0: */ /* vim: set ts=8 sw=8 tw=0: */

View File

@ -49,3 +49,4 @@ void notification_print(notification * n);
char *notification_fix_markup(char *str); char *notification_fix_markup(char *str);
void notification_update_text_to_render(notification *n); void notification_update_text_to_render(notification *n);
int notification_get_ttl(notification *n); int notification_get_ttl(notification *n);
int notification_get_age(notification *n);