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
1=== modified file 'src/CMakeLists.txt'
2--- src/CMakeLists.txt 2016-05-27 15:10:53 +0000
3+++ src/CMakeLists.txt 2016-10-10 16:00:06 +0000
4@@ -20,7 +20,7 @@
5 Widgets/NotificationEntry.vala
6 Widgets/AppEntry.vala
7 Widgets/SeparatorEntry.vala
8- Services/NotificationsMonitor.vala
9+ Services/NotificationMonitor.vala
10 Services/Notification.vala
11 Services/NotifySettings.vala
12 Services/Session.vala
13
14=== modified file 'src/Indicator.vala'
15--- src/Indicator.vala 2016-08-03 06:28:36 +0000
16+++ src/Indicator.vala 2016-10-10 16:00:06 +0000
17@@ -103,6 +103,7 @@
18 nlist.close_popover.connect (() => close ());
19 nlist.switch_stack.connect (on_switch_stack);
20 NotificationMonitor.get_instance ().received.connect (on_notification_received);
21+ NotificationMonitor.get_instance ().close_notification.connect (on_notification_closed);
22
23 NotifySettings.get_instance ().changed[NotifySettings.DO_NOT_DISTURB_KEY].connect (() => {
24 not_disturb_switch.get_switch ().active = NotifySettings.get_instance ().do_not_disturb;
25@@ -160,6 +161,15 @@
26 dynamic_icon.set_main_icon_name (get_display_icon_name ());
27 }
28
29+ private void on_notification_closed (uint32 id) {
30+ foreach (var item in nlist.items) {
31+ if (item.notification.id == id) {
32+ item.notification.close ();
33+ return;
34+ }
35+ }
36+ }
37+
38 private void on_switch_stack (bool show_list) {
39 clear_all_btn.sensitive = show_list;
40 if (show_list) {
41@@ -181,7 +191,11 @@
42 private string get_display_icon_name () {
43 if (NotifySettings.get_instance ().do_not_disturb) {
44 return "notification-disabled-symbolic";
45+<<<<<<< TREE
46 } else if (nlist != null && nlist.get_entries_length () > 0) {
47+=======
48+ } else if (nlist != null && nlist.items.length () > 0) {
49+>>>>>>> MERGE-SOURCE
50 return "notification-new-symbolic";
51 }
52
53
54=== modified file 'src/Services/Notification.vala'
55--- src/Services/Notification.vala 2016-08-03 06:28:36 +0000
56+++ src/Services/Notification.vala 2016-10-10 16:00:06 +0000
57@@ -37,6 +37,7 @@
58 public string desktop_id;
59 public AppInfo? app_info = null;
60
61+ public signal void closed ();
62 public signal bool time_changed (TimeSpan span);
63
64 private enum Column {
65@@ -126,6 +127,7 @@
66 }
67
68 public bool get_is_valid () {
69+<<<<<<< TREE
70 return app_info != null && hints.lookup_value (X_CANONICAL_PRIVATE_KEY, null) == null;
71 }
72
73@@ -150,6 +152,32 @@
74 }
75
76 return window;
77+=======
78+ return app_name in OTHER_WHITELIST || appinfo != null;
79+ }
80+
81+ public bool run_default_action () {
82+ if (DEFAULT_ACTION in actions) {
83+ INotifications? notifications_iface = NotificationMonitor.get_notifications_iface ();
84+ if (notifications_iface != null) {
85+ notifications_iface.action_invoked (DEFAULT_ACTION, id);
86+ return true;
87+ }
88+ }
89+
90+ return false;
91+ }
92+
93+ public void close () {
94+ closed ();
95+ }
96+
97+ private void set_properties () {
98+ if (app_name in OTHER_WHITELIST) {
99+ display_name = _("Other");
100+ app_icon = "dialog-information";
101+ }
102+>>>>>>> MERGE-SOURCE
103 }
104
105 private void setup_pid () {
106@@ -167,7 +195,7 @@
107 }
108
109 try {
110- IDBus? dbus_iface = Bus.get_proxy_sync (BusType.SESSION, "org.freedesktop.DBus", "/");
111+ IDBus? dbus_iface = NotificationMonitor.get_dbus_iface ();
112 if (dbus_iface != null && dbus_iface.name_has_owner (sender)) {
113 pid = dbus_iface.get_connection_unix_process_id (sender);
114 }
115
116=== renamed file 'src/Services/NotificationsMonitor.vala' => 'src/Services/NotificationMonitor.vala'
117--- src/Services/NotificationsMonitor.vala 2016-06-20 12:40:25 +0000
118+++ src/Services/NotificationMonitor.vala 2016-10-10 16:00:06 +0000
119@@ -23,17 +23,20 @@
120 public class NotificationMonitor : Object {
121 private const string NOTIFY_IFACE = "org.freedesktop.Notifications";
122 private const string NOTIFY_PATH = "/org/freedesktop/Notifications";
123- private const string MATCH_STRING = "eavesdrop='true',type='method_call',interface='org.freedesktop.Notifications',member='Notify'";
124+ private const string DBUS_IFACE = "org.freedesktop.DBus";
125+ private const string DBUS_PATH = "/";
126+ private const string MATCH_STRING = "eavesdrop='true',type='method_call',interface='org.freedesktop.Notifications'";
127 private const uint32 REASON_DISMISSED = 2;
128
129 private static NotificationMonitor? instance = null;
130+ private static INotifications? notifications_iface = null;
131+ private static IDBus? dbus_iface = null;
132
133 private DBusConnection connection;
134- public INotifications? notifications_iface = null;
135- public IDBus? dbus_iface = null;
136 private uint32 id_counter = 0;
137
138 public signal void received (DBusMessage message, uint32 id);
139+ public signal void close_notification (uint32 id);
140
141 public static NotificationMonitor get_instance () {
142 if (instance == null) {
143@@ -43,6 +46,30 @@
144 return instance;
145 }
146
147+ public static INotifications? get_notifications_iface () {
148+ if (notifications_iface == null) {
149+ try {
150+ notifications_iface = Bus.get_proxy_sync (BusType.SESSION, NOTIFY_IFACE, NOTIFY_PATH);
151+ } catch (Error e) {
152+ warning ("%s\n", e.message);
153+ }
154+ }
155+
156+ return notifications_iface;
157+ }
158+
159+ public static IDBus? get_dbus_iface () {
160+ if (dbus_iface == null) {
161+ try {
162+ dbus_iface = Bus.get_proxy_sync (BusType.SESSION, DBUS_IFACE, DBUS_PATH);
163+ } catch (Error e) {
164+ warning ("%s\n", e.message);
165+ }
166+ }
167+
168+ return dbus_iface;
169+ }
170+
171 private NotificationMonitor () {
172 try {
173 connection = Bus.get_sync (BusType.SESSION);
174@@ -61,12 +88,6 @@
175 var body = new Variant.parsed ("(%s,)", MATCH_STRING);
176 message.set_body (body);
177
178- try {
179- notifications_iface = Bus.get_proxy_sync (BusType.SESSION, NOTIFY_IFACE, NOTIFY_PATH);
180- } catch (Error e) {
181- error ("%s\n", e.message);
182- }
183-
184 id_counter = get_current_notification_id ();
185 try {
186 connection.send_message (message, DBusSendMessageFlags.NONE, null);
187@@ -78,24 +99,33 @@
188 }
189
190 private DBusMessage message_filter (DBusConnection con, owned DBusMessage message, bool incoming) {
191- if (incoming) {
192- if ((message.get_message_type () == DBusMessageType.METHOD_CALL) &&
193- (message.get_interface () == NOTIFY_IFACE) &&
194- (message.get_member () == "Notify")) {
195- uint32 replaces_id = message.get_body ().get_child_value (1).get_uint32 ();
196- uint32 current_id = replaces_id;
197-
198- if (replaces_id == 0) {
199- id_counter++;
200- current_id = id_counter;
201+ if (incoming) {
202+ if (message.get_message_type () == DBusMessageType.METHOD_CALL &&
203+ message.get_interface () == NOTIFY_IFACE) {
204+ if (message.get_member () == "Notify") {
205+ uint32 replaces_id = message.get_body ().get_child_value (1).get_uint32 ();
206+ uint32 current_id = replaces_id;
207+
208+ if (replaces_id == 0) {
209+ id_counter++;
210+ current_id = id_counter;
211+ }
212+
213+ Idle.add (() => {
214+ received (message, current_id);
215+ message = null;
216+ return false;
217+ });
218+ } else if (message.get_member () == "CloseNotification") {
219+ uint32 id = message.get_body ().get_child_value (0).get_uint32 ();
220+
221+ Idle.add (() => {
222+ close_notification (id);
223+ message = null;
224+ return false;
225+ });
226 }
227
228- Idle.add (() => {
229- this.received (message, current_id);
230- message = null;
231- return false;
232- });
233-
234 return null;
235 }
236 }
237@@ -109,7 +139,7 @@
238 hints.insert ("suppress-sound", new Variant.boolean (true));
239 string[] actions = {};
240 try {
241- return notifications_iface.notify ("", 0, "", "", "", actions, hints, 1);
242+ return get_notifications_iface ().notify ("", 0, "", "", "", actions, hints, 1);
243 } catch (Error e) {
244 error ("%s\n", e.message);
245 }
246
247=== modified file 'src/Widgets/AppEntry.vala'
248--- src/Widgets/AppEntry.vala 2016-07-20 20:11:51 +0000
249+++ src/Widgets/AppEntry.vala 2016-10-10 16:00:06 +0000
250@@ -66,8 +66,22 @@
251 return null;
252 }
253
254+<<<<<<< TREE
255 var entry = app_notifications.first ().data;
256 return entry.notification.get_app_window ();
257+=======
258+ public void update_app_window () {
259+ if (app_notifications.length () == 0) {
260+ return;
261+ }
262+
263+ var notification_entry = app_notifications.nth_data (0);
264+ app_window = notification_entry.get_app_window ();
265+ }
266+
267+ public unowned List<NotificationEntry> get_notifications () {
268+ return app_notifications;
269+>>>>>>> MERGE-SOURCE
270 }
271
272 public void add_notification_entry (NotificationEntry entry) {
273
274=== modified file 'src/Widgets/NotificationEntry.vala'
275--- src/Widgets/NotificationEntry.vala 2016-07-20 20:36:57 +0000
276+++ src/Widgets/NotificationEntry.vala 2016-10-10 16:00:06 +0000
277@@ -53,8 +53,35 @@
278 return active;
279 });
280
281+ notification.closed.connect (() => {
282+ clear ();
283+ });
284+
285 hexpand = true;
286+<<<<<<< TREE
287
288+=======
289+ add_widgets ();
290+
291+ if (notification.data_session) {
292+ notification.time_changed (notification.timestamp.difference (new DateTime.now_local ()));
293+ }
294+ }
295+
296+ public Wnck.Window? get_app_window () {
297+ Wnck.Window? window = null;
298+ Wnck.Screen.get_default ().get_windows ().@foreach ((_window) => {
299+ if (_window.get_pid () == notification.pid) {
300+ window = _window;
301+ return;
302+ }
303+ });
304+
305+ return window;
306+ }
307+
308+ private void add_widgets () {
309+>>>>>>> MERGE-SOURCE
310 var grid = new Gtk.Grid ();
311 grid.margin_start = 40;
312 grid.margin_end = 6;
313
314=== modified file 'src/Widgets/NotificationsList.vala'
315--- src/Widgets/NotificationsList.vala 2016-07-21 12:52:41 +0000
316+++ src/Widgets/NotificationsList.vala 2016-10-10 16:00:06 +0000
317@@ -18,7 +18,11 @@
318 public class NotificationsList : Gtk.ListBox {
319 public signal void switch_stack (bool show_list);
320 public signal void close_popover ();
321+<<<<<<< TREE
322
323+=======
324+ public List<NotificationEntry> items;
325+>>>>>>> MERGE-SOURCE
326 private List<AppEntry> app_entries;
327 private HashTable<string, int> table;
328 private int counter = 0;
329@@ -47,9 +51,24 @@
330
331 switch_stack (true);
332
333+<<<<<<< TREE
334 app_entry.clear.connect (clear_app_entry);
335
336 counter += 2;
337+=======
338+ app_entry.add_notification_entry (entry);
339+ resort_app_entry (app_entry);
340+
341+ entry.clear.connect (() => {
342+ destroy_notification_entry.begin (entry);
343+ });
344+
345+ app_entry.destroy_entry.connect (() => {
346+ destroy_app_entry (app_entry);
347+ });
348+
349+ counter += 2;
350+>>>>>>> MERGE-SOURCE
351
352 Session.get_instance ().add_notification (entry.notification);
353
354@@ -57,11 +76,14 @@
355 show_all ();
356 }
357
358+<<<<<<< TREE
359
360 public uint get_entries_length () {
361 return app_entries.length ();
362 }
363
364+=======
365+>>>>>>> MERGE-SOURCE
366 public void clear_all () {
367 app_entries.foreach ((app_entry) => {
368 app_entry.clear ();
369@@ -109,15 +131,30 @@
370 AppEntry? app_entry = null;
371 bool add = !(entry.notification.desktop_id in construct_desktop_id_list ());
372 if (add) {
373+<<<<<<< TREE
374 app_entry = new AppEntry (entry);
375+=======
376+ var window = entry.get_app_window ();
377+ app_entry = new AppEntry (entry, window);
378+
379+ screen.active_window_changed.connect (() => {
380+ if (screen.get_active_window () == app_entry.app_window) {
381+ app_entry.clear_btn_entry.clicked ();
382+ }
383+ });
384+>>>>>>> MERGE-SOURCE
385
386 app_entries.append (app_entry);
387 prepend (app_entry);
388 insert (entry, 1);
389 table.insert (app_entry.app_info.get_id (), 0);
390 } else {
391+<<<<<<< TREE
392 app_entry = get_app_entry_from_desktop_id (entry.notification.desktop_id);
393
394+=======
395+ app_entry = get_from_app_name (entry.notification.app_name);
396+>>>>>>> MERGE-SOURCE
397 if (app_entry != null) {
398 resort_app_entry (app_entry);
399 app_entry.add_notification_entry (entry);
400@@ -130,6 +167,7 @@
401 return app_entry;
402 }
403
404+<<<<<<< TREE
405 private void monitor_active_window () {
406 var screen = Wnck.Screen.get_default ();
407 screen.active_window_changed.connect (() => {
408@@ -142,6 +180,22 @@
409 }
410
411 private void clear_app_entry (AppEntry app_entry) {
412+=======
413+ private async void destroy_notification_entry (NotificationEntry entry) {
414+ entry.destroy ();
415+ items.remove (entry);
416+ entry.active = false;
417+
418+ Session.get_instance ().remove_notification (entry.notification);
419+ if (items.length () == 0) {
420+ clear_all ();
421+ }
422+
423+ update_separators ();
424+ }
425+
426+ private void destroy_app_entry (AppEntry app_entry) {
427+>>>>>>> MERGE-SOURCE
428 app_entries.remove (app_entry);
429
430 app_entry.app_notifications.foreach ((notification_entry) => {
431@@ -154,6 +208,7 @@
432 if (get_entries_length () == 0) {
433 clear_all ();
434 }
435+<<<<<<< TREE
436 }
437
438 private AppEntry? get_app_entry_from_desktop_id (string desktop_id) {
439@@ -161,6 +216,31 @@
440 app_entries.foreach ((_app_entry) => {
441 if (_app_entry.app_info.get_id () == desktop_id && app_entry == null) {
442 app_entry = _app_entry;
443+=======
444+
445+ update_separators ();
446+ }
447+
448+ private void resort_app_entry (AppEntry app_entry) {
449+ if (get_row_at_index (0) != app_entry) {
450+ remove (app_entry);
451+ prepend (app_entry);
452+ int counter = 1;
453+ app_entry.get_notifications ().@foreach ((notification_entry) => {
454+ remove (notification_entry);
455+ add_item (notification_entry);
456+ counter++;
457+ });
458+ }
459+ }
460+
461+ private AppEntry? get_from_app_name (string app_name) {
462+ AppEntry? entry = null;
463+ app_entries.@foreach ((_entry) => {
464+ if (_entry.app_name == app_name) {
465+ entry = _entry;
466+ return;
467+>>>>>>> MERGE-SOURCE
468 }
469 });
470
471@@ -177,6 +257,7 @@
472 }
473
474 private void on_row_activated (Gtk.ListBoxRow row) {
475+<<<<<<< TREE
476 bool close = true;
477
478 if (row is AppEntry) {
479@@ -200,10 +281,34 @@
480
481 if (close) {
482 close_popover ();
483+=======
484+ if (row is AppEntry) {
485+ var app_entry = (AppEntry)row;
486+ if (app_entry.app_window == null) {
487+ app_entry.update_app_window ();
488+ }
489+
490+ focus_notification_app (app_entry.app_window,
491+ app_entry.appinfo);
492+
493+ app_entry.clear_btn_entry.clicked ();
494+ close_popover ();
495+ } else if (row is NotificationEntry) {
496+ var notification_entry = (NotificationEntry)row;
497+ if (!notification_entry.notification.run_default_action ()) {
498+ focus_notification_app (notification_entry.get_app_window (),
499+ notification_entry.notification.appinfo);
500+ }
501+
502+ notification_entry.clear ();
503+ notification_entry.active = false;
504+ close_popover ();
505+>>>>>>> MERGE-SOURCE
506 }
507
508 update_separators ();
509 }
510+<<<<<<< TREE
511
512 private bool focus_notification_app (Wnck.Window? app_window, AppInfo? app_info) {
513 if (app_window != null) {
514@@ -220,4 +325,18 @@
515
516 return false;
517 }
518+=======
519+
520+ private void focus_notification_app (Wnck.Window? app_window, AppInfo? appinfo) {
521+ if (app_window != null) {
522+ app_window.unminimize (Gtk.get_current_event_time ());
523+ } else if (appinfo != null) {
524+ try {
525+ appinfo.launch (null, null);
526+ } catch (Error e) {
527+ warning ("%s\n", e.message);
528+ }
529+ }
530+ }
531+>>>>>>> MERGE-SOURCE
532 }

Subscribers

People subscribed via source and target branches

to all changes: