Skip to content

Commit da98738

Browse files
committed
Make notifications applet multi instance
and do not recreate menu on orientation change. Disconnect signals on applet close. Cleanup code a little bit
1 parent 501a250 commit da98738

File tree

3 files changed

+63
-45
lines changed

3 files changed

+63
-45
lines changed

files/usr/share/cinnamon/applets/[email protected]/applet.js

Lines changed: 59 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const Applet = imports.ui.applet;
2-
const Lang = imports.lang;
32
const Main = imports.ui.main;
43
const Gtk = imports.gi.Gtk;
54
const Gio = imports.gi.Gio;
@@ -12,6 +11,7 @@ const NotificationDestroyedReason = imports.ui.messageTray.NotificationDestroyed
1211
const Settings = imports.ui.settings;
1312
const Gettext = imports.gettext.domain("cinnamon-applets");
1413
const Util = imports.misc.util;
14+
const SignalManager = imports.misc.signalManager;
1515

1616
const PANEL_EDIT_MODE_KEY = "panel-edit-mode";
1717

@@ -34,17 +34,23 @@ class CinnamonNotificationsApplet extends Applet.TextIconApplet {
3434
// Layout
3535
this._orientation = orientation;
3636
this.menuManager = new PopupMenu.PopupMenuManager(this);
37+
this.menu = new Applet.AppletPopupMenu(this, orientation);
38+
this.menuManager.addMenu(this.menu);
3739

3840
// Lists
3941
this.notifications = []; // The list of notifications, in order from oldest to newest.
4042

4143
// Events
42-
Main.messageTray.connect('notify-applet-update', Lang.bind(this, this._notification_added));
43-
this.panelEditModeHandler = global.settings.connect('changed::' + PANEL_EDIT_MODE_KEY, Lang.bind(this, this._on_panel_edit_mode_changed));
44+
this.signals = new SignalManager.SignalManager(null);
45+
this.signals.connect(Main.messageTray, 'notify-applet-update', this._notification_added.bind(this));
46+
this.signals.connect(global.settings, 'changed::' + PANEL_EDIT_MODE_KEY, this._on_panel_edit_mode_changed.bind(this));
47+
this.signals.connect(this.menu, 'menu-animated-closed', this._onMenuClosed.bind(this));
4448

4549
// States
4650
this._blinking = false;
4751
this._blink_toggle = false;
52+
53+
this._display();
4854
}
4955

5056
_setKeybinding() {
@@ -55,19 +61,29 @@ class CinnamonNotificationsApplet extends Applet.TextIconApplet {
5561
on_applet_removed_from_panel () {
5662
Main.keybindingManager.removeXletHotKey(this, "notification-open");
5763
Main.keybindingManager.removeXletHotKey(this, "notification-clear");
58-
global.settings.disconnect(this.panelEditModeHandler);
5964

6065
MessageTray.extensionsHandlingNotifications--;
6166
if (MessageTray.extensionsHandlingNotifications === 0) {
6267
this._clear_all();
6368
}
69+
70+
this.destroy();
6471
}
6572

6673
_openMenu() {
6774
this._update_timestamp();
75+
76+
this.notifications.forEach(notification => {
77+
global.reparentActor(notification.actor, this._notificationbin);
78+
});
79+
6880
this.menu.toggle();
6981
}
7082

83+
_onMenuClosed() {
84+
this._notificationbin.remove_all_children();
85+
}
86+
7187
_display() {
7288
// Always start the applet empty, void of any notifications.
7389
this.set_applet_icon_symbolic_name("empty-notif");
@@ -76,7 +92,6 @@ class CinnamonNotificationsApplet extends Applet.TextIconApplet {
7692
// Setup the notification container.
7793
this._maincontainer = new St.BoxLayout({name: 'traycontainer', vertical: true});
7894
this._notificationbin = new St.BoxLayout({vertical:true});
79-
this.button_label_box = new St.BoxLayout();
8095

8196
// Setup the tray icon.
8297
this.menu_label = new PopupMenu.PopupMenuItem(stringify(this.notifications.length));
@@ -87,42 +102,50 @@ class CinnamonNotificationsApplet extends Applet.TextIconApplet {
87102
this.clear_separator = new PopupMenu.PopupSeparatorMenuItem();
88103

89104
this.clear_action = new PopupMenu.PopupMenuItem(_("Clear notifications"));
90-
this.clear_action.connect('activate', Lang.bind(this, this._clear_all));
105+
this.clear_action.connect('activate', this._clear_all.bind(this));
91106
this.clear_action.actor.hide();
92107

93-
if (this._orientation == St.Side.BOTTOM) {
94-
this.menu.addMenuItem(this.menu_label);
95-
this.menu.addActor(this._maincontainer);
96-
this.menu.addMenuItem(this.clear_separator);
97-
this.menu.addMenuItem(this.clear_action);
98-
} else {
99-
this.menu.addMenuItem(this.clear_action);
100-
this.menu.addMenuItem(this.clear_separator);
101-
this.menu.addMenuItem(this.menu_label);
102-
this.menu.addActor(this._maincontainer);
103-
}
104-
108+
this.menu.addMenuItem(this.clear_action);
109+
this.menu.addMenuItem(this.clear_separator);
110+
this.menu.addMenuItem(this.menu_label);
111+
this.menu.addActor(this._maincontainer);
112+
105113
this.scrollview = new St.ScrollView({ x_fill: true, y_fill: true, y_align: St.Align.START, style_class: "vfade"});
106114
this._maincontainer.add(this.scrollview);
107115
this.scrollview.add_actor(this._notificationbin);
108116
this.scrollview.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
109117
this.scrollview.set_clip_to_allocation(true);
110118

111119
let vscroll = this.scrollview.get_vscroll_bar();
112-
vscroll.connect('scroll-start', Lang.bind(this, function() {
113-
this.menu.passEvents = true;
114-
}));
115-
vscroll.connect('scroll-stop', Lang.bind(this, function() {
116-
this.menu.passEvents = false;
117-
}));
120+
vscroll.connect('scroll-start', () => this.menu.passEvents = true);
121+
vscroll.connect('scroll-stop', () => this.menu.passEvents = false);
118122

119123
// Alternative tray icons.
120124
this._crit_icon = new St.Icon({icon_name: 'critical-notif', icon_type: St.IconType.SYMBOLIC, reactive: true, track_hover: true, style_class: 'system-status-icon' });
121125
this._alt_crit_icon = new St.Icon({icon_name: 'alt-critical-notif', icon_type: St.IconType.SYMBOLIC, reactive: true, track_hover: true, style_class: 'system-status-icon' });
122126

123127
this._on_panel_edit_mode_changed();
124128

125-
this.menu.addSettingsAction(_("Notification Settings"), 'notifications');
129+
this.settingsMenuItem = this.menu.addSettingsAction(_("Notification Settings"), 'notifications');
130+
}
131+
132+
_arrangeDisplay() {
133+
// Remove menu actors so we can put them back in a different order according to orientation.
134+
this.menu.box.remove_all_children();
135+
136+
if (this._orientation == St.Side.BOTTOM) {
137+
this.menu.addActor(this.menu_label.actor);
138+
this.menu.addActor(this._maincontainer);
139+
this.menu.addActor(this.clear_separator.actor);
140+
this.menu.addActor(this.clear_action.actor);
141+
} else {
142+
this.menu.addActor(this.clear_action.actor);
143+
this.menu.addActor(this.clear_separator.actor);
144+
this.menu.addActor(this.menu_label.actor);
145+
this.menu.addActor(this._maincontainer);
146+
}
147+
148+
this.menu.addActor(this.settingsMenuItem.actor);
126149
}
127150

128151
_notification_added (mtray, notification) { // Notification event handler.
@@ -138,8 +161,6 @@ class CinnamonNotificationsApplet extends Applet.TextIconApplet {
138161
if (notification._destroyed) {
139162
this.notifications.splice(existing_index, 1);
140163
} else {
141-
notification._inNotificationBin = true;
142-
global.reparentActor(notification.actor, this._notificationbin);
143164
notification._timeLabel.show();
144165
}
145166
this.update_list();
@@ -148,11 +169,8 @@ class CinnamonNotificationsApplet extends Applet.TextIconApplet {
148169
return;
149170
}
150171
// Add notification to list.
151-
notification._inNotificationBin = true;
152172
this.notifications.push(notification);
153-
// Steal the notification panel.
154-
this._notificationbin.add(notification.actor);
155-
notification.actor._parent_container = this._notificationbin;
173+
156174
notification.actor.add_style_class_name('notification-applet-padding');
157175
// Register for destruction.
158176
notification.connect('scrolling-changed', (notif, scrolling) => { this.menu.passEvents = scrolling });
@@ -169,7 +187,7 @@ class CinnamonNotificationsApplet extends Applet.TextIconApplet {
169187

170188
update_list () {
171189
try {
172-
let count = this.notifications.length;
190+
const count = this.notifications.length;
173191
if (count > 0) { // There are notifications.
174192
this.actor.show();
175193
this.clear_action.actor.show();
@@ -278,12 +296,7 @@ class CinnamonNotificationsApplet extends Applet.TextIconApplet {
278296
on_orientation_changed (orientation) {
279297
this._orientation = orientation;
280298

281-
if (this.menu) {
282-
this.menu.destroy();
283-
}
284-
this.menu = new Applet.AppletPopupMenu(this, orientation);
285-
this.menuManager.addMenu(this.menu);
286-
this._display();
299+
this._arrangeDisplay();
287300
}
288301

289302
on_applet_clicked(event) {
@@ -314,7 +327,14 @@ class CinnamonNotificationsApplet extends Applet.TextIconApplet {
314327
this._applet_icon_box.child = this._alt_crit_icon;
315328
}
316329
this._blink_toggle = !this._blink_toggle;
317-
Mainloop.timeout_add_seconds(1, Lang.bind(this, this.critical_blink));
330+
Mainloop.timeout_add_seconds(1, this.critical_blink.bind(this));
331+
}
332+
333+
destroy() {
334+
this.signals.disconnectAllSignals();
335+
this._crit_icon.destroy();
336+
this._alt_crit_icon.destroy();
337+
this.menu.destroy();
318338
}
319339
}
320340

files/usr/share/cinnamon/applets/[email protected]/metadata.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
33
"name": "Notifications",
44
"description": "Click to display and manage system notifications",
5-
"icon": "cs-notifications"
5+
"icon": "cs-notifications",
6+
"max-instances": -1
67
}

js/ui/messageTray.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -262,12 +262,10 @@ var Notification = class Notification {
262262
this._actionArea = null;
263263
this._imageBin = null;
264264
this._timestamp = new Date();
265-
this._inNotificationBin = false;
266265

267266
source.connect('destroy', (source, reason) => { this.destroy(reason) });
268267

269268
this.actor = new St.Button({ accessible_role: Atk.Role.NOTIFICATION });
270-
this.actor._parent_container = null;
271269
this.actor.connect('clicked', () => this._onClicked());
272270
this.actor.connect('destroy', () => this._onDestroy());
273271

@@ -348,7 +346,6 @@ var Notification = class Notification {
348346
*/
349347
update(title, body, params) {
350348
this._timestamp = new Date();
351-
this._inNotificationBin = false;
352349
params = Params.parse(params, {
353350
icon: null,
354351
titleMarkup: false,
@@ -929,8 +926,8 @@ MessageTray.prototype = {
929926

930927
_showNotification: function () {
931928
this._notification = this._notificationQueue.shift();
932-
if (this._notification.actor._parent_container) {
933-
this._notification.actor._parent_container.remove_actor(this._notification.actor);
929+
if (this._notification.actor.get_parent()) {
930+
this._notification.actor.get_parent().remove_actor(this._notification.actor);
934931
}
935932

936933
this._notificationBin.child = this._notification.actor;

0 commit comments

Comments
 (0)