diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index 3e89954f7..a097d78f7 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -156,6 +156,15 @@ StScrollBar StButton#vhandle:hover color: #cccccc; } +/* Message Tray */ +#notification { + border-radius: 5px; + background: rgba(0,0,0,0.9); + border: 1px solid rgba(128,128,128,0.45); + color: white; + padding: 10px; +} + /* App Switcher */ .switcher-list { background: rgba(0,0,0,0.8); @@ -192,4 +201,4 @@ StScrollBar StButton#vhandle:hover .switcher-list .separator { width: 1px; background: rgba(255,255,255,0.33); -} \ No newline at end of file +} diff --git a/js/ui/Makefile.am b/js/ui/Makefile.am index bb12365e5..c5824a4ac 100644 --- a/js/ui/Makefile.am +++ b/js/ui/Makefile.am @@ -17,6 +17,7 @@ dist_jsui_DATA = \ link.js \ lookingGlass.js \ main.js \ + messageTray.js \ overview.js \ panel.js \ places.js \ diff --git a/js/ui/main.js b/js/ui/main.js index 6922630da..ec59928ab 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -14,6 +14,7 @@ const St = imports.gi.St; const Chrome = imports.ui.chrome; const Environment = imports.ui.environment; +const MessageTray = imports.ui.messageTray; const Messaging = imports.ui.messaging; const Overview = imports.ui.overview; const Panel = imports.ui.panel; @@ -34,6 +35,7 @@ let runDialog = null; let lookingGlass = null; let wm = null; let messaging = null; +let notificationPopup = null; let recorder = null; let shellDBusService = null; let modalCount = 0; @@ -104,6 +106,7 @@ function start() { sidebar = new Sidebar.Sidebar(); wm = new WindowManager.WindowManager(); messaging = new Messaging.Messaging(); + notificationPopup = new MessageTray.Notification(); global.screen.connect('toggle-recording', function() { if (recorder == null) { diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js new file mode 100644 index 000000000..73128afee --- /dev/null +++ b/js/ui/messageTray.js @@ -0,0 +1,72 @@ +/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ + +const Lang = imports.lang; +const Mainloop = imports.mainloop; +const St = imports.gi.St; +const Tweener = imports.ui.tweener; + +const Main = imports.ui.main; + +const ANIMATION_TIME = 0.2; +const NOTIFICATION_TIMEOUT = 4; + +function Notification() { + this._init(); +} + +Notification.prototype = { + _init: function() { + this.actor = new St.BoxLayout({ name: 'notification' }); + + this._text = new St.Label(); + this.actor.add(this._text, { expand: true, x_fill: false, x_align: St.Align.MIDDLE }); + + // Directly adding the actor to Main.chrome.actor is a hack to + // work around the fact that there is no way to add an actor that + // affects the input region but not the shape. + // See: https://bugzilla.gnome.org/show_bug.cgi?id=597044 + Main.chrome.actor.add_actor(this.actor); + Main.chrome.addInputRegionActor(this.actor); + + let primary = global.get_primary_monitor(); + this.actor.y = primary.height; + + this._hideTimeoutId = 0; + }, + + show: function(text) { + let primary = global.get_primary_monitor(); + + if (this._hideTimeoutId > 0) + Mainloop.source_remove(this._hideTimeoutId); + this._hideTimeoutId = Mainloop.timeout_add(NOTIFICATION_TIMEOUT * 1000, Lang.bind(this, this.hide)); + + this._text.text = text; + + this.actor.x = Math.round((primary.width - this.actor.width) / 2); + this.actor.show(); + Tweener.addTween(this.actor, + { y: primary.height - this.actor.height, + time: ANIMATION_TIME, + transition: "easeOutQuad" + }); + }, + + hide: function() { + let primary = global.get_primary_monitor(); + this._hideTimeoutId = 0; + + Tweener.addTween(this.actor, + { y: primary.height, + time: ANIMATION_TIME, + transition: "easeOutQuad", + onComplete: function() { + // Don't hide the notification if we are showing a new one. + if (this._hideTimeoutId == 0) + this.actor.hide(); + }, + onCompleteScope: this + }); + return false; + } +}; diff --git a/js/ui/messaging.js b/js/ui/messaging.js index 9c4be52eb..11d0d15a6 100644 --- a/js/ui/messaging.js +++ b/js/ui/messaging.js @@ -4,6 +4,8 @@ const DBus = imports.dbus; const Lang = imports.lang; const Shell = imports.gi.Shell; +const Main = imports.ui.main; + const AVATAR_SIZE = 24; const TELEPATHY = "org.freedesktop.Telepathy."; @@ -230,5 +232,6 @@ Source.prototype = { _receivedMessage: function(channel, id, timestamp, sender, type, flags, text) { log('Received: id ' + id + ', time ' + timestamp + ', sender ' + sender + ', type ' + type + ', flags ' + flags + ': ' + text); + Main.notificationPopup.show(text); } };