diff --git a/src/dbus.c b/src/dbus.c index fe03902..79af31c 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -264,7 +264,8 @@ static void on_notify(GDBusConnection *connection, n->color_strings[ColFG] = fgcolor; 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(); GVariant *reply = g_variant_new("(u)", id); diff --git a/src/dunst.c b/src/dunst.c index 16867dc..6ed9eff 100644 --- a/src/dunst.c +++ b/src/dunst.c @@ -261,7 +261,9 @@ int dunst_main(int argc, char *argv[]) n->timeout = 10 * G_USEC_PER_SEC; n->markup = MARKUP_NO; 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); diff --git a/src/notification.c b/src/notification.c index e3c0411..0703377 100644 --- a/src/notification.c +++ b/src/notification.c @@ -23,7 +23,6 @@ #include "utils.h" #include "x11/x.h" -int next_notification_id = 1; /* * print a human readable representation @@ -280,28 +279,28 @@ void notification_init_defaults(notification *n) } /* - * Initialize the given notification and add it to - * the queue. Replace notification with id if id > 0. + * Initialize the given notification * * n should be a pointer to a notification allocated with * notification_create, it is undefined behaviour to pass a notification * allocated some other way. */ -int notification_init(notification *n, int id) +void notification_init(notification *n) { assert(n != NULL); //Prevent undefined behaviour by initialising required fields notification_init_defaults(n); + // TODO: this does not belong into notification_init if (strcmp("DUNST_COMMAND_PAUSE", n->summary) == 0) { pause_display = true; - return 0; + return; } if (strcmp("DUNST_COMMAND_RESUME", n->summary) == 0) { pause_display = false; - return 0; + return; } n->script = NULL; @@ -423,65 +422,8 @@ int notification_init(notification *n, int id) n->msg = buffer; } - if (id == 0) { - n->id = ++next_notification_id; - } else { - n->id = id; - } - 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 */ n->urgency = n->urgency > CRIT ? CRIT : n->urgency; @@ -507,15 +449,13 @@ int notification_init(notification *n, int id) n->first_render = true; + /* TODO: this should not be part of notification_init */ if (strlen(n->msg) == 0) { notification_close(n, 2); if (settings.always_run_script) { notification_run_script(n); } 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); @@ -540,11 +480,6 @@ int notification_init(notification *n, int id) } g_free(tmp); - - if (settings.print_notifications) - notification_print(n); - - return n->id; } void notification_update_text_to_render(notification *n) diff --git a/src/notification.h b/src/notification.h index d56ef90..e5250c1 100644 --- a/src/notification.h +++ b/src/notification.h @@ -62,7 +62,7 @@ typedef struct _notification { } notification; notification *notification_create(void); -int notification_init(notification *n, int id); +void notification_init(notification *n); void notification_free(notification *n); int notification_cmp(const void *a, const void *b); int notification_cmp_data(const void *a, const void *b, void *data); diff --git a/src/queues.c b/src/queues.c index 41bc922..30b727d 100644 --- a/src/queues.c +++ b/src/queues.c @@ -15,6 +15,9 @@ GQueue *displayed = NULL; /* currently displayed notifications */ GQueue *history = NULL; /* history of displayed notifications */ unsigned int displayed_limit = 0; +int next_notification_id = 1; + +static int queues_stack_duplicate(notification *n); void queues_init(void) { @@ -28,6 +31,84 @@ void queues_displayed_limit(unsigned int 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) { diff --git a/src/queues.h b/src/queues.h index 7b53c58..f6517e8 100644 --- a/src/queues.h +++ b/src/queues.h @@ -21,6 +21,17 @@ void queues_init(void); */ 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 * the new notification. The given notification is inserted