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)
This commit is contained in:
matclab 2020-07-12 12:50:18 +02:00
parent 762d37758d
commit 0a08cefc68
4 changed files with 67 additions and 1 deletions

View File

@ -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);

View File

@ -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: */

View File

@ -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
*

View File

@ -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;
}