From 153768ef7ffbea5760bcd7611aa75aef71310ba5 Mon Sep 17 00:00:00 2001 From: Neha Doijode Date: Thu, 7 Jul 2011 02:31:07 +0530 Subject: [PATCH] NotificationDaemon: remove source if notification sender is removed from DBus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't want sources that are no longer associated with a running application to stick around in the message tray. Message tray sources were removed when the associated application’s state changed to Shell.AppState.STOPPED . This caused sources for applications that were still running, but did not have any open windows to be removed. Instead, we should use the notification’s sender removal from DBus as an indicator for when to remove the associated source from the message tray. https://bugzilla.gnome.org/show_bug.cgi?id=645764 --- js/ui/notificationDaemon.js | 57 ++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/js/ui/notificationDaemon.js b/js/ui/notificationDaemon.js index 66bd0c58f..37009d9f6 100644 --- a/js/ui/notificationDaemon.js +++ b/js/ui/notificationDaemon.js @@ -148,7 +148,7 @@ NotificationDaemon.prototype = { // // Either a pid or ndata.notification is needed to retrieve or // create a source. - _getSource: function(title, pid, ndata) { + _getSource: function(title, pid, ndata, sender) { if (!pid && !(ndata && ndata.notification)) return null; @@ -171,7 +171,7 @@ NotificationDaemon.prototype = { return source; } - let source = new Source(title, pid); + let source = new Source(title, pid, sender); source.setTransient(isForTransientNotification); if (!isForTransientNotification) { @@ -245,7 +245,7 @@ NotificationDaemon.prototype = { let sender = DBus.getCurrentMessageContext().sender; let pid = this._senderToPid[sender]; - let source = this._getSource(appName, pid, ndata); + let source = this._getSource(appName, pid, ndata, sender); if (source) { this._notifyForSource(source, ndata); @@ -266,7 +266,7 @@ NotificationDaemon.prototype = { if (!ndata) return; - source = this._getSource(appName, pid, ndata); + source = this._getSource(appName, pid, ndata, sender); // We only store sender-pid entries for persistent sources. // Removing the entries once the source is destroyed @@ -415,7 +415,7 @@ NotificationDaemon.prototype = { }, _onTrayIconAdded: function(o, icon) { - let source = this._getSource(icon.title || icon.wm_class || _("Unknown"), icon.pid, null); + let source = this._getSource(icon.title || icon.wm_class || _("Unknown"), icon.pid, null, null); source.setTrayIcon(icon); }, @@ -428,18 +428,28 @@ NotificationDaemon.prototype = { DBus.conformExport(NotificationDaemon.prototype, NotificationDaemonIface); -function Source(title, pid) { - this._init(title, pid); +function Source(title, pid, sender) { + this._init(title, pid, sender); } Source.prototype = { __proto__: MessageTray.Source.prototype, - _init: function(title, pid) { + _init: function(title, pid, sender) { MessageTray.Source.prototype._init.call(this, title); this._pid = pid; - this._appStateChangedId = 0; + if (sender) + // TODO: dbus-glib implementation of watch_name() doesn’t return an id to be used for + // unwatch_name() or implement unwatch_name(), however when we move to using GDBus implementation, + // we should save the id here and call unwatch_name() with it in destroy(). + // Moving to GDBus is the work in progress: https://bugzilla.gnome.org/show_bug.cgi?id=648651 + // and https://bugzilla.gnome.org/show_bug.cgi?id=622921 . + DBus.session.watch_name(sender, + false, + null, + Lang.bind(this, this._onNameVanished)); + this._setApp(); if (this.app) this.title = this.app.get_name(); @@ -448,6 +458,14 @@ Source.prototype = { this._trayIcon = null; }, + _onNameVanished: function() { + // Destroy the notification source when its sender is removed from DBus. + // Sender being removed from DBus would normally result in a tray icon being removed, + // so allow the code path that handles the tray icon being removed to handle that case. + if (!this.trayIcon) + this.destroy(); + }, + processNotification: function(notification, icon) { if (!this.app) this._setApp(); @@ -500,10 +518,6 @@ Source.prototype = { if (!this.app) return; - // We only update the app if this.app is null, so we can't disconnect the old this._appStateChangedId - // even if it were non-zero for some reason. - this._appStateChangedId = this.app.connect('notify::state', Lang.bind(this, this._appStateChanged)); - // Only override the icon if we were previously using // notification-based icons (ie, not a trayicon) or if it was unset before if (!this._trayIcon) { @@ -528,19 +542,6 @@ Source.prototype = { this.destroy(); }, - _appStateChanged: function() { - // Destroy notification sources when their apps exit. - // The app exiting would normally result in a tray icon being removed, - // so the associated source would be destroyed through the code path - // that handles the tray icon being removed. We should not destroy - // the source associated with a tray icon when the application state - // is Shell.AppState.STOPPED because running applications that have - // no open windows would also have that state. This is often the case - // for applications that use tray icons. - if (!this._trayIcon && this.app.get_state() == Shell.AppState.STOPPED) - this.destroy(); - }, - openApp: function() { if (this.app == null) return; @@ -553,10 +554,6 @@ Source.prototype = { }, destroy: function() { - if (this.app && this._appStateChangedId) { - this.app.disconnect(this._appStateChangedId); - this._appStateChangedId = 0; - } MessageTray.Source.prototype.destroy.call(this); } };