2010-02-22 18:53:41 +00:00
|
|
|
/* -*- 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() {
|
2010-08-09 17:18:15 +00:00
|
|
|
this._startupIds = {};
|
|
|
|
this._sources = {};
|
|
|
|
|
2010-02-22 18:53:41 +00:00
|
|
|
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);
|
2010-08-09 17:18:15 +00:00
|
|
|
let appId = app.get_id();
|
2010-02-22 18:53:41 +00:00
|
|
|
|
2010-08-09 17:18:15 +00:00
|
|
|
let source = this._sources[appId];
|
2010-02-22 18:53:41 +00:00
|
|
|
if (source == null) {
|
2010-08-09 17:18:15 +00:00
|
|
|
source = new Source(app, window);
|
|
|
|
this._sources[appId] = source;
|
2010-02-22 18:53:41 +00:00
|
|
|
Main.messageTray.add(source);
|
2010-08-09 17:18:15 +00:00
|
|
|
source.connect('destroy', Lang.bind(this, function() { delete this._sources[appId]; }));
|
2010-02-22 18:53:41 +00:00
|
|
|
}
|
|
|
|
|
2010-08-30 20:03:08 +00:00
|
|
|
let notification = new MessageTray.Notification(source, this._getTitle(app, window), this._getBanner(app, window));
|
2010-02-22 18:53:41 +00:00
|
|
|
source.notify(notification);
|
|
|
|
|
|
|
|
window.connect('notify::title', Lang.bind(this, function(win) {
|
2010-08-18 20:01:33 +00:00
|
|
|
notification.update(this._getTitle(app, win), this._getBanner(app, win));
|
2010-02-22 18:53:41 +00:00
|
|
|
}));
|
2010-03-15 13:50:05 +00:00
|
|
|
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(); }));
|
2010-02-22 18:53:41 +00:00
|
|
|
|
|
|
|
}
|
2010-03-15 13:50:05 +00:00
|
|
|
};
|
2010-02-22 18:53:41 +00:00
|
|
|
|
2010-08-09 17:18:15 +00:00
|
|
|
function Source(app, window) {
|
|
|
|
this._init(app, window);
|
2010-02-22 18:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Source.prototype = {
|
|
|
|
__proto__ : MessageTray.Source.prototype,
|
|
|
|
|
2010-08-09 17:18:15 +00:00
|
|
|
_init: function(app, window) {
|
|
|
|
MessageTray.Source.prototype._init.call(this, app.get_name());
|
2010-02-22 18:53:41 +00:00
|
|
|
this._window = window;
|
|
|
|
this._app = app;
|
2010-08-05 17:09:27 +00:00
|
|
|
this._setSummaryIcon(this.createNotificationIcon());
|
2010-02-22 18:53:41 +00:00
|
|
|
},
|
|
|
|
|
2010-08-05 17:09:27 +00:00
|
|
|
createNotificationIcon : function() {
|
|
|
|
return this._app.create_icon_texture(this.ICON_SIZE);
|
2010-02-22 18:53:41 +00:00
|
|
|
},
|
|
|
|
|
MessageTray: untangle click notifications
Previously, when you clicked on a notification, it would call
this.source.clicked(), which would emit a 'clicked' signal on the
source, and then various other stuff would happen from there. This
used to make a little bit of sense, when clicking on a notification
was supposed to do the same thing as clicking on its source, but makes
less sense now, when clicking on the source itself *doesn't* call
source.clicked()...
Change it so that when you click on a notification, the notification
emits 'clicked' itself, and the source notices that and calls its
notificationClicked() method, and the various source subclasses do
what they need to do with that, and Source no longer has a clicked
method/signal.
https://bugzilla.gnome.org/show_bug.cgi?id=631042
2010-09-30 20:41:38 +00:00
|
|
|
_notificationClicked : function(notification) {
|
2010-02-22 18:53:41 +00:00
|
|
|
Main.activateWindow(this._window);
|
MessageTray: untangle click notifications
Previously, when you clicked on a notification, it would call
this.source.clicked(), which would emit a 'clicked' signal on the
source, and then various other stuff would happen from there. This
used to make a little bit of sense, when clicking on a notification
was supposed to do the same thing as clicking on its source, but makes
less sense now, when clicking on the source itself *doesn't* call
source.clicked()...
Change it so that when you click on a notification, the notification
emits 'clicked' itself, and the source notices that and calls its
notificationClicked() method, and the various source subclasses do
what they need to do with that, and Source no longer has a clicked
method/signal.
https://bugzilla.gnome.org/show_bug.cgi?id=631042
2010-09-30 20:41:38 +00:00
|
|
|
this.destroy();
|
2010-02-22 18:53:41 +00:00
|
|
|
}
|
2010-03-15 13:50:05 +00:00
|
|
|
};
|