[gnome-shell] [MessageTray] pop out the last notification when mousing over the summary
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] [MessageTray] pop out the last notification when mousing over the summary
- Date: Thu, 25 Mar 2010 13:25:56 +0000 (UTC)
commit ac54fed8d48102cd0fd2cf1701cb3efcdcd77465
Author: Dan Winship <danw gnome org>
Date: Thu Feb 25 14:42:18 2010 -0500
[MessageTray] pop out the last notification when mousing over the summary
https://bugzilla.gnome.org/show_bug.cgi?id=610726
data/theme/gnome-shell.css | 26 +++++++-
js/ui/messageTray.js | 144 +++++++++++++++++++++++++++++++++++++++++--
2 files changed, 161 insertions(+), 9 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 4dc3a2e..6d1a5d1 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -677,6 +677,11 @@ StTooltip {
max-width: 40em;
}
+#summary-notification-bin #notification {
+ /* message-tray.height + notification.padding-bottom */
+ padding-bottom: 38px;
+}
+
#notification-actions {
spacing: 5px;
}
@@ -699,9 +704,26 @@ StTooltip {
background: #808080;
}
+/* The spacing and padding on the summary is tricky; we want to keep
+ * the icons from touching each other or the edges of the screen, but
+ * we also want them to be "Fitts"-y with respect to the edges, so the
+ * summary area's bottom and right padding must actually be part of
+ * the icons. However, we can't put *all* of the padding into the
+ * icons, because then the summary would be 0x0 when there were no
+ * icons in it, and so you wouldn't be able to hover over it to
+ * activate it.
+ *
+ * The padding-right on the non-rightmost icons is noticeable and
+ * slightly annoying. If StBoxLayout implemented the ":last-child"
+ * pseudo-class we could fix that...
+ */
#summary-mode {
- spacing: 10px;
- padding: 2px 4px;
+ spacing: 6px;
+ padding: 2px 0px 0px 4px;
+}
+
+.summary-icon {
+ padding: 0px 4px 2px 0px;
}
/* App Switcher */
diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js
index 69231c0..fefc9ee 100644
--- a/js/ui/messageTray.js
+++ b/js/ui/messageTray.js
@@ -15,7 +15,7 @@ const ANIMATION_TIME = 0.2;
const NOTIFICATION_TIMEOUT = 4;
const SUMMARY_TIMEOUT = 1;
-const MESSAGE_TRAY_TIMEOUT = 0.2;
+const HIDE_TIMEOUT = 0.2;
const ICON_SIZE = 24;
@@ -339,6 +339,19 @@ Source.prototype = {
},
notify: function(notification) {
+ if (this.notification)
+ this.notification.disconnect(this._notificationDestroyedId);
+
+ this.notification = notification;
+
+ this._notificationDestroyedId = notification.connect('destroy', Lang.bind(this,
+ function () {
+ if (this.notification == notification) {
+ this.notification = null;
+ this._notificationDestroyedId = 0;
+ }
+ }));
+
this.emit('notify', notification);
},
@@ -379,6 +392,17 @@ MessageTray.prototype = {
this._summaryBin.child = this._summary;
this._summaryBin.opacity = 0;
+ this._summaryNotificationBin = new St.Bin({ name: 'summary-notification-bin',
+ x_align: St.Align.END,
+ reactive: true,
+ track_hover: true });
+ this.actor.add(this._summaryNotificationBin);
+ this._summaryNotificationBin.lower_bottom();
+ this._summaryNotificationBin.hide();
+ this._summaryNotificationBin.connect('notify::hover', Lang.bind(this, this._onSummaryNotificationHoverChanged));
+ this._summaryNotification = null;
+ this._hoverSource = null;
+
this._trayState = State.HIDDEN;
this._trayLeftTimeoutId = 0;
this._pointerInTray = false;
@@ -387,13 +411,15 @@ MessageTray.prototype = {
this._pointerInSummary = false;
this._notificationState = State.HIDDEN;
this._notificationTimeoutId = 0;
+ this._summaryNotificationState = State.HIDDEN;
+ this._summaryNotificationTimeoutId = 0;
this._overviewVisible = false;
this._notificationRemoved = false;
- this.actor.show();
Main.chrome.addActor(this.actor, { affectsStruts: false,
visibleInOverview: true });
Main.chrome.trackActor(this._notificationBin, { affectsStruts: false });
+ Main.chrome.trackActor(this._summaryNotificationBin, { affectsStruts: false });
global.connect('screen-size-changed',
Lang.bind(this, this._setSizePosition));
@@ -420,8 +446,8 @@ MessageTray.prototype = {
this.actor.y = primary.y + primary.height - 1;
this.actor.width = primary.width;
- this._notificationBin.x = this._summaryBin.x = 0;
- this._notificationBin.width = this._summaryBin.width = primary.width;
+ this._notificationBin.x = this._summaryBin.x = this._summaryNotificationBin.x = 0;
+ this._notificationBin.width = this._summaryBin.width = this._summaryNotificationBin.width = primary.width;
},
contains: function(source) {
@@ -434,7 +460,8 @@ MessageTray.prototype = {
return;
}
- let iconBox = new St.Clickable({ reactive: true });
+ let iconBox = new St.Clickable({ style_class: 'summary-icon',
+ reactive: true });
iconBox.child = source.createIcon(ICON_SIZE);
this._summary.insert_actor(iconBox, 0);
this._summaryNeedsToBeShown = true;
@@ -443,6 +470,10 @@ MessageTray.prototype = {
source.connect('notify', Lang.bind(this, this._onNotify));
+ iconBox.connect('notify::hover', Lang.bind(this,
+ function () {
+ this._onSourceHoverChanged(source, iconBox.hover);
+ }));
iconBox.connect('clicked', Lang.bind(this,
function () {
source.clicked();
@@ -474,14 +505,23 @@ MessageTray.prototype = {
delete this._icons[source.id];
delete this._sources[source.id];
+ let needUpdate = false;
+
if (this._notification && this._notification.source == source) {
if (this._notificationTimeoutId) {
Mainloop.source_remove(this._notificationTimeoutId);
this._notificationTimeoutId = 0;
}
this._notificationRemoved = true;
- this._updateState();
+ needUpdate = true;
}
+ if (this._hoverSource == source) {
+ this._hoverSource = null;
+ needUpdate = true;
+ }
+
+ if (needUpdate);
+ this._updateState();
},
removeSourceByApp: function(app) {
@@ -532,6 +572,39 @@ MessageTray.prototype = {
this._updateState();
},
+ _onSourceHoverChanged: function(source, hover) {
+ if (!source.notification)
+ return;
+
+ if (this._summaryNotificationTimeoutId != 0) {
+ Mainloop.source_remove(this._summaryNotificationTimeoutId);
+ this._summaryNotificationTimeoutId = 0;
+ }
+
+ if (hover) {
+ this._hoverSource = source;
+ this._updateState();
+ } else if (this._hoverSource == source) {
+ let timeout = HIDE_TIMEOUT * 1000;
+ this._summaryNotificationTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onSourceHoverChangedTimeout, source));
+ }
+ },
+
+ _onSourceHoverChangedTimeout: function(source) {
+ this._summaryNotificationTimeoutId = 0;
+ if (this._hoverSource == source) {
+ this._hoverSource = null;
+ this._updateState();
+ }
+ },
+
+ _onSummaryNotificationHoverChanged: function() {
+ if (!this._summaryNotification)
+ return;
+ this._onSourceHoverChanged(this._summaryNotification.source,
+ this._summaryNotificationBin.hover);
+ },
+
_onSummaryHoverChanged: function() {
this._pointerInSummary = this._summary.hover;
this._updateState();
@@ -550,7 +623,7 @@ MessageTray.prototype = {
} else {
// We wait just a little before hiding the message tray in case the
// user quickly moves the mouse back into it.
- let timeout = MESSAGE_TRAY_TIMEOUT * 1000;
+ let timeout = HIDE_TIMEOUT * 1000;
this._trayLeftTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onTrayLeftTimeout));
}
},
@@ -603,6 +676,22 @@ MessageTray.prototype = {
this._hideSummary();
}
+ // Summary notification
+ let haveSummaryNotification = this._hoverSource != null;
+ let summaryNotificationIsMainNotification = (haveSummaryNotification &&
+ this._hoverSource.notification == this._notification);
+ let canShowSummaryNotification = this._summaryState == State.SHOWN;
+ let wrongSummaryNotification = (haveSummaryNotification &&
+ this._summaryNotification != this._hoverSource.notification);
+
+ if (this._summaryNotificationState == State.HIDDEN) {
+ if (haveSummaryNotification && !summaryNotificationIsMainNotification && canShowSummaryNotification)
+ this._showSummaryNotification();
+ } else if (this._summaryNotificationState == State.SHOWN) {
+ if (!haveSummaryNotification || !canShowSummaryNotification || wrongSummaryNotification)
+ this._hideSummaryNotification();
+ }
+
// Tray itself
let trayIsVisible = (this._trayState == State.SHOWING ||
this._trayState == State.SHOWN);
@@ -753,5 +842,46 @@ MessageTray.prototype = {
transition: "easeOutQuad"
});
this._summaryNeedsToBeShown = false;
+ },
+
+ _showSummaryNotification: function() {
+ this._summaryNotification = this._hoverSource.notification;
+
+ let index = this._notificationQueue.indexOf(this._summaryNotification);
+ if (index != -1)
+ this._notificationQueue.splice(index, 1);
+
+ this._summaryNotificationBin.child = this._summaryNotification.actor;
+ this._summaryNotification.popOut();
+
+ this._summaryNotificationBin.opacity = 0;
+ this._summaryNotificationBin.y = this.actor.height;
+ this._summaryNotificationBin.show();
+
+ this._tween(this._summaryNotificationBin, "_summaryNotificationState", State.SHOWN,
+ { y: this.actor.height - this._summaryNotificationBin.height,
+ opacity: 255,
+ time: ANIMATION_TIME,
+ transition: "easeOutQuad"
+ });
+ },
+
+ _hideSummaryNotification: function() {
+ this._summaryNotification.popIn();
+
+ this._tween(this._summaryNotificationBin, "_summaryNotificationState", State.HIDDEN,
+ { y: this.actor.height,
+ opacity: 0,
+ time: ANIMATION_TIME,
+ transition: "easeOutQuad",
+ onComplete: this._hideSummaryNotificationCompleted,
+ onCompleteScope: this
+ });
+ },
+
+ _hideSummaryNotificationCompleted: function() {
+ this._summaryNotificationBin.hide();
+ this._summaryNotificationBin.child = null;
+ this._summaryNotification = null;
}
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]