diff --git a/dunst.c b/dunst.c index 327927f..d87d858 100644 --- a/dunst.c +++ b/dunst.c @@ -242,8 +242,7 @@ void check_timeouts(void) if (difftime(now, current->start) > current->timeout) { /* l_move changes iter->next, so we need to store it beforehand */ next = iter->next; - l_move(displayed_notifications, notification_history, - iter); + close_notification(current, 1); iter = next; continue; @@ -520,6 +519,7 @@ char void handle_mouse_click(XEvent ev) { l_node *iter = displayed_notifications->head; + notification *n; int i; if (ev.xbutton.button == Button3) { move_all_to_history(); @@ -534,7 +534,8 @@ void handle_mouse_click(XEvent ev) iter = iter->next; } } - l_move(displayed_notifications, notification_history, iter); + n = (notification *) iter->data; + close_notification(n, 2); } } @@ -564,9 +565,9 @@ void handleXEvents(void) case KeyPress: if (XLookupKeysym(&ev.xkey, 0) == key) { if (!l_is_empty(displayed_notifications)) { - l_move(displayed_notifications, - notification_history, - displayed_notifications->head); + notification *n = (notification *) + displayed_notifications->head->data; + close_notification(n, 2); } } if (XLookupKeysym(&ev.xkey, 0) == history_key) { @@ -579,14 +580,17 @@ void handleXEvents(void) void move_all_to_history() { l_node *node; + notification *n; while (!l_is_empty(displayed_notifications)) { node = displayed_notifications->head; - l_move(displayed_notifications, notification_history, node); + n = (notification *) node->data; + close_notification(n, 2); } while (!l_is_empty(notification_queue)) { node = notification_queue->head; - l_move(notification_queue, notification_history, node); + n = (notification *) node->data; + close_notification(n, 2); } } @@ -662,7 +666,7 @@ int init_notification(notification * n, int id) if (id == 0) { n->id = ++next_notification_id; } else { - close_notification(id); + close_notification_by_id(id, -1); } l_push(notification_queue, n); @@ -670,16 +674,25 @@ int init_notification(notification * n, int id) return n->id; } -int close_notification(int id) +/* + * reasons: + * -1 -> notification is a replacement, no NotificationClosed signal emitted + * 1 -> the notification expired + * 2 -> the notification was dismissed by the user_data + * 3 -> The notification was closed by a call to CloseNotification + */ +int close_notification_by_id(int id, int reason) { l_node *iter; + notification *target = NULL; for (iter = displayed_notifications->head; iter; iter = iter->next) { notification *n = (notification *) iter->data; if (n->id == id) { l_move(displayed_notifications, notification_history, iter); - return True; + target = n; + break; } } @@ -688,11 +701,21 @@ int close_notification(int id) if (n->id == id) { l_move(displayed_notifications, notification_history, iter); - return True; + target = n; + break; } } - return False; + if (reason > 0 && reason < 4) { + notificationClosed(target, reason); + } + + return target == NULL; +} + +int close_notification(notification * n, int reason) +{ + return close_notification_by_id(n->id, reason); } rule_t *initrule(void) @@ -1127,8 +1150,8 @@ dunst_ini_handle(void *user_data, const char *section, /* FIXME warning on unknown alignment */ } else if (strcmp(name, "show_age_threshold") == 0) show_age_threshold = atoi(value); - else if (strcmp(name, "sticky_history") == 0) - sticky_history = dunst_ini_get_boolean(value); + else if (strcmp(name, "sticky_history") == 0) + sticky_history = dunst_ini_get_boolean(value); } else if (strcmp(section, "urgency_low") == 0) { if (strcmp(name, "background") == 0) lowbgcolor = dunst_ini_get_string(value); diff --git a/dunst.h b/dunst.h index 4af2ae6..8fa5f18 100644 --- a/dunst.h +++ b/dunst.h @@ -13,7 +13,7 @@ #define ColFG 1 #define ColBG 0 -enum alignment {left, center, right}; +enum alignment { left, center, right }; typedef struct _rule_t { char *name; @@ -39,6 +39,7 @@ typedef struct _notification { char *icon; char *msg; const char *format; + char *dbus_client; time_t start; time_t timestamp; int timeout; @@ -61,5 +62,6 @@ typedef struct _dimension_t { /* return id of notification */ int init_notification(notification * n, int id); -int close_notification(int id); +int close_notification(notification * n, int reason); +int close_notification_by_id(int id, int reason); void map_win(void); diff --git a/dunst_dbus.c b/dunst_dbus.c index 06b1a01..15bbf9b 100644 --- a/dunst_dbus.c +++ b/dunst_dbus.c @@ -35,7 +35,6 @@ _extract_hint(const char *name, const char *hint_name, } } - static const char *introspect = "" "" " " @@ -208,9 +207,7 @@ void closeNotification(DBusMessage * dmsg) _extract_basic(DBUS_TYPE_UINT32, &args, &id); - close_notification(id); - - /* TODO org.freedesktop.Notifications.NotificationClosed */ + close_notification_by_id(id, 3); dbus_connection_send(dbus_conn, reply, &dbus_serial); dbus_connection_flush(dbus_conn); @@ -253,6 +250,29 @@ void getServerInformation(DBusMessage * dmsg) dbus_message_unref(reply); } +void notificationClosed(notification * n, int reason) +{ + DBusMessage *dmsg; + DBusMessageIter args; + int id = n->id; + + dmsg = + dbus_message_new_signal("/org/freedesktop/Notifications", + "org.freedesktop.Notifications", + "NotificationClosed"); + dbus_message_iter_init_append(dmsg, &args); + dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &id); + dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &reason); + + dbus_message_set_destination(dmsg, n->dbus_client); + + dbus_connection_send(dbus_conn, dmsg, &dbus_serial); + + dbus_message_unref(dmsg); + + dbus_connection_flush(dbus_conn); +} + void notify(DBusMessage * dmsg) { DBusMessage *reply; @@ -330,6 +350,7 @@ void notify(DBusMessage * dmsg) n->icon = strdup(icon); n->timeout = expires; n->urgency = urgency; + n->dbus_client = strdup(dbus_message_get_sender(dmsg)); for (i = 0; i < ColLast; i++) { n->color_strings[i] = NULL; } diff --git a/dunst_dbus.h b/dunst_dbus.h index f5b3fc8..ac5a190 100644 --- a/dunst_dbus.h +++ b/dunst_dbus.h @@ -11,6 +11,7 @@ void notify(DBusMessage * msg); void getCapabilities(DBusMessage * dmsg); void closeNotification(DBusMessage * dmsg); void getServerInformation(DBusMessage * dmsg); +void notificationClosed(notification * n, int reason); #endif