gnome-shell/js/ui/windowAttentionHandler.js
Dan Winship 6f57f07214 [MessageTray] Clean up source-vs-notification icon handling
A Source needs exactly one summary icon (which in the case of a
trayicon-based source won't even be just an image), but possibly many
notification icons, which may vary for successive notifications
(particularly in the case of NotificationDaemon notifications). So
differentiate these cases in the API.

https://bugzilla.gnome.org/show_bug.cgi?id=627303
2010-08-26 11:00:54 -04:00

110 lines
3.9 KiB
JavaScript

/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
function WindowAttentionHandler() {
this._init();
}
WindowAttentionHandler.prototype = {
_init : function() {
this._startupIds = {};
this._sources = {};
let display = global.screen.get_display();
display.connect('window-demands-attention', Lang.bind(this, this._onWindowDemandsAttention));
let tracker = Shell.WindowTracker.get_default();
tracker.connect('startup-sequence-changed', Lang.bind(this, this._onStartupSequenceChanged));
},
_onStartupSequenceChanged : function(tracker) {
let sequences = tracker.get_startup_sequences();
this._startupIds = {};
for(let i = 0; i < sequences.length; i++) {
this._startupIds[sequences[i].get_id()] = true;
}
},
_getTitle : function(app, window) {
if (this._startupIds[window.get_startup_id()])
return app.get_name();
else
return window.title;
},
_getBanner : function(app, window) {
if (this._startupIds[window.get_startup_id()])
return _("%s has finished starting").format(app.get_name());
else
return _("'%s' is ready").format(window.title);
},
_onWindowDemandsAttention : function(display, window) {
// We don't want to show the notification when the window is already focused,
// because this is rather pointless.
// Some apps (like GIMP) do things like setting the urgency hint on the
// toolbar windows which would result into a notification even though GIMP itself is
// focused.
// We are just ignoring the hint on skip_taskbar windows for now.
// (Which is the same behaviour as with metacity + panel)
if (!window || window.has_focus() || window.is_skip_taskbar())
return;
let tracker = Shell.WindowTracker.get_default();
let app = tracker.get_window_app(window);
let appId = app.get_id();
let source = this._sources[appId];
if (source == null) {
source = new Source(app, window);
this._sources[appId] = source;
Main.messageTray.add(source);
source.connect('clicked', Lang.bind(this, function() { source.destroy(); }));
source.connect('destroy', Lang.bind(this, function() { delete this._sources[appId]; }));
}
let notification = new MessageTray.Notification(source, this._getTitle(app, window), this._getBanner(app, window), { bannerBody: true });
source.notify(notification);
window.connect('notify::title', Lang.bind(this, function(win) {
notification.update(this._getTitle(app, win), this._getBanner(app, win));
}));
window.connect('notify::demands-attention', Lang.bind(this, function() { source.destroy(); }));
window.connect('focus', Lang.bind(this, function() { source.destroy(); }));
window.connect('unmanaged', Lang.bind(this, function() { source.destroy(); }));
}
};
function Source(app, window) {
this._init(app, window);
}
Source.prototype = {
__proto__ : MessageTray.Source.prototype,
_init: function(app, window) {
MessageTray.Source.prototype._init.call(this, app.get_name());
this._window = window;
this._app = app;
this._setSummaryIcon(this.createNotificationIcon());
},
createNotificationIcon : function() {
return this._app.create_icon_texture(this.ICON_SIZE);
},
clicked : function() {
Main.activateWindow(this._window);
MessageTray.Source.prototype.clicked.call(this);
}
};