diff --git a/js/ui/Makefile.am b/js/ui/Makefile.am index ca38169f6..4eb388348 100644 --- a/js/ui/Makefile.am +++ b/js/ui/Makefile.am @@ -17,6 +17,7 @@ dist_jsui_DATA = \ lookingGlass.js \ main.js \ messageTray.js \ + notificationDaemon.js \ overview.js \ panel.js \ placeDisplay.js \ diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js index 3522a1adc..60dbebc0a 100644 --- a/js/ui/messageTray.js +++ b/js/ui/messageTray.js @@ -44,7 +44,11 @@ NotificationBox.prototype = { setContent: function(notification) { this._iconBox.child = notification.icon; - this._text.text = notification.text; + + // Support , , and , escape anything else + // so it displays as raw markup. + let markup = notification.text.replace(/<(\/?[^biu]>|[^>\/][^>])/g, "<$1"); + this._text.clutter_text.set_markup(markup); } }; diff --git a/js/ui/notificationDaemon.js b/js/ui/notificationDaemon.js index fef31f3c3..abcd2ce3d 100644 --- a/js/ui/notificationDaemon.js +++ b/js/ui/notificationDaemon.js @@ -8,6 +8,7 @@ const Mainloop = imports.mainloop; const Main = imports.ui.main; const MessageTray = imports.ui.messageTray; +const Params = imports.misc.params; let nextNotificationId = 1; @@ -42,6 +43,12 @@ const NotificationClosedReason = { UNDEFINED: 4 }; +const Urgency = { + LOW: 0, + NORMAL: 1, + CRITICAL: 2 +}; + function NotificationDaemon() { this._init(); } @@ -92,7 +99,11 @@ NotificationDaemon.prototype = { })); } - source.notify(summary); + summary = GLib.markup_escape_text(summary, -1); + if (body) + source.notify('' + summary + ': ' + body); + else + source.notify('' + summary + ''); return id; }, @@ -109,7 +120,7 @@ NotificationDaemon.prototype = { 'body', // 'body-hyperlinks', // 'body-images', - // 'body-markup', + 'body-markup', // 'icon-multi', 'icon-static' // 'sound', @@ -145,8 +156,11 @@ 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) { @@ -166,8 +180,17 @@ Source.prototype = { return textureCache.load_from_raw(data, data.length, hasAlpha, width, height, rowStride, size); } else { - // FIXME: fallback icon? - return textureCache.load_icon_name('gtk-dialog-info', size); + 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); } } };