Move id assignment to separate function in queues.c

Move all id-changing functions out of notification_init and handle this
in queues.c

Also use stack_duplicates in combination with replacement of
notifications correctly. Fixes #404 (issue not found)
This commit is contained in:
Benedikt Heine 2017-10-08 18:30:51 +02:00
parent af9f6b8b7d
commit f869175d0d
6 changed files with 104 additions and 74 deletions

View File

@ -264,7 +264,8 @@ static void on_notify(GDBusConnection *connection,
n->color_strings[ColFG] = fgcolor; n->color_strings[ColFG] = fgcolor;
n->color_strings[ColBG] = bgcolor; n->color_strings[ColBG] = bgcolor;
int id = notification_init(n, replaces_id); notification_init(n);
int id = queues_notification_insert(n, replaces_id);
wake_up(); wake_up();
GVariant *reply = g_variant_new("(u)", id); GVariant *reply = g_variant_new("(u)", id);

View File

@ -261,7 +261,9 @@ int dunst_main(int argc, char *argv[])
n->timeout = 10 * G_USEC_PER_SEC; n->timeout = 10 * G_USEC_PER_SEC;
n->markup = MARKUP_NO; n->markup = MARKUP_NO;
n->urgency = LOW; n->urgency = LOW;
notification_init(n, 0); notification_init(n);
queues_notification_insert(n, 0);
// we do not call wakeup now, wake_up does not work here yet
} }
mainloop = g_main_loop_new(NULL, FALSE); mainloop = g_main_loop_new(NULL, FALSE);

View File

@ -23,7 +23,6 @@
#include "utils.h" #include "utils.h"
#include "x11/x.h" #include "x11/x.h"
int next_notification_id = 1;
/* /*
* print a human readable representation * print a human readable representation
@ -280,28 +279,28 @@ void notification_init_defaults(notification *n)
} }
/* /*
* Initialize the given notification and add it to * Initialize the given notification
* the queue. Replace notification with id if id > 0.
* *
* n should be a pointer to a notification allocated with * n should be a pointer to a notification allocated with
* notification_create, it is undefined behaviour to pass a notification * notification_create, it is undefined behaviour to pass a notification
* allocated some other way. * allocated some other way.
*/ */
int notification_init(notification *n, int id) void notification_init(notification *n)
{ {
assert(n != NULL); assert(n != NULL);
//Prevent undefined behaviour by initialising required fields //Prevent undefined behaviour by initialising required fields
notification_init_defaults(n); notification_init_defaults(n);
// TODO: this does not belong into notification_init
if (strcmp("DUNST_COMMAND_PAUSE", n->summary) == 0) { if (strcmp("DUNST_COMMAND_PAUSE", n->summary) == 0) {
pause_display = true; pause_display = true;
return 0; return;
} }
if (strcmp("DUNST_COMMAND_RESUME", n->summary) == 0) { if (strcmp("DUNST_COMMAND_RESUME", n->summary) == 0) {
pause_display = false; pause_display = false;
return 0; return;
} }
n->script = NULL; n->script = NULL;
@ -423,65 +422,8 @@ int notification_init(notification *n, int id)
n->msg = buffer; n->msg = buffer;
} }
if (id == 0) {
n->id = ++next_notification_id;
} else {
n->id = id;
}
n->dup_count = 0; n->dup_count = 0;
/* TODO: move this to queue.c */
/* check if n is a duplicate */
if (settings.stack_duplicates) {
for (GList *iter = g_queue_peek_head_link(queue); iter;
iter = iter->next) {
notification *orig = iter->data;
if (notification_is_duplicate(orig, n)) {
/* If the progress differs this was probably intended to replace the notification
* but notify-send was used. So don't increment dup_count in this case
*/
if (orig->progress == n->progress) {
orig->dup_count++;
} else {
orig->progress = n->progress;
}
/* notifications that differ only in progress hints should be expected equal,
* but we want the latest message, with the latest hint value
*/
g_free(orig->msg);
orig->msg = g_strdup(n->msg);
notification_free(n);
wake_up();
return orig->id;
}
}
for (GList *iter = g_queue_peek_head_link(displayed); iter;
iter = iter->next) {
notification *orig = iter->data;
if (notification_is_duplicate(orig, n)) {
/* notifications that differ only in progress hints should be expected equal,
* but we want the latest message, with the latest hint value
*/
g_free(orig->msg);
orig->msg = g_strdup(n->msg);
/* If the progress differs this was probably intended to replace the notification
* but notify-send was used. So don't increment dup_count in this case
*/
if (orig->progress == n->progress) {
orig->dup_count++;
} else {
orig->progress = n->progress;
}
orig->start = g_get_monotonic_time();
notification_free(n);
wake_up();
return orig->id;
}
}
}
/* urgency > CRIT -> array out of range */ /* urgency > CRIT -> array out of range */
n->urgency = n->urgency > CRIT ? CRIT : n->urgency; n->urgency = n->urgency > CRIT ? CRIT : n->urgency;
@ -507,15 +449,13 @@ int notification_init(notification *n, int id)
n->first_render = true; n->first_render = true;
/* TODO: this should not be part of notification_init */
if (strlen(n->msg) == 0) { if (strlen(n->msg) == 0) {
notification_close(n, 2); notification_close(n, 2);
if (settings.always_run_script) { if (settings.always_run_script) {
notification_run_script(n); notification_run_script(n);
} }
printf("skipping notification: %s %s\n", n->body, n->summary); printf("skipping notification: %s %s\n", n->body, n->summary);
} else {
if (id == 0 || !notification_replace_by_id(n))
g_queue_insert_sorted(queue, n, notification_cmp_data, NULL);
} }
char *tmp = g_strconcat(n->summary, " ", n->body, NULL); char *tmp = g_strconcat(n->summary, " ", n->body, NULL);
@ -540,11 +480,6 @@ int notification_init(notification *n, int id)
} }
g_free(tmp); g_free(tmp);
if (settings.print_notifications)
notification_print(n);
return n->id;
} }
void notification_update_text_to_render(notification *n) void notification_update_text_to_render(notification *n)

View File

@ -62,7 +62,7 @@ typedef struct _notification {
} notification; } notification;
notification *notification_create(void); notification *notification_create(void);
int notification_init(notification *n, int id); void notification_init(notification *n);
void notification_free(notification *n); void notification_free(notification *n);
int notification_cmp(const void *a, const void *b); int notification_cmp(const void *a, const void *b);
int notification_cmp_data(const void *a, const void *b, void *data); int notification_cmp_data(const void *a, const void *b, void *data);

View File

@ -15,6 +15,9 @@ GQueue *displayed = NULL; /* currently displayed notifications */
GQueue *history = NULL; /* history of displayed notifications */ GQueue *history = NULL; /* history of displayed notifications */
unsigned int displayed_limit = 0; unsigned int displayed_limit = 0;
int next_notification_id = 1;
static int queues_stack_duplicate(notification *n);
void queues_init(void) void queues_init(void)
{ {
@ -28,6 +31,84 @@ void queues_displayed_limit(unsigned int limit)
displayed_limit = limit; displayed_limit = limit;
} }
int queues_notification_insert(notification *n, int replaces_id)
{
if (replaces_id == 0) {
n->id = ++next_notification_id;
if (settings.stack_duplicates) {
int stacked = queues_stack_duplicate(n);
if (stacked > 0) {
// notification got stacked
return stacked;
}
}
g_queue_insert_sorted(queue, n, notification_cmp_data, NULL);
} else {
n->id = replaces_id;
if (!notification_replace_by_id(n))
g_queue_insert_sorted(queue, n, notification_cmp_data, NULL);
}
if (settings.print_notifications)
notification_print(n);
return n->id;
}
/*
* Replaces duplicate notification and stacks it
*
* Returns the notification id of the stacked notification
* Returns -1 if not notification could be stacked
*/
static int queues_stack_duplicate(notification *n)
{
for (GList *iter = g_queue_peek_head_link(displayed); iter;
iter = iter->next) {
notification *orig = iter->data;
if (notification_is_duplicate(orig, n)) {
/* If the progress differs, probably notify-send was used to update the notification
* So only count it as a duplicate, if the progress was not the same.
* */
if (orig->progress == n->progress) {
orig->dup_count++;
} else {
orig->progress = n->progress;
}
orig->start = g_get_monotonic_time();
g_free(orig->msg);
orig->msg = g_strdup(n->msg);
notification_free(n);
return orig->id;
}
}
for (GList *iter = g_queue_peek_head_link(queue); iter;
iter = iter->next) {
notification *orig = iter->data;
if (notification_is_duplicate(orig, n)) {
/* If the progress differs, probably notify-send was used to update the notification
* So only count it as a duplicate, if the progress was not the same.
* */
if (orig->progress == n->progress) {
orig->dup_count++;
} else {
orig->progress = n->progress;
}
g_free(orig->msg);
orig->msg = g_strdup(n->msg);
notification_free(n);
return orig->id;
}
}
return -1;
}
bool notification_replace_by_id(notification *new) bool notification_replace_by_id(notification *new)
{ {

View File

@ -21,6 +21,17 @@ void queues_init(void);
*/ */
void queues_displayed_limit(unsigned int limit); void queues_displayed_limit(unsigned int limit);
/*
* Insert a fully initialized notification into queues
* Respects stack_duplicates, and notification replacement
*
* If replaces_id != 0, n replaces notification with id replaces_id
* If replaces_id == 0, n gets occupies a new position
*
* Returns the assigned notification id
*/
int queues_notification_insert(notification *n, int replaces_id);
/* /*
* Replace the notification which matches the id field of * Replace the notification which matches the id field of
* the new notification. The given notification is inserted * the new notification. The given notification is inserted