[MessageTray] pop out the last notification when mousing over the summary
https://bugzilla.gnome.org/show_bug.cgi?id=610726
This commit is contained in:
parent
6deee27d14
commit
ac54fed8d4
@ -677,6 +677,11 @@ StTooltip {
|
|||||||
max-width: 40em;
|
max-width: 40em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#summary-notification-bin #notification {
|
||||||
|
/* message-tray.height + notification.padding-bottom */
|
||||||
|
padding-bottom: 38px;
|
||||||
|
}
|
||||||
|
|
||||||
#notification-actions {
|
#notification-actions {
|
||||||
spacing: 5px;
|
spacing: 5px;
|
||||||
}
|
}
|
||||||
@ -699,9 +704,26 @@ StTooltip {
|
|||||||
background: #808080;
|
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 {
|
#summary-mode {
|
||||||
spacing: 10px;
|
spacing: 6px;
|
||||||
padding: 2px 4px;
|
padding: 2px 0px 0px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-icon {
|
||||||
|
padding: 0px 4px 2px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* App Switcher */
|
/* App Switcher */
|
||||||
|
@ -15,7 +15,7 @@ const ANIMATION_TIME = 0.2;
|
|||||||
const NOTIFICATION_TIMEOUT = 4;
|
const NOTIFICATION_TIMEOUT = 4;
|
||||||
const SUMMARY_TIMEOUT = 1;
|
const SUMMARY_TIMEOUT = 1;
|
||||||
|
|
||||||
const MESSAGE_TRAY_TIMEOUT = 0.2;
|
const HIDE_TIMEOUT = 0.2;
|
||||||
|
|
||||||
const ICON_SIZE = 24;
|
const ICON_SIZE = 24;
|
||||||
|
|
||||||
@ -339,6 +339,19 @@ Source.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
notify: function(notification) {
|
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);
|
this.emit('notify', notification);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -379,6 +392,17 @@ MessageTray.prototype = {
|
|||||||
this._summaryBin.child = this._summary;
|
this._summaryBin.child = this._summary;
|
||||||
this._summaryBin.opacity = 0;
|
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._trayState = State.HIDDEN;
|
||||||
this._trayLeftTimeoutId = 0;
|
this._trayLeftTimeoutId = 0;
|
||||||
this._pointerInTray = false;
|
this._pointerInTray = false;
|
||||||
@ -387,13 +411,15 @@ MessageTray.prototype = {
|
|||||||
this._pointerInSummary = false;
|
this._pointerInSummary = false;
|
||||||
this._notificationState = State.HIDDEN;
|
this._notificationState = State.HIDDEN;
|
||||||
this._notificationTimeoutId = 0;
|
this._notificationTimeoutId = 0;
|
||||||
|
this._summaryNotificationState = State.HIDDEN;
|
||||||
|
this._summaryNotificationTimeoutId = 0;
|
||||||
this._overviewVisible = false;
|
this._overviewVisible = false;
|
||||||
this._notificationRemoved = false;
|
this._notificationRemoved = false;
|
||||||
|
|
||||||
this.actor.show();
|
|
||||||
Main.chrome.addActor(this.actor, { affectsStruts: false,
|
Main.chrome.addActor(this.actor, { affectsStruts: false,
|
||||||
visibleInOverview: true });
|
visibleInOverview: true });
|
||||||
Main.chrome.trackActor(this._notificationBin, { affectsStruts: false });
|
Main.chrome.trackActor(this._notificationBin, { affectsStruts: false });
|
||||||
|
Main.chrome.trackActor(this._summaryNotificationBin, { affectsStruts: false });
|
||||||
|
|
||||||
global.connect('screen-size-changed',
|
global.connect('screen-size-changed',
|
||||||
Lang.bind(this, this._setSizePosition));
|
Lang.bind(this, this._setSizePosition));
|
||||||
@ -420,8 +446,8 @@ MessageTray.prototype = {
|
|||||||
this.actor.y = primary.y + primary.height - 1;
|
this.actor.y = primary.y + primary.height - 1;
|
||||||
this.actor.width = primary.width;
|
this.actor.width = primary.width;
|
||||||
|
|
||||||
this._notificationBin.x = this._summaryBin.x = 0;
|
this._notificationBin.x = this._summaryBin.x = this._summaryNotificationBin.x = 0;
|
||||||
this._notificationBin.width = this._summaryBin.width = primary.width;
|
this._notificationBin.width = this._summaryBin.width = this._summaryNotificationBin.width = primary.width;
|
||||||
},
|
},
|
||||||
|
|
||||||
contains: function(source) {
|
contains: function(source) {
|
||||||
@ -434,7 +460,8 @@ MessageTray.prototype = {
|
|||||||
return;
|
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);
|
iconBox.child = source.createIcon(ICON_SIZE);
|
||||||
this._summary.insert_actor(iconBox, 0);
|
this._summary.insert_actor(iconBox, 0);
|
||||||
this._summaryNeedsToBeShown = true;
|
this._summaryNeedsToBeShown = true;
|
||||||
@ -443,6 +470,10 @@ MessageTray.prototype = {
|
|||||||
|
|
||||||
source.connect('notify', Lang.bind(this, this._onNotify));
|
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,
|
iconBox.connect('clicked', Lang.bind(this,
|
||||||
function () {
|
function () {
|
||||||
source.clicked();
|
source.clicked();
|
||||||
@ -474,14 +505,23 @@ MessageTray.prototype = {
|
|||||||
delete this._icons[source.id];
|
delete this._icons[source.id];
|
||||||
delete this._sources[source.id];
|
delete this._sources[source.id];
|
||||||
|
|
||||||
|
let needUpdate = false;
|
||||||
|
|
||||||
if (this._notification && this._notification.source == source) {
|
if (this._notification && this._notification.source == source) {
|
||||||
if (this._notificationTimeoutId) {
|
if (this._notificationTimeoutId) {
|
||||||
Mainloop.source_remove(this._notificationTimeoutId);
|
Mainloop.source_remove(this._notificationTimeoutId);
|
||||||
this._notificationTimeoutId = 0;
|
this._notificationTimeoutId = 0;
|
||||||
}
|
}
|
||||||
this._notificationRemoved = true;
|
this._notificationRemoved = true;
|
||||||
this._updateState();
|
needUpdate = true;
|
||||||
}
|
}
|
||||||
|
if (this._hoverSource == source) {
|
||||||
|
this._hoverSource = null;
|
||||||
|
needUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needUpdate);
|
||||||
|
this._updateState();
|
||||||
},
|
},
|
||||||
|
|
||||||
removeSourceByApp: function(app) {
|
removeSourceByApp: function(app) {
|
||||||
@ -532,6 +572,39 @@ MessageTray.prototype = {
|
|||||||
this._updateState();
|
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() {
|
_onSummaryHoverChanged: function() {
|
||||||
this._pointerInSummary = this._summary.hover;
|
this._pointerInSummary = this._summary.hover;
|
||||||
this._updateState();
|
this._updateState();
|
||||||
@ -550,7 +623,7 @@ MessageTray.prototype = {
|
|||||||
} else {
|
} else {
|
||||||
// We wait just a little before hiding the message tray in case the
|
// We wait just a little before hiding the message tray in case the
|
||||||
// user quickly moves the mouse back into it.
|
// 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));
|
this._trayLeftTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onTrayLeftTimeout));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -603,6 +676,22 @@ MessageTray.prototype = {
|
|||||||
this._hideSummary();
|
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
|
// Tray itself
|
||||||
let trayIsVisible = (this._trayState == State.SHOWING ||
|
let trayIsVisible = (this._trayState == State.SHOWING ||
|
||||||
this._trayState == State.SHOWN);
|
this._trayState == State.SHOWN);
|
||||||
@ -753,5 +842,46 @@ MessageTray.prototype = {
|
|||||||
transition: "easeOutQuad"
|
transition: "easeOutQuad"
|
||||||
});
|
});
|
||||||
this._summaryNeedsToBeShown = false;
|
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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user