Initial implementation of the message tray and notification daemon
From the message-tray branch. Most of the UI parts were written by Marina, and most of the D-Bus parts by me.
This commit is contained in:
parent
c90371d9d5
commit
11276a3505
@ -472,6 +472,27 @@ StTooltip {
|
|||||||
color: #cccccc;
|
color: #cccccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Message Tray */
|
||||||
|
#message-tray {
|
||||||
|
background-gradient-direction: vertical;
|
||||||
|
background-gradient-start: rgba(0,0,0,0.01);
|
||||||
|
background-gradient-end: rgba(0,0,0,0.95);
|
||||||
|
height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#notification {
|
||||||
|
border-radius: 5px;
|
||||||
|
background: rgba(0,0,0,0.9);
|
||||||
|
color: white;
|
||||||
|
padding: 2px 10px;
|
||||||
|
spacing: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summary-mode {
|
||||||
|
spacing: 10px;
|
||||||
|
padding: 2px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
/* App Switcher */
|
/* App Switcher */
|
||||||
.switcher-list {
|
.switcher-list {
|
||||||
background: rgba(0,0,0,0.8);
|
background: rgba(0,0,0,0.8);
|
||||||
|
@ -16,6 +16,8 @@ dist_jsui_DATA = \
|
|||||||
link.js \
|
link.js \
|
||||||
lookingGlass.js \
|
lookingGlass.js \
|
||||||
main.js \
|
main.js \
|
||||||
|
messageTray.js \
|
||||||
|
notificationDaemon.js \
|
||||||
overview.js \
|
overview.js \
|
||||||
panel.js \
|
panel.js \
|
||||||
placeDisplay.js \
|
placeDisplay.js \
|
||||||
|
@ -15,11 +15,13 @@ const St = imports.gi.St;
|
|||||||
const Chrome = imports.ui.chrome;
|
const Chrome = imports.ui.chrome;
|
||||||
const Environment = imports.ui.environment;
|
const Environment = imports.ui.environment;
|
||||||
const ExtensionSystem = imports.ui.extensionSystem;
|
const ExtensionSystem = imports.ui.extensionSystem;
|
||||||
|
const MessageTray = imports.ui.messageTray;
|
||||||
const Overview = imports.ui.overview;
|
const Overview = imports.ui.overview;
|
||||||
const Panel = imports.ui.panel;
|
const Panel = imports.ui.panel;
|
||||||
const PlaceDisplay = imports.ui.placeDisplay;
|
const PlaceDisplay = imports.ui.placeDisplay;
|
||||||
const RunDialog = imports.ui.runDialog;
|
const RunDialog = imports.ui.runDialog;
|
||||||
const LookingGlass = imports.ui.lookingGlass;
|
const LookingGlass = imports.ui.lookingGlass;
|
||||||
|
const NotificationDaemon = imports.ui.notificationDaemon;
|
||||||
const ShellDBus = imports.ui.shellDBus;
|
const ShellDBus = imports.ui.shellDBus;
|
||||||
const Sidebar = imports.ui.sidebar;
|
const Sidebar = imports.ui.sidebar;
|
||||||
const WindowManager = imports.ui.windowManager;
|
const WindowManager = imports.ui.windowManager;
|
||||||
@ -35,6 +37,8 @@ let overview = null;
|
|||||||
let runDialog = null;
|
let runDialog = null;
|
||||||
let lookingGlass = null;
|
let lookingGlass = null;
|
||||||
let wm = null;
|
let wm = null;
|
||||||
|
let notificationDaemon = null;
|
||||||
|
let messageTray = null;
|
||||||
let recorder = null;
|
let recorder = null;
|
||||||
let shellDBusService = null;
|
let shellDBusService = null;
|
||||||
let modalCount = 0;
|
let modalCount = 0;
|
||||||
@ -113,6 +117,8 @@ function start() {
|
|||||||
panel = new Panel.Panel();
|
panel = new Panel.Panel();
|
||||||
sidebar = new Sidebar.Sidebar();
|
sidebar = new Sidebar.Sidebar();
|
||||||
wm = new WindowManager.WindowManager();
|
wm = new WindowManager.WindowManager();
|
||||||
|
notificationDaemon = new NotificationDaemon.NotificationDaemon();
|
||||||
|
messageTray = new MessageTray.MessageTray();
|
||||||
|
|
||||||
_startDate = new Date();
|
_startDate = new Date();
|
||||||
|
|
||||||
|
239
js/ui/messageTray.js
Normal file
239
js/ui/messageTray.js
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
const St = imports.gi.St;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
|
const ANIMATION_TIME = 0.2;
|
||||||
|
const NOTIFICATION_TIMEOUT = 4;
|
||||||
|
|
||||||
|
const MESSAGE_TRAY_TIMEOUT = 0.2;
|
||||||
|
|
||||||
|
const ICON_SIZE = 24;
|
||||||
|
|
||||||
|
function Notification(icon, text) {
|
||||||
|
this._init(icon, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
Notification.prototype = {
|
||||||
|
_init: function(icon, text) {
|
||||||
|
this.icon = icon;
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function NotificationBox() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationBox.prototype = {
|
||||||
|
_init: function() {
|
||||||
|
this.actor = new St.BoxLayout({ name: 'notification' });
|
||||||
|
|
||||||
|
this._iconBox = new St.Bin();
|
||||||
|
this.actor.add(this._iconBox);
|
||||||
|
|
||||||
|
this._text = new St.Label();
|
||||||
|
this.actor.add(this._text, { expand: true, x_fill: false, y_fill: false, y_align: St.Align.MIDDLE });
|
||||||
|
},
|
||||||
|
|
||||||
|
setContent: function(notification) {
|
||||||
|
this._iconBox.child = notification.icon;
|
||||||
|
|
||||||
|
// Support <b>, <i>, and <u>, escape anything else
|
||||||
|
// so it displays as raw markup.
|
||||||
|
let markup = notification.text.replace(/<(\/?[^biu]>|[^>\/][^>])/g, "<$1");
|
||||||
|
this._text.clutter_text.set_markup(markup);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function Source(id, createIcon) {
|
||||||
|
this._init(id, createIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
Source.prototype = {
|
||||||
|
_init: function(id, createIcon) {
|
||||||
|
this.id = id;
|
||||||
|
if (createIcon)
|
||||||
|
this.createIcon = createIcon;
|
||||||
|
},
|
||||||
|
|
||||||
|
// This can be overridden by a subclass, or by the createIcon
|
||||||
|
// parameter to _init()
|
||||||
|
createIcon: function(size) {
|
||||||
|
throw new Error('no implementation of createIcon in ' + this);
|
||||||
|
},
|
||||||
|
|
||||||
|
notify: function(text) {
|
||||||
|
Main.messageTray.showNotification(new Notification(this.createIcon(ICON_SIZE), text));
|
||||||
|
},
|
||||||
|
|
||||||
|
clicked: function() {
|
||||||
|
this.emit('clicked');
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
this.emit('destroy');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Signals.addSignalMethods(Source.prototype);
|
||||||
|
|
||||||
|
function MessageTray() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageTray.prototype = {
|
||||||
|
_init: function() {
|
||||||
|
this.actor = new St.BoxLayout({ name: 'message-tray',
|
||||||
|
reactive: true });
|
||||||
|
|
||||||
|
let primary = global.get_primary_monitor();
|
||||||
|
this.actor.x = 0;
|
||||||
|
this.actor.y = primary.height - 1;
|
||||||
|
|
||||||
|
this.actor.width = primary.width;
|
||||||
|
|
||||||
|
this._summaryBin = new St.Bin({ x_align: St.Align.END });
|
||||||
|
this.actor.add(this._summaryBin, { expand: true });
|
||||||
|
this._summaryBin.hide();
|
||||||
|
|
||||||
|
this._notificationBox = new NotificationBox();
|
||||||
|
this._notificationQueue = [];
|
||||||
|
this.actor.add(this._notificationBox.actor);
|
||||||
|
this._notificationBox.actor.hide();
|
||||||
|
|
||||||
|
Main.chrome.addActor(this.actor, { affectsStruts: false });
|
||||||
|
|
||||||
|
this.actor.connect('enter-event',
|
||||||
|
Lang.bind(this, this._onMessageTrayEntered));
|
||||||
|
this.actor.connect('leave-event',
|
||||||
|
Lang.bind(this, this._onMessageTrayLeft));
|
||||||
|
this._isShowing = false;
|
||||||
|
this.actor.show();
|
||||||
|
|
||||||
|
this._summary = new St.BoxLayout({ name: 'summary-mode' });
|
||||||
|
this._summaryBin.child = this._summary;
|
||||||
|
|
||||||
|
this._sources = {};
|
||||||
|
this._icons = {};
|
||||||
|
},
|
||||||
|
|
||||||
|
contains: function(source) {
|
||||||
|
return this._sources.hasOwnProperty(source.id);
|
||||||
|
},
|
||||||
|
|
||||||
|
add: function(source) {
|
||||||
|
if (this.contains(source)) {
|
||||||
|
log('Trying to re-add source ' + source.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let iconBox = new St.Bin({ reactive: true });
|
||||||
|
iconBox.child = source.createIcon(ICON_SIZE);
|
||||||
|
this._summary.insert_actor(iconBox, 0);
|
||||||
|
this._icons[source.id] = iconBox;
|
||||||
|
this._sources[source.id] = source;
|
||||||
|
|
||||||
|
iconBox.connect('button-release-event', Lang.bind(this,
|
||||||
|
function () {
|
||||||
|
source.clicked();
|
||||||
|
}));
|
||||||
|
|
||||||
|
source.connect('destroy', Lang.bind(this,
|
||||||
|
function () {
|
||||||
|
this.remove(source);
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
remove: function(source) {
|
||||||
|
if (!this.contains(source))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._summary.remove_actor(this._icons[source.id]);
|
||||||
|
delete this._icons[source.id];
|
||||||
|
delete this._sources[source.id];
|
||||||
|
},
|
||||||
|
|
||||||
|
getSource: function(id) {
|
||||||
|
return this._sources[id];
|
||||||
|
},
|
||||||
|
|
||||||
|
_onMessageTrayEntered: function() {
|
||||||
|
// Don't hide the message tray after a timeout if the user has moved the mouse over it.
|
||||||
|
// We might have a timeout in place if the user moved the mouse away from the message tray for a very short period of time
|
||||||
|
// or if we are showing a notification.
|
||||||
|
if (this._hideTimeoutId > 0)
|
||||||
|
Mainloop.source_remove(this._hideTimeoutId);
|
||||||
|
|
||||||
|
if (this._isShowing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If the message tray was not already showing, we'll show it in the summary mode.
|
||||||
|
this._summaryBin.show();
|
||||||
|
this._show();
|
||||||
|
},
|
||||||
|
|
||||||
|
_onMessageTrayLeft: function() {
|
||||||
|
if (!this._isShowing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// We wait just a little before hiding the message tray in case the user will quickly move the mouse back over it.
|
||||||
|
this._hideTimeoutId = Mainloop.timeout_add(MESSAGE_TRAY_TIMEOUT * 1000, Lang.bind(this, this._hide));
|
||||||
|
},
|
||||||
|
|
||||||
|
_show: function() {
|
||||||
|
this._isShowing = true;
|
||||||
|
let primary = global.get_primary_monitor();
|
||||||
|
Tweener.addTween(this.actor,
|
||||||
|
{ y: primary.height - this.actor.height,
|
||||||
|
time: ANIMATION_TIME,
|
||||||
|
transition: "easeOutQuad"
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_hide: function() {
|
||||||
|
this._hideTimeoutId = 0;
|
||||||
|
|
||||||
|
let primary = global.get_primary_monitor();
|
||||||
|
|
||||||
|
Tweener.addTween(this.actor,
|
||||||
|
{ y: primary.height - 1,
|
||||||
|
time: ANIMATION_TIME,
|
||||||
|
transition: "easeOutQuad",
|
||||||
|
onComplete: this._hideComplete,
|
||||||
|
onCompleteScope: this
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_hideComplete: function() {
|
||||||
|
this._isShowing = false;
|
||||||
|
this._summaryBin.hide();
|
||||||
|
this._notificationBox.actor.hide();
|
||||||
|
if (this._notificationQueue.length > 0)
|
||||||
|
this.showNotification(this._notificationQueue.shift());
|
||||||
|
},
|
||||||
|
|
||||||
|
showNotification: function(notification) {
|
||||||
|
if (this._isShowing) {
|
||||||
|
this._notificationQueue.push(notification);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._notificationBox.setContent(notification);
|
||||||
|
|
||||||
|
this._notificationBox.actor.x = Math.round((this.actor.width - this._notificationBox.actor.width) / 2);
|
||||||
|
this._notificationBox.actor.show();
|
||||||
|
|
||||||
|
// Because we set up the timeout before we do the animation, we add ANIMATION_TIME to NOTIFICATION_TIMEOUT, so that
|
||||||
|
// NOTIFICATION_TIMEOUT represents the time the notifiation is fully shown.
|
||||||
|
this._hideTimeoutId = Mainloop.timeout_add((NOTIFICATION_TIMEOUT + ANIMATION_TIME) * 1000, Lang.bind(this, this._hide));
|
||||||
|
|
||||||
|
this._show();
|
||||||
|
}
|
||||||
|
};
|
218
js/ui/notificationDaemon.js
Normal file
218
js/ui/notificationDaemon.js
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const DBus = imports.dbus;
|
||||||
|
const GLib = imports.gi.GLib;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const MessageTray = imports.ui.messageTray;
|
||||||
|
const Params = imports.misc.params;
|
||||||
|
|
||||||
|
let nextNotificationId = 1;
|
||||||
|
|
||||||
|
const NotificationDaemonIface = {
|
||||||
|
name: 'org.freedesktop.Notifications',
|
||||||
|
methods: [{ name: 'Notify',
|
||||||
|
inSignature: 'susssasa{sv}i',
|
||||||
|
outSignature: 'u'
|
||||||
|
},
|
||||||
|
{ name: 'CloseNotification',
|
||||||
|
inSignature: 'u',
|
||||||
|
outSignature: ''
|
||||||
|
},
|
||||||
|
{ name: 'GetCapabilities',
|
||||||
|
inSignature: '',
|
||||||
|
outSignature: 'as'
|
||||||
|
},
|
||||||
|
{ name: 'GetServerInformation',
|
||||||
|
inSignature: '',
|
||||||
|
outSignature: 'ssss'
|
||||||
|
}],
|
||||||
|
signals: [{ name: 'NotificationClosed',
|
||||||
|
inSignature: 'uu' },
|
||||||
|
{ name: 'ActionInvoked',
|
||||||
|
inSignature: 'us' }]
|
||||||
|
};
|
||||||
|
|
||||||
|
const NotificationClosedReason = {
|
||||||
|
EXPIRED: 1,
|
||||||
|
DISMISSED: 2,
|
||||||
|
APP_CLOSED: 3,
|
||||||
|
UNDEFINED: 4
|
||||||
|
};
|
||||||
|
|
||||||
|
const Urgency = {
|
||||||
|
LOW: 0,
|
||||||
|
NORMAL: 1,
|
||||||
|
CRITICAL: 2
|
||||||
|
};
|
||||||
|
|
||||||
|
function NotificationDaemon() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationDaemon.prototype = {
|
||||||
|
_init: function() {
|
||||||
|
DBus.session.exportObject('/org/freedesktop/Notifications', this);
|
||||||
|
|
||||||
|
this._everAcquiredName = false;
|
||||||
|
DBus.session.acquire_name('org.freedesktop.Notifications',
|
||||||
|
// We pass MANY_INSTANCES so that if
|
||||||
|
// notification-daemon is running, we'll
|
||||||
|
// get queued behind it and then get the
|
||||||
|
// name after killing it below
|
||||||
|
DBus.MANY_INSTANCES,
|
||||||
|
Lang.bind(this, this._acquiredName),
|
||||||
|
Lang.bind(this, this._lostName));
|
||||||
|
},
|
||||||
|
|
||||||
|
_acquiredName: function() {
|
||||||
|
this._everAcquiredName = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_lostName: function() {
|
||||||
|
if (this._everAcquiredName)
|
||||||
|
log('Lost name org.freedesktop.Notifications!');
|
||||||
|
else if (GLib.getenv('GNOME_SHELL_NO_REPLACE'))
|
||||||
|
log('Failed to acquire org.freedesktop.Notifications');
|
||||||
|
else {
|
||||||
|
log('Failed to acquire org.freedesktop.Notifications; trying again');
|
||||||
|
|
||||||
|
// kill the notification-daemon. pkill is more portable
|
||||||
|
// than killall, but on Linux at least it won't match if
|
||||||
|
// you pass more than 15 characters of the process name...
|
||||||
|
// However, if you use the "-f" flag to match the entire
|
||||||
|
// command line, it will work, but we have to be careful
|
||||||
|
// in that case that we don't match "gedit
|
||||||
|
// notification-daemon.c" or whatever...
|
||||||
|
let p = new Shell.Process({ args: ['pkill', '-f',
|
||||||
|
'^([^ ]*/)?(notification-daemon|notify-osd)$']});
|
||||||
|
p.run();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_sourceId: function(id) {
|
||||||
|
return 'notification-' + id;
|
||||||
|
},
|
||||||
|
|
||||||
|
Notify: function(appName, replacesId, icon, summary, body,
|
||||||
|
actions, hints, timeout) {
|
||||||
|
let id, source = null;
|
||||||
|
|
||||||
|
if (replacesId != 0) {
|
||||||
|
id = replacesId;
|
||||||
|
source = Main.messageTray.getSource(this._sourceId(id));
|
||||||
|
// source may be null if the current source was destroyed
|
||||||
|
// right as the client sent the new notification
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source == null) {
|
||||||
|
id = nextNotificationId++;
|
||||||
|
|
||||||
|
source = new Source(this._sourceId(id), icon, hints);
|
||||||
|
Main.messageTray.add(source);
|
||||||
|
|
||||||
|
source.connect('clicked', Lang.bind(this,
|
||||||
|
function() {
|
||||||
|
source.destroy();
|
||||||
|
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
summary = GLib.markup_escape_text(summary, -1);
|
||||||
|
if (body)
|
||||||
|
source.notify('<b>' + summary + '</b>: ' + body);
|
||||||
|
else
|
||||||
|
source.notify('<b>' + summary + '</b>');
|
||||||
|
return id;
|
||||||
|
},
|
||||||
|
|
||||||
|
CloseNotification: function(id) {
|
||||||
|
let source = Main.messageTray.getSource(this._sourceId(id));
|
||||||
|
if (source)
|
||||||
|
source.destroy();
|
||||||
|
this._emitNotificationClosed(id, NotificationClosedReason.APP_CLOSED);
|
||||||
|
},
|
||||||
|
|
||||||
|
GetCapabilities: function() {
|
||||||
|
return [
|
||||||
|
// 'actions',
|
||||||
|
'body',
|
||||||
|
// 'body-hyperlinks',
|
||||||
|
// 'body-images',
|
||||||
|
'body-markup',
|
||||||
|
// 'icon-multi',
|
||||||
|
'icon-static'
|
||||||
|
// 'sound',
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
GetServerInformation: function() {
|
||||||
|
return [
|
||||||
|
'GNOME Shell',
|
||||||
|
'GNOME',
|
||||||
|
'0.1', // FIXME, get this from somewhere
|
||||||
|
'1.0'
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
_emitNotificationClosed: function(id, reason) {
|
||||||
|
DBus.session.emit_signal('/org/freedesktop/Notifications',
|
||||||
|
'org.freedesktop.Notifications',
|
||||||
|
'NotificationClosed', 'uu',
|
||||||
|
[id, reason]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DBus.conformExport(NotificationDaemon.prototype, NotificationDaemonIface);
|
||||||
|
|
||||||
|
function Source(sourceId, icon, hints) {
|
||||||
|
this._init(sourceId, icon, hints);
|
||||||
|
}
|
||||||
|
|
||||||
|
Source.prototype = {
|
||||||
|
__proto__: MessageTray.Source.prototype,
|
||||||
|
|
||||||
|
_init: function(sourceId, icon, hints) {
|
||||||
|
MessageTray.Source.prototype._init.call(this, sourceId);
|
||||||
|
|
||||||
|
hints = Params.parse(hints, { urgency: Urgency.NORMAL }, true);
|
||||||
|
|
||||||
|
this._icon = icon;
|
||||||
|
this._iconData = hints.icon_data;
|
||||||
|
this._urgency = hints.urgency;
|
||||||
|
},
|
||||||
|
|
||||||
|
createIcon: function(size) {
|
||||||
|
let textureCache = Shell.TextureCache.get_default();
|
||||||
|
|
||||||
|
if (this._icon) {
|
||||||
|
if (this._icon.substr(0, 7) == 'file://')
|
||||||
|
return textureCache.load_uri_async(this._icon, size, size);
|
||||||
|
else if (this._icon[0] == '/') {
|
||||||
|
let uri = GLib.filename_to_uri(this._icon, null);
|
||||||
|
return textureCache.load_uri_async(uri, size, size);
|
||||||
|
} else
|
||||||
|
return textureCache.load_icon_name(this._icon, size);
|
||||||
|
} else if (this._iconData) {
|
||||||
|
let [width, height, rowStride, hasAlpha,
|
||||||
|
bitsPerSample, nChannels, data] = this._iconData;
|
||||||
|
return textureCache.load_from_raw(data, data.length, hasAlpha,
|
||||||
|
width, height, rowStride, size);
|
||||||
|
} else {
|
||||||
|
let stockIcon;
|
||||||
|
switch (this._urgency) {
|
||||||
|
case Urgency.LOW:
|
||||||
|
case Urgency.NORMAL:
|
||||||
|
stockIcon = 'gtk-dialog-info';
|
||||||
|
break;
|
||||||
|
case Urgency.CRITICAL:
|
||||||
|
stockIcon = 'gtk-dialog-error';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return textureCache.load_icon_name(stockIcon, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
5
src/gnome-shell.in
Normal file → Executable file
5
src/gnome-shell.in
Normal file → Executable file
@ -357,8 +357,9 @@ try:
|
|||||||
shell = None
|
shell = None
|
||||||
if options.xephyr:
|
if options.xephyr:
|
||||||
xephyr = start_xephyr()
|
xephyr = start_xephyr()
|
||||||
# This makes us not grab the org.gnome.Panel name
|
# This makes us not grab the org.gnome.Panel or
|
||||||
os.environ['GNOME_SHELL_NO_REPLACE_PANEL'] = '1'
|
# org.freedesktop.Notifications D-Bus names
|
||||||
|
os.environ['GNOME_SHELL_NO_REPLACE'] = '1'
|
||||||
shell = start_shell()
|
shell = start_shell()
|
||||||
else:
|
else:
|
||||||
xephyr = None
|
xephyr = None
|
||||||
|
@ -751,7 +751,7 @@ shell_global_grab_dbus_service (ShellGlobal *global)
|
|||||||
* unless a special environment variable is passed. The environment
|
* unless a special environment variable is passed. The environment
|
||||||
* variable is used by the gnome-shell (no --replace) launcher in
|
* variable is used by the gnome-shell (no --replace) launcher in
|
||||||
* Xephyr */
|
* Xephyr */
|
||||||
if (!g_getenv ("GNOME_SHELL_NO_REPLACE_PANEL"))
|
if (!g_getenv ("GNOME_SHELL_NO_REPLACE"))
|
||||||
{
|
{
|
||||||
if (!dbus_g_proxy_call (bus, "RequestName", &error, G_TYPE_STRING,
|
if (!dbus_g_proxy_call (bus, "RequestName", &error, G_TYPE_STRING,
|
||||||
"org.gnome.Panel", G_TYPE_UINT,
|
"org.gnome.Panel", G_TYPE_UINT,
|
||||||
|
Loading…
Reference in New Issue
Block a user