Merge lp:~donadigo/wingpanel-indicator-notifications/close-notification-support-new into lp:~wingpanel-devs/wingpanel-indicator-notifications/wingpanel-indicator-notifications

Proposed by Adam Bieńkowski
Status: Merged
Approved by: Corentin Noël
Approved revision: 128
Merged at revision: 126
Proposed branch: lp:~donadigo/wingpanel-indicator-notifications/close-notification-support-new
Merge into: lp:~wingpanel-devs/wingpanel-indicator-notifications/wingpanel-indicator-notifications
Diff against target: 251 lines (+95/-46)
5 files modified
src/Indicator.vala (+15/-1)
src/Services/Notification.vala (+5/-0)
src/Services/NotificationsMonitor.vala (+69/-45)
src/Widgets/NotificationEntry.vala (+2/-0)
src/Widgets/NotificationsList.vala (+4/-0)
To merge this branch: bzr merge lp:~donadigo/wingpanel-indicator-notifications/close-notification-support-new
Reviewer Review Type Date Requested Status
Corentin Noël Approve
Review via email: mp+312735@code.launchpad.net

Commit message

Add support for withdrawing the notifications from the indicator

Description of the change

Fixes bug #1631470: "Allow apps to withdraw a notification".

This branch adds support for withdrawing the notifications from the indicator. Note, that this will not work at the moment with GLib based applications, this is issue within the GLib itself, more info and patch here: https://bugzilla.gnome.org/show_bug.cgi?id=775765

Changes include the removal of hacky sending the notification to the server by the indicator to determine the notification ID. This is now done by waiting for server to return the ID of the notification and then it gets displayed in the UI. This doesn't change the time the notification arrives in the indicator, we only wait for the response, not the actual show / hide of the notification, that's up to the server.

Please test extensively.

To post a comment you must log in.
Revision history for this message
Corentin Noël (tintou) wrote :

Everything seems nice here

review: Approve
Revision history for this message
RabbitBot (rabbitbot-a) wrote :

There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/Indicator.vala'
--- src/Indicator.vala 2016-08-03 06:28:36 +0000
+++ src/Indicator.vala 2016-12-12 20:06:10 +0000
@@ -102,7 +102,10 @@
102102
103 nlist.close_popover.connect (() => close ());103 nlist.close_popover.connect (() => close ());
104 nlist.switch_stack.connect (on_switch_stack);104 nlist.switch_stack.connect (on_switch_stack);
105 NotificationMonitor.get_instance ().received.connect (on_notification_received);105
106 var monitor = NotificationMonitor.get_instance ();
107 monitor.notification_received.connect (on_notification_received);
108 monitor.notification_closed.connect (on_notification_closed);
106109
107 NotifySettings.get_instance ().changed[NotifySettings.DO_NOT_DISTURB_KEY].connect (() => {110 NotifySettings.get_instance ().changed[NotifySettings.DO_NOT_DISTURB_KEY].connect (() => {
108 not_disturb_switch.get_switch ().active = NotifySettings.get_instance ().do_not_disturb;111 not_disturb_switch.get_switch ().active = NotifySettings.get_instance ().do_not_disturb;
@@ -171,6 +174,17 @@
171 dynamic_icon.set_main_icon_name (get_display_icon_name ()); 174 dynamic_icon.set_main_icon_name (get_display_icon_name ());
172 }175 }
173176
177 private void on_notification_closed (uint32 id) {
178 foreach (var app_entry in nlist.get_entries ()) {
179 foreach (var item in app_entry.app_notifications) {
180 if (item.notification.id == id) {
181 item.notification.close ();
182 return;
183 }
184 }
185 }
186 }
187
174 private void restore_previous_session () {188 private void restore_previous_session () {
175 var previous_session = Session.get_instance ().get_session_notifications ();189 var previous_session = Session.get_instance ().get_session_notifications ();
176 previous_session.foreach ((notification) => {190 previous_session.foreach ((notification) => {
177191
=== modified file 'src/Services/Notification.vala'
--- src/Services/Notification.vala 2016-08-03 06:28:36 +0000
+++ src/Services/Notification.vala 2016-12-12 20:06:10 +0000
@@ -37,6 +37,7 @@
37 public string desktop_id;37 public string desktop_id;
38 public AppInfo? app_info = null;38 public AppInfo? app_info = null;
3939
40 public signal void closed ();
40 public signal bool time_changed (TimeSpan span);41 public signal bool time_changed (TimeSpan span);
4142
42 private enum Column {43 private enum Column {
@@ -129,6 +130,10 @@
129 return app_info != null && hints.lookup_value (X_CANONICAL_PRIVATE_KEY, null) == null;130 return app_info != null && hints.lookup_value (X_CANONICAL_PRIVATE_KEY, null) == null;
130 }131 }
131132
133 public void close () {
134 closed ();
135 }
136
132 public bool run_default_action () {137 public bool run_default_action () {
133 if (DEFAULT_ACTION in actions && NotificationMonitor.get_instance ().notifications_iface != null) {138 if (DEFAULT_ACTION in actions && NotificationMonitor.get_instance ().notifications_iface != null) {
134 NotificationMonitor.get_instance ().notifications_iface.action_invoked (DEFAULT_ACTION, id);139 NotificationMonitor.get_instance ().notifications_iface.action_invoked (DEFAULT_ACTION, id);
135140
=== modified file 'src/Services/NotificationsMonitor.vala'
--- src/Services/NotificationsMonitor.vala 2016-06-20 12:40:25 +0000
+++ src/Services/NotificationsMonitor.vala 2016-12-12 20:06:10 +0000
@@ -23,17 +23,18 @@
23public class NotificationMonitor : Object {23public class NotificationMonitor : Object {
24 private const string NOTIFY_IFACE = "org.freedesktop.Notifications";24 private const string NOTIFY_IFACE = "org.freedesktop.Notifications";
25 private const string NOTIFY_PATH = "/org/freedesktop/Notifications";25 private const string NOTIFY_PATH = "/org/freedesktop/Notifications";
26 private const string MATCH_STRING = "eavesdrop='true',type='method_call',interface='org.freedesktop.Notifications',member='Notify'";26 private const string METHOD_CALL_MATCH_STRING = "eavesdrop='true',type='method_call',interface='org.freedesktop.Notifications'";
27 private const string METHOD_RETURN_MATCH_STRING = "eavesdrop='true',type='method_return'";
28 private const string ERROR_MATCH_STRING = "eavesdrop='true',type='error'";
27 private const uint32 REASON_DISMISSED = 2;29 private const uint32 REASON_DISMISSED = 2;
2830
29 private static NotificationMonitor? instance = null;31 private static NotificationMonitor? instance = null;
3032
31 private DBusConnection connection;33 private DBusConnection connection;
32 public INotifications? notifications_iface = null;34 private DBusMessage? awaiting_reply = null;
33 public IDBus? dbus_iface = null;
34 private uint32 id_counter = 0;
3535
36 public signal void received (DBusMessage message, uint32 id);36 public signal void notification_received (DBusMessage message, uint32 id);
37 public signal void notification_closed (uint32 id);
3738
38 public static NotificationMonitor get_instance () {39 public static NotificationMonitor get_instance () {
39 if (instance == null) {40 if (instance == null) {
@@ -43,75 +44,98 @@
43 return instance;44 return instance;
44 }45 }
4546
47 public INotifications? notifications_iface = null;
48
46 private NotificationMonitor () {49 private NotificationMonitor () {
47 try {50 try {
48 connection = Bus.get_sync (BusType.SESSION);51 connection = Bus.get_sync (BusType.SESSION);
49 add_filter (); 52 add_rule (ERROR_MATCH_STRING);
53 add_rule (METHOD_CALL_MATCH_STRING);
54 add_rule (METHOD_RETURN_MATCH_STRING);
55 connection.add_filter (message_filter);
50 } catch (Error e) {56 } catch (Error e) {
51 error ("%s\n", e.message);57 error ("%s\n", e.message);
52 }58 }
59
60 try {
61 notifications_iface = Bus.get_proxy_sync (BusType.SESSION, NOTIFY_IFACE, NOTIFY_PATH);
62 } catch (Error e) {
63 error ("%s\n", e.message);
64 }
53 }65 }
5466
55 private void add_filter () {67 private void add_rule (string rule) {
56 var message = new DBusMessage.method_call ("org.freedesktop.DBus",68 var message = new DBusMessage.method_call ("org.freedesktop.DBus",
57 "/org/freedesktop/DBus",69 "/org/freedesktop/DBus",
58 "org.freedesktop.DBus",70 "org.freedesktop.DBus",
59 "AddMatch");71 "AddMatch");
6072
61 var body = new Variant.parsed ("(%s,)", MATCH_STRING);73 var body = new Variant.parsed ("(%s,)", rule);
62 message.set_body (body);74 message.set_body (body);
63 75
64 try {76 try {
65 notifications_iface = Bus.get_proxy_sync (BusType.SESSION, NOTIFY_IFACE, NOTIFY_PATH);
66 } catch (Error e) {
67 error ("%s\n", e.message);
68 }
69
70 id_counter = get_current_notification_id ();
71 try {
72 connection.send_message (message, DBusSendMessageFlags.NONE, null);77 connection.send_message (message, DBusSendMessageFlags.NONE, null);
73 } catch (Error e) {78 } catch (Error e) {
74 error ("%s\n", e.message);79 error ("%s\n", e.message);
75 }80 }
76
77 connection.add_filter (message_filter);
78 }81 }
7982
80 private DBusMessage message_filter (DBusConnection con, owned DBusMessage message, bool incoming) {83 private DBusMessage message_filter (DBusConnection con, owned DBusMessage message, bool incoming) {
81 if (incoming) {84 if (incoming && message.get_interface () == NOTIFY_IFACE && message.get_message_type () == DBusMessageType.METHOD_CALL) {
82 if ((message.get_message_type () == DBusMessageType.METHOD_CALL) &&85 if (message.get_member () == "Notify") {
83 (message.get_interface () == NOTIFY_IFACE) &&86 try {
84 (message.get_member () == "Notify")) {87 awaiting_reply = message.copy ();
85 uint32 replaces_id = message.get_body ().get_child_value (1).get_uint32 ();88 } catch (Error e) {
86 uint32 current_id = replaces_id; 89 warning (e.message);
8790 }
88 if (replaces_id == 0) {91 } else if (message.get_member () == "CloseNotification") {
89 id_counter++;92 var body = message.get_body ();
90 current_id = id_counter;93 if (body.n_children () != 1) {
91 }94 return message;
9295 }
96
97 var child = body.get_child_value (0);
98 if (!child.is_of_type (VariantType.UINT32)) {
99 return message;
100 }
101
102 uint32 id = child.get_uint32 ();
93 Idle.add (() => {103 Idle.add (() => {
94 this.received (message, current_id);104 notification_closed (id);
95 message = null;
96 return false;105 return false;
97 });106 });
98107 }
99 return null;108
109 return null;
110 } else if (awaiting_reply != null && awaiting_reply.get_serial () == message.get_reply_serial ()) {
111 if (message.get_message_type () == DBusMessageType.METHOD_RETURN) {
112 var body = message.get_body ();
113 if (body.n_children () != 1) {
114 return message;
115 }
116
117 var child = body.get_child_value (0);
118 if (!child.is_of_type (VariantType.UINT32)) {
119 return message;
120 }
121
122 uint32 id = child.get_uint32 ();
123 try {
124 var copy = awaiting_reply.copy ();
125 Idle.add (() => {
126 notification_received (copy, id);
127 return false;
128 });
129 } catch (Error e) {
130 warning (e.message);
131 }
132
133 awaiting_reply = null;
134 } else if (message.get_message_type () == DBusMessageType.ERROR) {
135 awaiting_reply = null;
100 }136 }
101 }137 }
102138
103 return message;139 return message;
104 }140 }
105
106 /* Check what's the current notification id */
107 private uint32 get_current_notification_id () {
108 var hints = new HashTable<string, Variant> (str_hash, str_equal);
109 hints.insert ("suppress-sound", new Variant.boolean (true));
110 string[] actions = {};
111 try {
112 return notifications_iface.notify ("", 0, "", "", "", actions, hints, 1);
113 } catch (Error e) {
114 error ("%s\n", e.message);
115 }
116 }
117}141}
118142
=== modified file 'src/Widgets/NotificationEntry.vala'
--- src/Widgets/NotificationEntry.vala 2016-07-20 20:36:57 +0000
+++ src/Widgets/NotificationEntry.vala 2016-12-12 20:06:10 +0000
@@ -53,6 +53,8 @@
53 return active;53 return active;
54 });54 });
5555
56 notification.closed.connect (() => clear ());
57
56 hexpand = true;58 hexpand = true;
57 59
58 var grid = new Gtk.Grid ();60 var grid = new Gtk.Grid ();
5961
=== modified file 'src/Widgets/NotificationsList.vala'
--- src/Widgets/NotificationsList.vala 2016-11-20 13:30:03 +0000
+++ src/Widgets/NotificationsList.vala 2016-12-12 20:06:10 +0000
@@ -58,6 +58,10 @@
58 }58 }
5959
6060
61 public unowned List<AppEntry> get_entries () {
62 return app_entries;
63 }
64
61 public uint get_entries_length () {65 public uint get_entries_length () {
62 return app_entries.length ();66 return app_entries.length ();
63 }67 }

Subscribers

People subscribed via source and target branches

to all changes: