153
_lookupSource: function(title, pid, trayIcon) {
154
for (let i = 0; i < this._sources.length; i++) {
155
let source = this._sources[i];
156
if (source.pid == pid &&
157
(source.initialTitle == title || source.trayIcon || trayIcon))
153
163
// Returns the source associated with ndata.notification if it is set.
154
// Otherwise, returns the source associated with the pid if one is
155
// stored in this._sources and the notification is not transient.
156
// Otherwise, creates a new source as long as pid is provided.
164
// Otherwise, returns the source associated with the title and pid if
165
// such source is stored in this._sources and the notification is not
166
// transient. If the existing or requested source is associated with
167
// a tray icon and passed in pid matches a pid of an existing source,
168
// the title match is ignored to enable representing a tray icon and
169
// notifications from the same application with a single source.
171
// If no existing source is found, a new source is created as long as
158
174
// Either a pid or ndata.notification is needed to retrieve or
159
175
// create a source.
160
_getSource: function(title, pid, ndata, sender) {
176
_getSource: function(title, pid, ndata, sender, trayIcon) {
161
177
if (!pid && !(ndata && ndata.notification))
174
190
// with a transient one from the same sender, so we
175
191
// always create a new source object for new transient notifications
176
192
// and never add it to this._sources .
177
if (!isForTransientNotification && this._sources[pid]) {
178
let source = this._sources[pid];
179
source.setTitle(title);
193
if (!isForTransientNotification) {
194
let source = this._lookupSource(title, pid, trayIcon);
196
source.setTitle(title);
183
let source = new Source(title, pid, sender);
201
let source = new Source(title, pid, sender, trayIcon);
184
202
source.setTransient(isForTransientNotification);
186
204
if (!isForTransientNotification) {
187
this._sources[pid] = source;
205
this._sources.push(source);
188
206
source.connect('destroy', Lang.bind(this,
190
delete this._sources[pid];
208
let index = this._sources.indexOf(source);
210
this._sources.splice(index, 1);
261
281
let sender = DBus.getCurrentMessageContext().sender;
262
282
let pid = this._senderToPid[sender];
264
let source = this._getSource(appName, pid, ndata, sender);
284
let source = this._getSource(appName, pid, ndata, sender, null);
267
287
this._notifyForSource(source, ndata);
285
source = this._getSource(appName, pid, ndata, sender);
305
source = this._getSource(appName, pid, ndata, sender, null);
287
307
// We only store sender-pid entries for persistent sources.
288
308
// Removing the entries once the source is destroyed
432
452
if (!tracker.focus_app)
435
for (let id in this._sources) {
436
let source = this._sources[id];
455
for (let i = 0; i < this._sources.length; i++) {
456
let source = this._sources[i];
437
457
if (source.app == tracker.focus_app) {
438
458
source.destroyNonResidentNotifications();
458
478
_onTrayIconAdded: function(o, icon) {
459
let source = this._getSource(icon.title || icon.wm_class || _("Unknown"), icon.pid, null, null);
460
source.setTrayIcon(icon);
479
let source = this._getSource(icon.title || icon.wm_class || _("Unknown"), icon.pid, null, null, icon);
463
482
_onTrayIconRemoved: function(o, icon) {
464
let source = this._sources[icon.pid];
483
let source = this._lookupSource(null, icon.pid, true);
466
485
source.destroy();
470
489
DBus.conformExport(NotificationDaemon.prototype, NotificationDaemonIface);
472
function Source(title, pid, sender) {
473
this._init(title, pid, sender);
491
function Source(title, pid, sender, trayIcon) {
492
this._init(title, pid, sender, trayIcon);
476
495
Source.prototype = {
477
496
__proto__: MessageTray.Source.prototype,
479
_init: function(title, pid, sender) {
498
_init: function(title, pid, sender, trayIcon) {
480
499
MessageTray.Source.prototype._init.call(this, title);
501
this.initialTitle = title;
484
505
// TODO: dbus-glib implementation of watch_name() doesn’t return an id to be used for
485
506
// unwatch_name() or implement unwatch_name(), however when we move to using GDBus implementation,
496
517
this.title = this.app.get_name();
498
519
this.useNotificationIcon = true;
499
this._trayIcon = null;
521
this.trayIcon = trayIcon;
523
this._setSummaryIcon(this.trayIcon);
524
this.useNotificationIcon = false;
502
528
_onNameVanished: function() {
544
570
let id = global.connect('notify::stage-input-mode', Lang.bind(this,
546
572
global.disconnect(id);
547
this._trayIcon.click(event);
573
this.trayIcon.click(event);
549
575
Main.overview.hide();
551
this._trayIcon.click(event);
577
this.trayIcon.click(event);
560
this.app = Shell.WindowTracker.get_default().get_app_from_pid(this._pid);
586
this.app = Shell.WindowTracker.get_default().get_app_from_pid(this.pid);
564
590
// Only override the icon if we were previously using
565
591
// notification-based icons (ie, not a trayicon) or if it was unset before
566
if (!this._trayIcon) {
592
if (!this.trayIcon) {
567
593
this.useNotificationIcon = false;
568
594
this._setSummaryIcon(this.app.create_icon_texture (this.ICON_SIZE));
572
setTrayIcon: function(icon) {
573
this._setSummaryIcon(icon);
574
this.useNotificationIcon = false;
575
this._trayIcon = icon;
578
598
open: function(notification) {
579
599
this.destroyNonResidentNotifications();
583
603
_lastNotificationRemoved: function() {