kill tray 2
This commit is contained in:
parent
a80b8f7791
commit
2b93bcf921
@ -95,64 +95,6 @@ function _fixMarkup(text, allowMarkup) {
|
|||||||
return GLib.markup_escape_text(text, -1);
|
return GLib.markup_escape_text(text, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const FocusGrabber = new Lang.Class({
|
|
||||||
Name: 'FocusGrabber',
|
|
||||||
|
|
||||||
_init: function(actor) {
|
|
||||||
this._actor = actor;
|
|
||||||
this._prevKeyFocusActor = null;
|
|
||||||
this._focusActorChangedId = 0;
|
|
||||||
this._focused = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
grabFocus: function() {
|
|
||||||
if (this._focused)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._prevKeyFocusActor = global.stage.get_key_focus();
|
|
||||||
|
|
||||||
this._focusActorChangedId = global.stage.connect('notify::key-focus', Lang.bind(this, this._focusActorChanged));
|
|
||||||
|
|
||||||
if (!this._actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false))
|
|
||||||
this._actor.grab_key_focus();
|
|
||||||
|
|
||||||
this._focused = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_focusUngrabbed: function() {
|
|
||||||
if (!this._focused)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (this._focusActorChangedId > 0) {
|
|
||||||
global.stage.disconnect(this._focusActorChangedId);
|
|
||||||
this._focusActorChangedId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._focused = false;
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_focusActorChanged: function() {
|
|
||||||
let focusedActor = global.stage.get_key_focus();
|
|
||||||
if (!focusedActor || !this._actor.contains(focusedActor))
|
|
||||||
this._focusUngrabbed();
|
|
||||||
},
|
|
||||||
|
|
||||||
ungrabFocus: function() {
|
|
||||||
if (!this._focusUngrabbed())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this._prevKeyFocusActor) {
|
|
||||||
global.stage.set_key_focus(this._prevKeyFocusActor);
|
|
||||||
this._prevKeyFocusActor = null;
|
|
||||||
} else {
|
|
||||||
let focusedActor = global.stage.get_key_focus();
|
|
||||||
if (focusedActor && this._actor.contains(focusedActor))
|
|
||||||
global.stage.set_key_focus(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const URLHighlighter = new Lang.Class({
|
const URLHighlighter = new Lang.Class({
|
||||||
Name: 'URLHighlighter',
|
Name: 'URLHighlighter',
|
||||||
|
|
||||||
@ -980,79 +922,9 @@ const MessageTray = new Lang.Class({
|
|||||||
Name: 'MessageTray',
|
Name: 'MessageTray',
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this._presence = new GnomeSession.Presence(Lang.bind(this, function(proxy, error) {
|
|
||||||
this._onStatusChanged(proxy.status);
|
|
||||||
}));
|
|
||||||
this._busy = false;
|
|
||||||
this._presence.connectSignal('StatusChanged', Lang.bind(this, function(proxy, senderName, [status]) {
|
|
||||||
this._onStatusChanged(status);
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._notificationWidget = new St.Widget({ name: 'notification-container',
|
|
||||||
reactive: true,
|
|
||||||
track_hover: true,
|
|
||||||
y_align: Clutter.ActorAlign.START,
|
|
||||||
x_align: Clutter.ActorAlign.CENTER,
|
|
||||||
y_expand: true,
|
|
||||||
x_expand: true,
|
|
||||||
layout_manager: new Clutter.BinLayout() });
|
|
||||||
this._notificationWidget.connect('key-release-event', Lang.bind(this, this._onNotificationKeyRelease));
|
|
||||||
this._notificationWidget.connect('notify::hover', Lang.bind(this, this._onNotificationHoverChanged));
|
|
||||||
this._notificationWidget.connect('notify::height', Lang.bind(this, function() {
|
|
||||||
this._notificationWidget.translation_y = -this._notificationWidget.height;
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._notificationBin = new St.Bin({ y_expand: true });
|
|
||||||
this._notificationBin.set_y_align(Clutter.ActorAlign.START);
|
|
||||||
this._notificationWidget.add_actor(this._notificationBin);
|
|
||||||
this._notificationWidget.hide();
|
|
||||||
this._notificationFocusGrabber = new FocusGrabber(this._notificationWidget);
|
|
||||||
this._notificationQueue = [];
|
|
||||||
this._notification = null;
|
|
||||||
this._notificationClickedId = 0;
|
|
||||||
|
|
||||||
this._userActiveWhileNotificationShown = false;
|
|
||||||
|
|
||||||
this.idleMonitor = Meta.IdleMonitor.get_core();
|
|
||||||
|
|
||||||
// pointerInNotification is sort of a misnomer -- it tracks whether
|
|
||||||
// a message tray notification should expand. The value is
|
|
||||||
// partially driven by the hover state of the notification, but has
|
|
||||||
// a lot of complex state related to timeouts and the current
|
|
||||||
// state of the pointer when a notification pops up.
|
|
||||||
this._pointerInNotification = false;
|
|
||||||
|
|
||||||
// This tracks this._notificationWidget.hover and is used to fizzle
|
|
||||||
// out non-changing hover notifications in onNotificationHoverChanged.
|
|
||||||
this._notificationHovered = false;
|
|
||||||
|
|
||||||
this._keyboardVisible = false;
|
|
||||||
this._notificationState = State.HIDDEN;
|
|
||||||
this._notificationTimeoutId = 0;
|
|
||||||
this._notificationRemoved = false;
|
|
||||||
this._reNotifyAfterHideNotification = null;
|
|
||||||
this._inCtrlAltTab = false;
|
|
||||||
|
|
||||||
Main.layoutManager.trackChrome(this._notificationWidget);
|
|
||||||
|
|
||||||
global.screen.connect('in-fullscreen-changed', Lang.bind(this, this._updateState));
|
|
||||||
|
|
||||||
this._sources = new Map();
|
this._sources = new Map();
|
||||||
},
|
},
|
||||||
|
|
||||||
close: function() {
|
|
||||||
this._escapeTray();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onNotificationKeyRelease: function(actor, event) {
|
|
||||||
if (event.get_key_symbol() == Clutter.KEY_Escape && event.get_state() == 0) {
|
|
||||||
this._expireNotification();
|
|
||||||
return Clutter.EVENT_STOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Clutter.EVENT_PROPAGATE;
|
|
||||||
},
|
|
||||||
|
|
||||||
_expireNotification: function() {
|
_expireNotification: function() {
|
||||||
this._notificationExpired = true;
|
this._notificationExpired = true;
|
||||||
this._updateState();
|
this._updateState();
|
||||||
@ -1072,7 +944,7 @@ const MessageTray = new Lang.Class({
|
|||||||
source.policy.store();
|
source.policy.store();
|
||||||
|
|
||||||
source.policy.connect('enable-changed', Lang.bind(this, this._onSourceEnableChanged, source));
|
source.policy.connect('enable-changed', Lang.bind(this, this._onSourceEnableChanged, source));
|
||||||
source.policy.connect('policy-changed', Lang.bind(this, this._updateState));
|
// source.policy.connect('policy-changed', Lang.bind(this, this._updateState));
|
||||||
this._onSourceEnableChanged(source.policy, source);
|
this._onSourceEnableChanged(source.policy, source);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1130,402 +1002,8 @@ const MessageTray = new Lang.Class({
|
|||||||
this._removeSource(source);
|
this._removeSource(source);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onNotificationDestroy: function(notification) {
|
|
||||||
if (this._notification == notification && (this._notificationState == State.SHOWN || this._notificationState == State.SHOWING)) {
|
|
||||||
this._updateNotificationTimeout(0);
|
|
||||||
this._notificationRemoved = true;
|
|
||||||
this._updateState();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let index = this._notificationQueue.indexOf(notification);
|
|
||||||
if (index != -1)
|
|
||||||
this._notificationQueue.splice(index, 1);
|
|
||||||
},
|
|
||||||
|
|
||||||
openTray: function() {
|
|
||||||
if (Main.overview.animationInProgress)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._traySummoned = true;
|
|
||||||
this._updateState();
|
|
||||||
},
|
|
||||||
|
|
||||||
hide: function() {
|
|
||||||
this._traySummoned = false;
|
|
||||||
this._updateState();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onNotify: function(source, notification) {
|
_onNotify: function(source, notification) {
|
||||||
if (this._notification == notification) {
|
// Fill in here.
|
||||||
// If a notification that is being shown is updated, we update
|
|
||||||
// how it is shown and extend the time until it auto-hides.
|
|
||||||
// If a new notification is updated while it is being hidden,
|
|
||||||
// we stop hiding it and show it again.
|
|
||||||
this._updateShowingNotification();
|
|
||||||
} else if (this._notificationQueue.indexOf(notification) < 0) {
|
|
||||||
notification.connect('destroy',
|
|
||||||
Lang.bind(this, this._onNotificationDestroy));
|
|
||||||
this._notificationQueue.push(notification);
|
|
||||||
this._notificationQueue.sort(function(notification1, notification2) {
|
|
||||||
return (notification2.urgency - notification1.urgency);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this._updateState();
|
|
||||||
},
|
|
||||||
|
|
||||||
_resetNotificationLeftTimeout: function() {
|
|
||||||
this._useLongerNotificationLeftTimeout = false;
|
|
||||||
if (this._notificationLeftTimeoutId) {
|
|
||||||
Mainloop.source_remove(this._notificationLeftTimeoutId);
|
|
||||||
this._notificationLeftTimeoutId = 0;
|
|
||||||
this._notificationLeftMouseX = -1;
|
|
||||||
this._notificationLeftMouseY = -1;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onNotificationHoverChanged: function() {
|
|
||||||
if (this._notificationWidget.hover == this._notificationHovered)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._notificationHovered = this._notificationWidget.hover;
|
|
||||||
if (this._notificationHovered) {
|
|
||||||
// No dwell inside notifications at the bottom of the screen
|
|
||||||
// this._cancelTrayDwell();
|
|
||||||
|
|
||||||
this._resetNotificationLeftTimeout();
|
|
||||||
|
|
||||||
if (this._showNotificationMouseX >= 0) {
|
|
||||||
let actorAtShowNotificationPosition =
|
|
||||||
global.stage.get_actor_at_pos(Clutter.PickMode.ALL, this._showNotificationMouseX, this._showNotificationMouseY);
|
|
||||||
this._showNotificationMouseX = -1;
|
|
||||||
this._showNotificationMouseY = -1;
|
|
||||||
// Don't set this._pointerInNotification to true if the pointer was initially in the area where the notification
|
|
||||||
// popped up. That way we will not be expanding notifications that happen to pop up over the pointer
|
|
||||||
// automatically. Instead, the user is able to expand the notification by mousing away from it and then
|
|
||||||
// mousing back in. Because this is an expected action, we set the boolean flag that indicates that a longer
|
|
||||||
// timeout should be used before popping down the notification.
|
|
||||||
/*
|
|
||||||
if (this.actor.contains(actorAtShowNotificationPosition)) {
|
|
||||||
this._useLongerNotificationLeftTimeout = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
this._pointerInNotification = true;
|
|
||||||
this._updateState();
|
|
||||||
} else {
|
|
||||||
// We record the position of the mouse the moment it leaves the tray. These coordinates are used in
|
|
||||||
// this._onNotificationLeftTimeout() to determine if the mouse has moved far enough during the initial timeout for us
|
|
||||||
// to consider that the user intended to leave the tray and therefore hide the tray. If the mouse is still
|
|
||||||
// close to its previous position, we extend the timeout once.
|
|
||||||
let [x, y, mods] = global.get_pointer();
|
|
||||||
this._notificationLeftMouseX = x;
|
|
||||||
this._notificationLeftMouseY = y;
|
|
||||||
|
|
||||||
// We wait just a little before hiding the message tray in case the user quickly moves the mouse back into it.
|
|
||||||
// We wait for a longer period if the notification popped up where the mouse pointer was already positioned.
|
|
||||||
// That gives the user more time to mouse away from the notification and mouse back in in order to expand it.
|
|
||||||
let timeout = this._useLongerNotificationLeftTimeout ? LONGER_HIDE_TIMEOUT * 1000 : HIDE_TIMEOUT * 1000;
|
|
||||||
this._notificationLeftTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onNotificationLeftTimeout));
|
|
||||||
GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onKeyboardVisibleChanged: function(layoutManager, keyboardVisible) {
|
|
||||||
this._keyboardVisible = keyboardVisible;
|
|
||||||
this._updateState();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onStatusChanged: function(status) {
|
|
||||||
if (status == GnomeSession.PresenceStatus.BUSY) {
|
|
||||||
// remove notification and allow the summary to be closed now
|
|
||||||
this._updateNotificationTimeout(0);
|
|
||||||
this._busy = true;
|
|
||||||
} else if (status != GnomeSession.PresenceStatus.IDLE) {
|
|
||||||
// We preserve the previous value of this._busy if the status turns to IDLE
|
|
||||||
// so that we don't start showing notifications queued during the BUSY state
|
|
||||||
// as the screensaver gets activated.
|
|
||||||
this._busy = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._updateState();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onNotificationLeftTimeout: function() {
|
|
||||||
let [x, y, mods] = global.get_pointer();
|
|
||||||
// We extend the timeout once if the mouse moved no further than MOUSE_LEFT_ACTOR_THRESHOLD to either side or up.
|
|
||||||
// We don't check how far down the mouse moved because any point above the tray, but below the exit coordinate,
|
|
||||||
// is close to the tray.
|
|
||||||
if (this._notificationLeftMouseX > -1 &&
|
|
||||||
y > this._notificationLeftMouseY - MOUSE_LEFT_ACTOR_THRESHOLD &&
|
|
||||||
x < this._notificationLeftMouseX + MOUSE_LEFT_ACTOR_THRESHOLD &&
|
|
||||||
x > this._notificationLeftMouseX - MOUSE_LEFT_ACTOR_THRESHOLD) {
|
|
||||||
this._notificationLeftMouseX = -1;
|
|
||||||
this._notificationLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT * 1000,
|
|
||||||
Lang.bind(this, this._onNotificationLeftTimeout));
|
|
||||||
GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout');
|
|
||||||
} else {
|
|
||||||
this._notificationLeftTimeoutId = 0;
|
|
||||||
this._useLongerNotificationLeftTimeout = false;
|
|
||||||
this._pointerInNotification = false;
|
|
||||||
this._updateNotificationTimeout(0);
|
|
||||||
this._updateState();
|
|
||||||
}
|
|
||||||
return GLib.SOURCE_REMOVE;
|
|
||||||
},
|
|
||||||
|
|
||||||
_escapeTray: function() {
|
|
||||||
this._pointerInNotification = false;
|
|
||||||
this._traySummoned = false;
|
|
||||||
this._updateNotificationTimeout(0);
|
|
||||||
this._updateState();
|
|
||||||
},
|
|
||||||
|
|
||||||
// All of the logic for what happens when occurs here; the various
|
|
||||||
// event handlers merely update variables such as
|
|
||||||
// 'this._pointerInNotification', 'this._traySummoned', etc, and
|
|
||||||
// _updateState() figures out what (if anything) needs to be done
|
|
||||||
// at the present time.
|
|
||||||
_updateState: function() {
|
|
||||||
// If our state changes caused _updateState to be called,
|
|
||||||
// just exit now to prevent reentrancy issues.
|
|
||||||
if (this._updatingState)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._updatingState = true;
|
|
||||||
|
|
||||||
// Filter out acknowledged notifications.
|
|
||||||
this._notificationQueue = this._notificationQueue.filter(function(n) {
|
|
||||||
return !n.acknowledged;
|
|
||||||
});
|
|
||||||
|
|
||||||
let hasNotifications = Main.sessionMode.hasNotifications;
|
|
||||||
|
|
||||||
if (this._notificationState == State.HIDDEN) {
|
|
||||||
let shouldShowNotification = (hasNotifications && !this._traySummoned);
|
|
||||||
let nextNotification = this._notificationQueue[0] || null;
|
|
||||||
if (shouldShowNotification && nextNotification) {
|
|
||||||
let limited = this._busy || Main.layoutManager.bottomMonitor.inFullscreen;
|
|
||||||
let showNextNotification = (!limited || nextNotification.forFeedback || nextNotification.urgency == Urgency.CRITICAL);
|
|
||||||
if (showNextNotification)
|
|
||||||
this._showNotification();
|
|
||||||
}
|
|
||||||
} else if (this._notificationState == State.SHOWN) {
|
|
||||||
let expired = (this._userActiveWhileNotificationShown &&
|
|
||||||
this._notificationTimeoutId == 0 &&
|
|
||||||
this._notification.urgency != Urgency.CRITICAL &&
|
|
||||||
!this._notification.focused &&
|
|
||||||
!this._pointerInNotification) || this._notificationExpired;
|
|
||||||
let mustClose = (this._notificationRemoved || !hasNotifications || expired || this._traySummoned);
|
|
||||||
|
|
||||||
if (mustClose) {
|
|
||||||
let animate = hasNotifications && !this._notificationRemoved;
|
|
||||||
this._hideNotification(animate);
|
|
||||||
} else if (this._pointerInNotification) {
|
|
||||||
this._ensureNotificationFocused();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._updatingState = false;
|
|
||||||
|
|
||||||
// Clean transient variables that are used to communicate actions
|
|
||||||
// to updateState()
|
|
||||||
this._notificationExpired = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
_tween: function(actor, statevar, value, params) {
|
|
||||||
let onComplete = params.onComplete;
|
|
||||||
let onCompleteScope = params.onCompleteScope;
|
|
||||||
let onCompleteParams = params.onCompleteParams;
|
|
||||||
|
|
||||||
params.onComplete = this._tweenComplete;
|
|
||||||
params.onCompleteScope = this;
|
|
||||||
params.onCompleteParams = [statevar, value, onComplete, onCompleteScope, onCompleteParams];
|
|
||||||
|
|
||||||
// Remove other tweens that could mess with the state machine
|
|
||||||
Tweener.removeTweens(actor);
|
|
||||||
Tweener.addTween(actor, params);
|
|
||||||
|
|
||||||
let valuing = (value == State.SHOWN) ? State.SHOWING : State.HIDING;
|
|
||||||
this[statevar] = valuing;
|
|
||||||
},
|
|
||||||
|
|
||||||
_tweenComplete: function(statevar, value, onComplete, onCompleteScope, onCompleteParams) {
|
|
||||||
this[statevar] = value;
|
|
||||||
if (onComplete)
|
|
||||||
onComplete.apply(onCompleteScope, onCompleteParams);
|
|
||||||
this._updateState();
|
|
||||||
},
|
|
||||||
|
|
||||||
_showTray: function() {
|
|
||||||
/*
|
|
||||||
if (!this._grabHelper.grab({ actor: this.actor,
|
|
||||||
onUngrab: Lang.bind(this, this._escapeTray) })) {
|
|
||||||
this._traySummoned = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.emit('showing');
|
|
||||||
this._tween(this.actor, '_trayState', State.SHOWN,
|
|
||||||
{ y: -this.actor.height,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad'
|
|
||||||
});
|
|
||||||
|
|
||||||
*/
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onIdleMonitorBecameActive: function() {
|
|
||||||
this._userActiveWhileNotificationShown = true;
|
|
||||||
this._updateNotificationTimeout(2000);
|
|
||||||
this._updateState();
|
|
||||||
},
|
|
||||||
|
|
||||||
_showNotification: function() {
|
|
||||||
this._notification = this._notificationQueue.shift();
|
|
||||||
|
|
||||||
this._userActiveWhileNotificationShown = this.idleMonitor.get_idletime() <= IDLE_TIME;
|
|
||||||
if (!this._userActiveWhileNotificationShown) {
|
|
||||||
// If the user isn't active, set up a watch to let us know
|
|
||||||
// when the user becomes active.
|
|
||||||
this.idleMonitor.add_user_active_watch(Lang.bind(this, this._onIdleMonitorBecameActive));
|
|
||||||
}
|
|
||||||
|
|
||||||
this._notificationClickedId = this._notification.connect('done-displaying',
|
|
||||||
Lang.bind(this, this._escapeTray));
|
|
||||||
this._notificationUnfocusedId = this._notification.connect('unfocused', Lang.bind(this, function() {
|
|
||||||
this._updateState();
|
|
||||||
}));
|
|
||||||
this._notificationBin.child = this._notification.actor;
|
|
||||||
|
|
||||||
this._notificationWidget.opacity = 0;
|
|
||||||
this._notificationWidget.show();
|
|
||||||
|
|
||||||
this._updateShowingNotification();
|
|
||||||
|
|
||||||
let [x, y, mods] = global.get_pointer();
|
|
||||||
// We save the position of the mouse at the time when we started showing the notification
|
|
||||||
// in order to determine if the notification popped up under it. We make that check if
|
|
||||||
// the user starts moving the mouse and _onNotificationHoverChanged() gets called. We don't
|
|
||||||
// expand the notification if it just happened to pop up under the mouse unless the user
|
|
||||||
// explicitly mouses away from it and then mouses back in.
|
|
||||||
this._showNotificationMouseX = x;
|
|
||||||
this._showNotificationMouseY = y;
|
|
||||||
// We save the coordinates of the mouse at the time when we started showing the notification
|
|
||||||
// and then we update it in _notificationTimeout(). We don't pop down the notification if
|
|
||||||
// the mouse is moving towards it or within it.
|
|
||||||
this._lastSeenMouseX = x;
|
|
||||||
this._lastSeenMouseY = y;
|
|
||||||
|
|
||||||
this._resetNotificationLeftTimeout();
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateShowingNotification: function() {
|
|
||||||
this._notification.acknowledged = true;
|
|
||||||
this._notification.playSound();
|
|
||||||
|
|
||||||
// We tween all notifications to full opacity. This ensures that both new notifications and
|
|
||||||
// notifications that might have been in the process of hiding get full opacity.
|
|
||||||
//
|
|
||||||
// We use this._showNotificationCompleted() onComplete callback to extend the time the updated
|
|
||||||
// notification is being shown.
|
|
||||||
|
|
||||||
this._tween(this._notificationWidget, '_notificationState', State.SHOWN,
|
|
||||||
{ opacity: 255,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onComplete: this._showNotificationCompleted,
|
|
||||||
onCompleteScope: this
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_showNotificationCompleted: function() {
|
|
||||||
if (this._notification.urgency != Urgency.CRITICAL)
|
|
||||||
this._updateNotificationTimeout(NOTIFICATION_TIMEOUT * 1000);
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateNotificationTimeout: function(timeout) {
|
|
||||||
if (this._notificationTimeoutId) {
|
|
||||||
Mainloop.source_remove(this._notificationTimeoutId);
|
|
||||||
this._notificationTimeoutId = 0;
|
|
||||||
}
|
|
||||||
if (timeout > 0) {
|
|
||||||
this._notificationTimeoutId =
|
|
||||||
Mainloop.timeout_add(timeout,
|
|
||||||
Lang.bind(this, this._notificationTimeout));
|
|
||||||
GLib.Source.set_name_by_id(this._notificationTimeoutId, '[gnome-shell] this._notificationTimeout');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_notificationTimeout: function() {
|
|
||||||
let [x, y, mods] = global.get_pointer();
|
|
||||||
if (y > this._lastSeenMouseY + 10 && !this._notificationHovered) {
|
|
||||||
// The mouse is moving towards the notification, so don't
|
|
||||||
// hide it yet. (We just create a new timeout (and destroy
|
|
||||||
// the old one) each time because the bookkeeping is
|
|
||||||
// simpler.)
|
|
||||||
this._updateNotificationTimeout(1000);
|
|
||||||
} else if (this._useLongerNotificationLeftTimeout && !this._notificationLeftTimeoutId &&
|
|
||||||
(x != this._lastSeenMouseX || y != this._lastSeenMouseY)) {
|
|
||||||
// Refresh the timeout if the notification originally
|
|
||||||
// popped up under the pointer, and the pointer is hovering
|
|
||||||
// inside it.
|
|
||||||
this._updateNotificationTimeout(1000);
|
|
||||||
} else {
|
|
||||||
this._notificationTimeoutId = 0;
|
|
||||||
this._updateState();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._lastSeenMouseX = x;
|
|
||||||
this._lastSeenMouseY = y;
|
|
||||||
return GLib.SOURCE_REMOVE;
|
|
||||||
},
|
|
||||||
|
|
||||||
_hideNotification: function(animate) {
|
|
||||||
this._notificationFocusGrabber.ungrabFocus();
|
|
||||||
|
|
||||||
if (this._notificationClickedId) {
|
|
||||||
this._notification.disconnect(this._notificationClickedId);
|
|
||||||
this._notificationClickedId = 0;
|
|
||||||
}
|
|
||||||
if (this._notificationUnfocusedId) {
|
|
||||||
this._notification.disconnect(this._notificationUnfocusedId);
|
|
||||||
this._notificationUnfocusedId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._resetNotificationLeftTimeout();
|
|
||||||
|
|
||||||
if (animate) {
|
|
||||||
this._tween(this._notificationWidget, '_notificationState', State.HIDDEN,
|
|
||||||
{ opacity: 0,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onComplete: this._hideNotificationCompleted,
|
|
||||||
onCompleteScope: this
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Tweener.removeTweens(this._notificationWidget);
|
|
||||||
this._notificationWidget.opacity = 0;
|
|
||||||
this._notificationState = State.HIDDEN;
|
|
||||||
this._hideNotificationCompleted();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_hideNotificationCompleted: function() {
|
|
||||||
let notification = this._notification;
|
|
||||||
this._notification = null;
|
|
||||||
|
|
||||||
this._pointerInNotification = false;
|
|
||||||
this._notificationRemoved = false;
|
|
||||||
this._notificationBin.child = null;
|
|
||||||
this._notificationWidget.hide();
|
|
||||||
},
|
|
||||||
|
|
||||||
_ensureNotificationFocused: function() {
|
|
||||||
this._notificationFocusGrabber.grabFocus();
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
Signals.addSignalMethods(MessageTray.prototype);
|
Signals.addSignalMethods(MessageTray.prototype);
|
||||||
|
@ -114,7 +114,7 @@ const FdoNotificationDaemon = new Lang.Class({
|
|||||||
Main.overview.connect('hidden',
|
Main.overview.connect('hidden',
|
||||||
Lang.bind(this, this._onFocusAppChanged));
|
Lang.bind(this, this._onFocusAppChanged));
|
||||||
|
|
||||||
this._trayManager.manage_screen(global.screen, Main.messageTray.actor);
|
// this._trayManager.manage_screen(global.screen, Main.messageTray.actor);
|
||||||
},
|
},
|
||||||
|
|
||||||
_imageForNotificationData: function(hints) {
|
_imageForNotificationData: function(hints) {
|
||||||
|
Loading…
Reference in New Issue
Block a user