From 762d37758d99dba6ee315d56659241c892e3a367 Mon Sep 17 00:00:00 2001 From: matclab Date: Fri, 10 Jul 2020 14:39:33 +0200 Subject: [PATCH 1/5] Add ignore_dbusclose settings closes #731 --- config.h | 1 + src/dbus.c | 3 ++- src/settings.c | 5 +++++ src/settings.h | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) 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/src/dbus.c b/src/dbus.c index ec8e350..eb39c38 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -494,7 +494,8 @@ static void dbus_cb_CloseNotification( { guint32 id; g_variant_get(parameters, "(u)", &id); - queues_notification_close_id(id, REASON_SIG); + if (!settings.ignore_dbusclose) + 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); 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; From 0a08cefc68a51150560159340f6c97524a70df06 Mon Sep 17 00:00:00 2001 From: matclab Date: Sun, 12 Jul 2020 12:50:18 +0200 Subject: [PATCH 2/5] ignore_dbusclose: send NotificationClosed signal back for spec compliance The notification spec has no concept of disallowing closing notifications, so to make the ignore_dbusclose 'compliant' we choose to lie to the clients that the notification is actually closed, but keep it open. To do this, we send a NotificationClosed signal back (via signal_notification_closed which also call notification_invalidate_action) --- src/dbus.c | 10 +++++++++- src/queues.c | 23 +++++++++++++++++++++++ src/queues.h | 11 +++++++++++ test/queues.c | 24 ++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/dbus.c b/src/dbus.c index eb39c38..20e24ff 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -494,8 +494,16 @@ static void dbus_cb_CloseNotification( { guint32 id; g_variant_get(parameters, "(u)", &id); - if (!settings.ignore_dbusclose) + if (settings.ignore_dbusclose) { + // 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); 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/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; } From 7796f7f848d259e849e9ee582816aa3fc4fcbd9f Mon Sep 17 00:00:00 2001 From: matclab Date: Sun, 12 Jul 2020 12:50:37 +0200 Subject: [PATCH 3/5] ignore_dbusclose: Add dunstrc example and man page section --- docs/dunst.pod | 7 +++++++ dunstrc | 6 ++++++ 2 files changed, 13 insertions(+) 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. From 7bd55a53bf4ee6bf3e1522369a6223c8c499d92f Mon Sep 17 00:00:00 2001 From: matclab Date: Sun, 12 Jul 2020 22:42:26 +0200 Subject: [PATCH 4/5] ignore_dbusclose: Add debug message when ignoring --- src/dbus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dbus.c b/src/dbus.c index 20e24ff..a4501f6 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -495,6 +495,7 @@ static void dbus_cb_CloseNotification( guint32 id; g_variant_get(parameters, "(u)", &id); 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); From 842a5242f797eb9cff28b4c77b06d084ded9e705 Mon Sep 17 00:00:00 2001 From: matclab Date: Tue, 14 Jul 2020 17:52:36 +0200 Subject: [PATCH 5/5] Remove warning message This message has no real added value and is emitted every time a notification is closed when `ignore_dbuclose` is set. --- src/dbus.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/dbus.c b/src/dbus.c index a4501f6..fd82060 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -525,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; }