diff --git a/config.h b/config.h index f8ca9cf..c5f2577 100644 --- a/config.h +++ b/config.h @@ -38,6 +38,7 @@ struct settings defaults = { .history_length = 20, /* max amount of notifications kept in history */ .show_indicators = true, .word_wrap = false, +.ignore_dbusclose = false, .ellipsize = ELLIPSE_MIDDLE, .ignore_newline = false, .line_height = 0, /* if line height < font height, it will be raised to font height */ diff --git a/docs/dunst.pod b/docs/dunst.pod index 44a71ee..9f9dd86 100644 --- a/docs/dunst.pod +++ b/docs/dunst.pod @@ -515,6 +515,13 @@ Close all notifications. =back + +=item B (default: false) + +Ignore the dbus closeNotification message. This is useful to enforce the timeout +set by dunst configuration. Without this parameter, an application may close +the notification sent before the user defined timeout. + =back =head2 Shortcut section B diff --git a/dunstrc b/dunstrc index e9c8715..331347e 100644 --- a/dunstrc +++ b/dunstrc @@ -224,6 +224,12 @@ # notification height to avoid clipping text and/or icons. corner_radius = 0 + # Ignore the dbus closeNotification message. + # Useful to enforce the timeout set by dunst configuration. Without this + # parameter, an application may close the notification sent before the + # user defined timeout. + ignore_dbusclose = false + ### Legacy # Use the Xinerama extension instead of RandR for multi-monitor support. diff --git a/src/dbus.c b/src/dbus.c index ec8e350..fd82060 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -494,7 +494,17 @@ static void dbus_cb_CloseNotification( { guint32 id; g_variant_get(parameters, "(u)", &id); - queues_notification_close_id(id, REASON_SIG); + if (settings.ignore_dbusclose) { + LOG_D("Ignoring CloseNotification message"); + // Stay commpliant by lying to the sender, telling him we closed the notification + if (id > 0) { + struct notification *n = queues_get_by_id(id); + if (n) + signal_notification_closed(n, REASON_SIG); + } + } else { + queues_notification_close_id(id, REASON_SIG); + } wake_up(); g_dbus_method_invocation_return_value(invocation, NULL); g_dbus_connection_flush(connection, NULL, NULL, NULL); @@ -515,8 +525,6 @@ static void dbus_cb_GetServerInformation( void signal_notification_closed(struct notification *n, enum reason reason) { if (!n->dbus_valid) { - LOG_W("Closing notification '%s' not supported. " - "Notification already closed.", n->summary); return; } diff --git a/src/queues.c b/src/queues.c index 8a73e09..f0326d1 100644 --- a/src/queues.c +++ b/src/queues.c @@ -506,6 +506,27 @@ gint64 queues_get_next_datachange(gint64 time) return sleep != G_MAXINT64 ? sleep : -1; } + + + +/* see queues.h */ +struct notification* queues_get_by_id(int id) +{ + assert(id > 0); + + GQueue *recqueues[] = { displayed, waiting, history }; + for (int i = 0; i < sizeof(recqueues)/sizeof(GQueue*); i++) { + for (GList *iter = g_queue_peek_head_link(recqueues[i]); iter; + iter = iter->next) { + struct notification *cur = iter->data; + if (cur->id == id) + return cur; + } + } + + return NULL; +} + /** * Helper function for queues_teardown() to free a single notification * @@ -527,4 +548,6 @@ void queues_teardown(void) g_queue_free_full(waiting, teardown_notification); waiting = NULL; } + + /* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */ diff --git a/src/queues.h b/src/queues.h index caf8d1c..cc233d2 100644 --- a/src/queues.h +++ b/src/queues.h @@ -145,6 +145,17 @@ void queues_update(struct dunst_status status); */ gint64 queues_get_next_datachange(gint64 time); +/** + * Get the notification which has the given id in the displayed and waiting queue or + * NULL if not found + * + * @param the id searched for. + * + * @return the `id` notification or NULL + */ +struct notification* queues_get_by_id(int id); + + /** * Remove all notifications from all list and free the notifications * diff --git a/src/settings.c b/src/settings.c index e67446b..4477403 100644 --- a/src/settings.c +++ b/src/settings.c @@ -176,6 +176,11 @@ void load_settings(char *cmdline_config_path) "word_wrap", "-word_wrap", defaults.word_wrap, "Truncating long lines or do word wrap" ); + settings.ignore_dbusclose = option_get_bool( + "global", + "ignore_dbusclose", "-ignore_dbusclose", defaults.ignore_dbusclose, + "Ignore dbus CloseNotification events" + ); { char *c = option_get_string( diff --git a/src/settings.h b/src/settings.h index 6622880..9f1e042 100644 --- a/src/settings.h +++ b/src/settings.h @@ -59,6 +59,7 @@ struct settings { int history_length; int show_indicators; int word_wrap; + int ignore_dbusclose; enum ellipsize ellipsize; int ignore_newline; int line_height; diff --git a/test/queues.c b/test/queues.c index f60049b..b1c39b2 100644 --- a/test/queues.c +++ b/test/queues.c @@ -740,6 +740,29 @@ TEST test_queues_timeout_before_paused(void) PASS(); } +TEST test_queue_find_by_id(void) +{ + struct notification *n; + int id; + queues_init(); + + n = test_notification("n", 0); + queues_notification_insert(n); + n = test_notification("n1", 0); + queues_notification_insert(n); + id = n->id; + n = test_notification("n2", 0); + queues_notification_insert(n); + + n = queues_get_by_id(id); + + ASSERT(n->id == id); + ASSERT(!strncmp(n->summary, "n1", 2)); + + queues_teardown(); + PASS(); +} + SUITE(suite_queues) { settings.icon_path = ""; @@ -770,6 +793,7 @@ SUITE(suite_queues) RUN_TEST(test_queues_update_seeping); RUN_TEST(test_queues_update_xmore); RUN_TEST(test_queues_timeout_before_paused); + RUN_TEST(test_queue_find_by_id); settings.icon_path = NULL; }