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

Proposed by Adam Bieńkowski
Status: Rejected
Rejected by: Danielle Foré
Proposed branch: lp:~donadigo/wingpanel-indicator-notifications/close-notification-support
Merge into: lp:~wingpanel-devs/wingpanel-indicator-notifications/wingpanel-indicator-notifications
Diff against target: 532 lines (+260/-28) (has conflicts)
7 files modified
src/CMakeLists.txt (+1/-1)
src/Indicator.vala (+14/-0)
src/Services/Notification.vala (+29/-1)
src/Services/NotificationMonitor.vala (+56/-26)
src/Widgets/AppEntry.vala (+14/-0)
src/Widgets/NotificationEntry.vala (+27/-0)
src/Widgets/NotificationsList.vala (+119/-0)
Text conflict in src/Indicator.vala
Text conflict in src/Services/Notification.vala
Text conflict in src/Widgets/AppEntry.vala
Text conflict in src/Widgets/NotificationEntry.vala
Text conflict in src/Widgets/NotificationsList.vala
To merge this branch: bzr merge lp:~donadigo/wingpanel-indicator-notifications/close-notification-support
Reviewer Review Type Date Requested Status
elementary Pantheon team Pending
Review via email: mp+308067@code.launchpad.net

Commit message

* Add CloseNotification support.

Description of the change

This branch adds CloseNotification call support so apps can withdraw the notifications and they will get removed from the indicator.

To post a comment you must log in.

Unmerged revisions

98. By Adam Bieńkowski

Added close notification support

97. By Adam Bieńkowski

Clicking a notification now opens / focuses the app; general code improvements

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2016-05-27 15:10:53 +0000
+++ src/CMakeLists.txt 2016-10-10 16:00:06 +0000
@@ -20,7 +20,7 @@
20 Widgets/NotificationEntry.vala20 Widgets/NotificationEntry.vala
21 Widgets/AppEntry.vala21 Widgets/AppEntry.vala
22 Widgets/SeparatorEntry.vala22 Widgets/SeparatorEntry.vala
23 Services/NotificationsMonitor.vala23 Services/NotificationMonitor.vala
24 Services/Notification.vala24 Services/Notification.vala
25 Services/NotifySettings.vala25 Services/NotifySettings.vala
26 Services/Session.vala26 Services/Session.vala
2727
=== modified file 'src/Indicator.vala'
--- src/Indicator.vala 2016-08-03 06:28:36 +0000
+++ src/Indicator.vala 2016-10-10 16:00:06 +0000
@@ -103,6 +103,7 @@
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 NotificationMonitor.get_instance ().received.connect (on_notification_received);
106 NotificationMonitor.get_instance ().close_notification.connect (on_notification_closed);
106107
107 NotifySettings.get_instance ().changed[NotifySettings.DO_NOT_DISTURB_KEY].connect (() => {108 NotifySettings.get_instance ().changed[NotifySettings.DO_NOT_DISTURB_KEY].connect (() => {
108 not_disturb_switch.get_switch ().active = NotifySettings.get_instance ().do_not_disturb;109 not_disturb_switch.get_switch ().active = NotifySettings.get_instance ().do_not_disturb;
@@ -160,6 +161,15 @@
160 dynamic_icon.set_main_icon_name (get_display_icon_name ()); 161 dynamic_icon.set_main_icon_name (get_display_icon_name ());
161 }162 }
162163
164 private void on_notification_closed (uint32 id) {
165 foreach (var item in nlist.items) {
166 if (item.notification.id == id) {
167 item.notification.close ();
168 return;
169 }
170 }
171 }
172
163 private void on_switch_stack (bool show_list) {173 private void on_switch_stack (bool show_list) {
164 clear_all_btn.sensitive = show_list;174 clear_all_btn.sensitive = show_list;
165 if (show_list) {175 if (show_list) {
@@ -181,7 +191,11 @@
181 private string get_display_icon_name () {191 private string get_display_icon_name () {
182 if (NotifySettings.get_instance ().do_not_disturb) {192 if (NotifySettings.get_instance ().do_not_disturb) {
183 return "notification-disabled-symbolic";193 return "notification-disabled-symbolic";
194<<<<<<< TREE
184 } else if (nlist != null && nlist.get_entries_length () > 0) {195 } else if (nlist != null && nlist.get_entries_length () > 0) {
196=======
197 } else if (nlist != null && nlist.items.length () > 0) {
198>>>>>>> MERGE-SOURCE
185 return "notification-new-symbolic";199 return "notification-new-symbolic";
186 }200 }
187 201
188202
=== modified file 'src/Services/Notification.vala'
--- src/Services/Notification.vala 2016-08-03 06:28:36 +0000
+++ src/Services/Notification.vala 2016-10-10 16:00:06 +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 {
@@ -126,6 +127,7 @@
126 }127 }
127128
128 public bool get_is_valid () {129 public bool get_is_valid () {
130<<<<<<< TREE
129 return app_info != null && hints.lookup_value (X_CANONICAL_PRIVATE_KEY, null) == null;131 return app_info != null && hints.lookup_value (X_CANONICAL_PRIVATE_KEY, null) == null;
130 }132 }
131133
@@ -150,6 +152,32 @@
150 }152 }
151153
152 return window; 154 return window;
155=======
156 return app_name in OTHER_WHITELIST || appinfo != null;
157 }
158
159 public bool run_default_action () {
160 if (DEFAULT_ACTION in actions) {
161 INotifications? notifications_iface = NotificationMonitor.get_notifications_iface ();
162 if (notifications_iface != null) {
163 notifications_iface.action_invoked (DEFAULT_ACTION, id);
164 return true;
165 }
166 }
167
168 return false;
169 }
170
171 public void close () {
172 closed ();
173 }
174
175 private void set_properties () {
176 if (app_name in OTHER_WHITELIST) {
177 display_name = _("Other");
178 app_icon = "dialog-information";
179 }
180>>>>>>> MERGE-SOURCE
153 }181 }
154182
155 private void setup_pid () {183 private void setup_pid () {
@@ -167,7 +195,7 @@
167 }195 }
168196
169 try {197 try {
170 IDBus? dbus_iface = Bus.get_proxy_sync (BusType.SESSION, "org.freedesktop.DBus", "/");198 IDBus? dbus_iface = NotificationMonitor.get_dbus_iface ();
171 if (dbus_iface != null && dbus_iface.name_has_owner (sender)) {199 if (dbus_iface != null && dbus_iface.name_has_owner (sender)) {
172 pid = dbus_iface.get_connection_unix_process_id (sender);200 pid = dbus_iface.get_connection_unix_process_id (sender);
173 }201 }
174202
=== renamed file 'src/Services/NotificationsMonitor.vala' => 'src/Services/NotificationMonitor.vala'
--- src/Services/NotificationsMonitor.vala 2016-06-20 12:40:25 +0000
+++ src/Services/NotificationMonitor.vala 2016-10-10 16:00:06 +0000
@@ -23,17 +23,20 @@
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 DBUS_IFACE = "org.freedesktop.DBus";
27 private const string DBUS_PATH = "/";
28 private const string MATCH_STRING = "eavesdrop='true',type='method_call',interface='org.freedesktop.Notifications'";
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;
32 private static INotifications? notifications_iface = null;
33 private static IDBus? dbus_iface = null;
3034
31 private DBusConnection connection;35 private DBusConnection connection;
32 public INotifications? notifications_iface = null;
33 public IDBus? dbus_iface = null;
34 private uint32 id_counter = 0;36 private uint32 id_counter = 0;
3537
36 public signal void received (DBusMessage message, uint32 id);38 public signal void received (DBusMessage message, uint32 id);
39 public signal void close_notification (uint32 id);
3740
38 public static NotificationMonitor get_instance () {41 public static NotificationMonitor get_instance () {
39 if (instance == null) {42 if (instance == null) {
@@ -43,6 +46,30 @@
43 return instance;46 return instance;
44 }47 }
4548
49 public static INotifications? get_notifications_iface () {
50 if (notifications_iface == null) {
51 try {
52 notifications_iface = Bus.get_proxy_sync (BusType.SESSION, NOTIFY_IFACE, NOTIFY_PATH);
53 } catch (Error e) {
54 warning ("%s\n", e.message);
55 }
56 }
57
58 return notifications_iface;
59 }
60
61 public static IDBus? get_dbus_iface () {
62 if (dbus_iface == null) {
63 try {
64 dbus_iface = Bus.get_proxy_sync (BusType.SESSION, DBUS_IFACE, DBUS_PATH);
65 } catch (Error e) {
66 warning ("%s\n", e.message);
67 }
68 }
69
70 return dbus_iface;
71 }
72
46 private NotificationMonitor () {73 private NotificationMonitor () {
47 try {74 try {
48 connection = Bus.get_sync (BusType.SESSION);75 connection = Bus.get_sync (BusType.SESSION);
@@ -61,12 +88,6 @@
61 var body = new Variant.parsed ("(%s,)", MATCH_STRING);88 var body = new Variant.parsed ("(%s,)", MATCH_STRING);
62 message.set_body (body);89 message.set_body (body);
63 90
64 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 ();91 id_counter = get_current_notification_id ();
71 try {92 try {
72 connection.send_message (message, DBusSendMessageFlags.NONE, null);93 connection.send_message (message, DBusSendMessageFlags.NONE, null);
@@ -78,24 +99,33 @@
78 }99 }
79100
80 private DBusMessage message_filter (DBusConnection con, owned DBusMessage message, bool incoming) {101 private DBusMessage message_filter (DBusConnection con, owned DBusMessage message, bool incoming) {
81 if (incoming) {102 if (incoming) {
82 if ((message.get_message_type () == DBusMessageType.METHOD_CALL) &&103 if (message.get_message_type () == DBusMessageType.METHOD_CALL &&
83 (message.get_interface () == NOTIFY_IFACE) &&104 message.get_interface () == NOTIFY_IFACE) {
84 (message.get_member () == "Notify")) {105 if (message.get_member () == "Notify") {
85 uint32 replaces_id = message.get_body ().get_child_value (1).get_uint32 ();106 uint32 replaces_id = message.get_body ().get_child_value (1).get_uint32 ();
86 uint32 current_id = replaces_id; 107 uint32 current_id = replaces_id;
87108
88 if (replaces_id == 0) {109 if (replaces_id == 0) {
89 id_counter++;110 id_counter++;
90 current_id = id_counter;111 current_id = id_counter;
112 }
113
114 Idle.add (() => {
115 received (message, current_id);
116 message = null;
117 return false;
118 });
119 } else if (message.get_member () == "CloseNotification") {
120 uint32 id = message.get_body ().get_child_value (0).get_uint32 ();
121
122 Idle.add (() => {
123 close_notification (id);
124 message = null;
125 return false;
126 });
91 }127 }
92128
93 Idle.add (() => {
94 this.received (message, current_id);
95 message = null;
96 return false;
97 });
98
99 return null;129 return null;
100 }130 }
101 }131 }
@@ -109,7 +139,7 @@
109 hints.insert ("suppress-sound", new Variant.boolean (true));139 hints.insert ("suppress-sound", new Variant.boolean (true));
110 string[] actions = {};140 string[] actions = {};
111 try {141 try {
112 return notifications_iface.notify ("", 0, "", "", "", actions, hints, 1);142 return get_notifications_iface ().notify ("", 0, "", "", "", actions, hints, 1);
113 } catch (Error e) {143 } catch (Error e) {
114 error ("%s\n", e.message);144 error ("%s\n", e.message);
115 }145 }
116146
=== modified file 'src/Widgets/AppEntry.vala'
--- src/Widgets/AppEntry.vala 2016-07-20 20:11:51 +0000
+++ src/Widgets/AppEntry.vala 2016-10-10 16:00:06 +0000
@@ -66,8 +66,22 @@
66 return null;66 return null;
67 }67 }
6868
69<<<<<<< TREE
69 var entry = app_notifications.first ().data;70 var entry = app_notifications.first ().data;
70 return entry.notification.get_app_window ();71 return entry.notification.get_app_window ();
72=======
73 public void update_app_window () {
74 if (app_notifications.length () == 0) {
75 return;
76 }
77
78 var notification_entry = app_notifications.nth_data (0);
79 app_window = notification_entry.get_app_window ();
80 }
81
82 public unowned List<NotificationEntry> get_notifications () {
83 return app_notifications;
84>>>>>>> MERGE-SOURCE
71 }85 }
7286
73 public void add_notification_entry (NotificationEntry entry) {87 public void add_notification_entry (NotificationEntry entry) {
7488
=== modified file 'src/Widgets/NotificationEntry.vala'
--- src/Widgets/NotificationEntry.vala 2016-07-20 20:36:57 +0000
+++ src/Widgets/NotificationEntry.vala 2016-10-10 16:00:06 +0000
@@ -53,8 +53,35 @@
53 return active;53 return active;
54 });54 });
5555
56 notification.closed.connect (() => {
57 clear ();
58 });
59
56 hexpand = true;60 hexpand = true;
61<<<<<<< TREE
57 62
63=======
64 add_widgets ();
65
66 if (notification.data_session) {
67 notification.time_changed (notification.timestamp.difference (new DateTime.now_local ()));
68 }
69 }
70
71 public Wnck.Window? get_app_window () {
72 Wnck.Window? window = null;
73 Wnck.Screen.get_default ().get_windows ().@foreach ((_window) => {
74 if (_window.get_pid () == notification.pid) {
75 window = _window;
76 return;
77 }
78 });
79
80 return window;
81 }
82
83 private void add_widgets () {
84>>>>>>> MERGE-SOURCE
58 var grid = new Gtk.Grid ();85 var grid = new Gtk.Grid ();
59 grid.margin_start = 40;86 grid.margin_start = 40;
60 grid.margin_end = 6;87 grid.margin_end = 6;
6188
=== modified file 'src/Widgets/NotificationsList.vala'
--- src/Widgets/NotificationsList.vala 2016-07-21 12:52:41 +0000
+++ src/Widgets/NotificationsList.vala 2016-10-10 16:00:06 +0000
@@ -18,7 +18,11 @@
18public class NotificationsList : Gtk.ListBox {18public class NotificationsList : Gtk.ListBox {
19 public signal void switch_stack (bool show_list);19 public signal void switch_stack (bool show_list);
20 public signal void close_popover ();20 public signal void close_popover ();
21<<<<<<< TREE
2122
23=======
24 public List<NotificationEntry> items;
25>>>>>>> MERGE-SOURCE
22 private List<AppEntry> app_entries;26 private List<AppEntry> app_entries;
23 private HashTable<string, int> table;27 private HashTable<string, int> table;
24 private int counter = 0;28 private int counter = 0;
@@ -47,9 +51,24 @@
4751
48 switch_stack (true);52 switch_stack (true);
4953
54<<<<<<< TREE
50 app_entry.clear.connect (clear_app_entry);55 app_entry.clear.connect (clear_app_entry);
5156
52 counter += 2;57 counter += 2;
58=======
59 app_entry.add_notification_entry (entry);
60 resort_app_entry (app_entry);
61
62 entry.clear.connect (() => {
63 destroy_notification_entry.begin (entry);
64 });
65
66 app_entry.destroy_entry.connect (() => {
67 destroy_app_entry (app_entry);
68 });
69
70 counter += 2;
71>>>>>>> MERGE-SOURCE
5372
54 Session.get_instance ().add_notification (entry.notification);73 Session.get_instance ().add_notification (entry.notification);
5574
@@ -57,11 +76,14 @@
57 show_all ();76 show_all ();
58 }77 }
5978
79<<<<<<< TREE
6080
61 public uint get_entries_length () {81 public uint get_entries_length () {
62 return app_entries.length ();82 return app_entries.length ();
63 }83 }
6484
85=======
86>>>>>>> MERGE-SOURCE
65 public void clear_all () {87 public void clear_all () {
66 app_entries.foreach ((app_entry) => {88 app_entries.foreach ((app_entry) => {
67 app_entry.clear ();89 app_entry.clear ();
@@ -109,15 +131,30 @@
109 AppEntry? app_entry = null;131 AppEntry? app_entry = null;
110 bool add = !(entry.notification.desktop_id in construct_desktop_id_list ());132 bool add = !(entry.notification.desktop_id in construct_desktop_id_list ());
111 if (add) {133 if (add) {
134<<<<<<< TREE
112 app_entry = new AppEntry (entry);135 app_entry = new AppEntry (entry);
136=======
137 var window = entry.get_app_window ();
138 app_entry = new AppEntry (entry, window);
139
140 screen.active_window_changed.connect (() => {
141 if (screen.get_active_window () == app_entry.app_window) {
142 app_entry.clear_btn_entry.clicked ();
143 }
144 });
145>>>>>>> MERGE-SOURCE
113146
114 app_entries.append (app_entry);147 app_entries.append (app_entry);
115 prepend (app_entry);148 prepend (app_entry);
116 insert (entry, 1);149 insert (entry, 1);
117 table.insert (app_entry.app_info.get_id (), 0);150 table.insert (app_entry.app_info.get_id (), 0);
118 } else {151 } else {
152<<<<<<< TREE
119 app_entry = get_app_entry_from_desktop_id (entry.notification.desktop_id);153 app_entry = get_app_entry_from_desktop_id (entry.notification.desktop_id);
120154
155=======
156 app_entry = get_from_app_name (entry.notification.app_name);
157>>>>>>> MERGE-SOURCE
121 if (app_entry != null) {158 if (app_entry != null) {
122 resort_app_entry (app_entry);159 resort_app_entry (app_entry);
123 app_entry.add_notification_entry (entry);160 app_entry.add_notification_entry (entry);
@@ -130,6 +167,7 @@
130 return app_entry;167 return app_entry;
131 }168 }
132169
170<<<<<<< TREE
133 private void monitor_active_window () {171 private void monitor_active_window () {
134 var screen = Wnck.Screen.get_default ();172 var screen = Wnck.Screen.get_default ();
135 screen.active_window_changed.connect (() => {173 screen.active_window_changed.connect (() => {
@@ -142,6 +180,22 @@
142 }180 }
143181
144 private void clear_app_entry (AppEntry app_entry) {182 private void clear_app_entry (AppEntry app_entry) {
183=======
184 private async void destroy_notification_entry (NotificationEntry entry) {
185 entry.destroy ();
186 items.remove (entry);
187 entry.active = false;
188
189 Session.get_instance ().remove_notification (entry.notification);
190 if (items.length () == 0) {
191 clear_all ();
192 }
193
194 update_separators ();
195 }
196
197 private void destroy_app_entry (AppEntry app_entry) {
198>>>>>>> MERGE-SOURCE
145 app_entries.remove (app_entry);199 app_entries.remove (app_entry);
146200
147 app_entry.app_notifications.foreach ((notification_entry) => {201 app_entry.app_notifications.foreach ((notification_entry) => {
@@ -154,6 +208,7 @@
154 if (get_entries_length () == 0) {208 if (get_entries_length () == 0) {
155 clear_all ();209 clear_all ();
156 }210 }
211<<<<<<< TREE
157 }212 }
158213
159 private AppEntry? get_app_entry_from_desktop_id (string desktop_id) {214 private AppEntry? get_app_entry_from_desktop_id (string desktop_id) {
@@ -161,6 +216,31 @@
161 app_entries.foreach ((_app_entry) => {216 app_entries.foreach ((_app_entry) => {
162 if (_app_entry.app_info.get_id () == desktop_id && app_entry == null) {217 if (_app_entry.app_info.get_id () == desktop_id && app_entry == null) {
163 app_entry = _app_entry;218 app_entry = _app_entry;
219=======
220
221 update_separators ();
222 }
223
224 private void resort_app_entry (AppEntry app_entry) {
225 if (get_row_at_index (0) != app_entry) {
226 remove (app_entry);
227 prepend (app_entry);
228 int counter = 1;
229 app_entry.get_notifications ().@foreach ((notification_entry) => {
230 remove (notification_entry);
231 add_item (notification_entry);
232 counter++;
233 });
234 }
235 }
236
237 private AppEntry? get_from_app_name (string app_name) {
238 AppEntry? entry = null;
239 app_entries.@foreach ((_entry) => {
240 if (_entry.app_name == app_name) {
241 entry = _entry;
242 return;
243>>>>>>> MERGE-SOURCE
164 }244 }
165 });245 });
166246
@@ -177,6 +257,7 @@
177 }257 }
178258
179 private void on_row_activated (Gtk.ListBoxRow row) {259 private void on_row_activated (Gtk.ListBoxRow row) {
260<<<<<<< TREE
180 bool close = true;261 bool close = true;
181262
182 if (row is AppEntry) {263 if (row is AppEntry) {
@@ -200,10 +281,34 @@
200281
201 if (close) {282 if (close) {
202 close_popover ();283 close_popover ();
284=======
285 if (row is AppEntry) {
286 var app_entry = (AppEntry)row;
287 if (app_entry.app_window == null) {
288 app_entry.update_app_window ();
289 }
290
291 focus_notification_app (app_entry.app_window,
292 app_entry.appinfo);
293
294 app_entry.clear_btn_entry.clicked ();
295 close_popover ();
296 } else if (row is NotificationEntry) {
297 var notification_entry = (NotificationEntry)row;
298 if (!notification_entry.notification.run_default_action ()) {
299 focus_notification_app (notification_entry.get_app_window (),
300 notification_entry.notification.appinfo);
301 }
302
303 notification_entry.clear ();
304 notification_entry.active = false;
305 close_popover ();
306>>>>>>> MERGE-SOURCE
203 }307 }
204308
205 update_separators ();309 update_separators ();
206 }310 }
311<<<<<<< TREE
207312
208 private bool focus_notification_app (Wnck.Window? app_window, AppInfo? app_info) {313 private bool focus_notification_app (Wnck.Window? app_window, AppInfo? app_info) {
209 if (app_window != null) {314 if (app_window != null) {
@@ -220,4 +325,18 @@
220325
221 return false;326 return false;
222 }327 }
328=======
329
330 private void focus_notification_app (Wnck.Window? app_window, AppInfo? appinfo) {
331 if (app_window != null) {
332 app_window.unminimize (Gtk.get_current_event_time ());
333 } else if (appinfo != null) {
334 try {
335 appinfo.launch (null, null);
336 } catch (Error e) {
337 warning ("%s\n", e.message);
338 }
339 }
340 }
341>>>>>>> MERGE-SOURCE
223}342}

Subscribers

People subscribed via source and target branches

to all changes: