ScreenShield: fade the screen to black when locking manually

When locking manually (or locking with an animation), fade the
screen to black after a small timeout. This provides a smoother
experience, instead of abruptly turning off the screen.

https://bugzilla.gnome.org/show_bug.cgi?id=699112
This commit is contained in:
Giovanni Campagna 2013-08-17 19:40:09 +02:00
parent 6b8339e9b4
commit 2a2bcc8984

View File

@ -580,11 +580,17 @@ const ScreenShield = new Lang.Class({
this._becameActiveId = 0; this._becameActiveId = 0;
this._lockTimeoutId = 0; this._lockTimeoutId = 0;
this._lightbox = new Lightbox.Lightbox(Main.uiGroup, // The "long" lightbox is used for the longer (20 seconds) fade from session
// to idle status, the "short" is used for quickly fading to black when locking
// manually
this._longLightbox = new Lightbox.Lightbox(Main.uiGroup,
{ inhibitEvents: true, { inhibitEvents: true,
fadeInTime: STANDARD_FADE_TIME,
fadeFactor: 1 }); fadeFactor: 1 });
this._lightbox.connect('shown', Lang.bind(this, this._onLightboxShown)); this._longLightbox.connect('shown', Lang.bind(this, this._onLongLightboxShown));
this._shortLightbox = new Lightbox.Lightbox(Main.uiGroup,
{ inhibitEvents: true,
fadeFactor: 1 });
this._shortLightbox.connect('shown', Lang.bind(this, this._onShortLightboxShown));
this.idleMonitor = new GnomeDesktop.IdleMonitor(); this.idleMonitor = new GnomeDesktop.IdleMonitor();
}, },
@ -807,7 +813,7 @@ const ScreenShield = new Lang.Class({
this._maybeCancelDialog(); this._maybeCancelDialog();
if (this._lightbox.actor.visible || if (this._longLightbox.actor.visible ||
this._isActive) { this._isActive) {
// We're either shown and active, or in the process of // We're either shown and active, or in the process of
// showing. // showing.
@ -833,13 +839,9 @@ const ScreenShield = new Lang.Class({
return; return;
} }
this._lightbox.show();
if (this._activationTime == 0) if (this._activationTime == 0)
this._activationTime = GLib.get_monotonic_time(); this._activationTime = GLib.get_monotonic_time();
this._becameActiveId = this.idleMonitor.add_user_active_watch(Lang.bind(this, this._onUserBecameActive));
let shouldLock = this._settings.get_boolean(LOCK_ENABLED_KEY) && !this._isLocked; let shouldLock = this._settings.get_boolean(LOCK_ENABLED_KEY) && !this._isLocked;
if (shouldLock) { if (shouldLock) {
@ -847,48 +849,59 @@ const ScreenShield = new Lang.Class({
this._lockTimeoutId = Mainloop.timeout_add(lockTimeout * 1000, this._lockTimeoutId = Mainloop.timeout_add(lockTimeout * 1000,
Lang.bind(this, function() { Lang.bind(this, function() {
this._lockTimeoutId = 0; this._lockTimeoutId = 0;
this.lock(true); this.lock(false);
return false; return false;
})); }));
} }
this._activateFade(this._longLightbox, STANDARD_FADE_TIME);
},
_activateFade: function(lightbox, time) {
lightbox.show(time);
if (this._becameActiveId == 0)
this._becameActiveId = this.idleMonitor.add_user_active_watch(Lang.bind(this, this._onUserBecameActive));
}, },
_onUserBecameActive: function() { _onUserBecameActive: function() {
// This function gets called here when the user becomes active // This function gets called here when the user becomes active
// after gnome-session changed the status to IDLE // after we activated a lightbox
// There are four possibilities here: // There are two possibilities here:
// - we're called when already locked; isActive and isLocked are true, // - we're called when already locked/active; isLocked or isActive is true,
// we just go back to the lock screen curtain // we just go back to the lock screen curtain
// - we're called before the lightbox is fully shown; at this point // (isActive == isLocked == true: normal case
// isActive is false, so we just hide the ligthbox, reset the activationTime // isActive == false, isLocked == true: during the fade for manual locking
// and go back to the unlocked desktop // isActive == true, isLocked == false: after session idle, before lock-delay)
// - we're called after showing the lightbox, but before the lock // - we're called because the session is IDLE but before the lightbox
// delay; this is mostly like the case above, but isActive is true now // is fully shown; at this point isActive is false, so we just hide
// so we need to notify gnome-settings-daemon to go back to the normal // the lightbox, reset the activationTime and go back to the unlocked
// policies for blanking // desktop
// (they're handled by the same code, and we emit one extra ActiveChanged // using deactivate() is a little of overkill, but it ensures we
// signal in the case above) // don't forget of some bit like modal, DBus properties or idle watches
// - we're called after showing the lightbox and after lock-delay; the //
// session is effectivelly locked now, it's time to build and show // Note: if the (long) lightbox is shown then we're necessarily
// the lock screen // active, because we call activate() without animation.
this.idleMonitor.remove_watch(this._becameActiveId); this.idleMonitor.remove_watch(this._becameActiveId);
this._becameActiveId = 0; this._becameActiveId = 0;
let lightboxWasShown = this._lightbox.shown; if (this._isActive || this._isLocked) {
this._lightbox.hide(); this._longLightbox.hide();
this._shortLightbox.hide();
// Shortcircuit in case the mouse was moved before the fade completed } else {
if (!lightboxWasShown) {
this.deactivate(false); this.deactivate(false);
return;
} }
}, },
_onLightboxShown: function() { _onLongLightboxShown: function() {
this.activate(false); this.activate(false);
}, },
_onShortLightboxShown: function() {
this._completeLockScreenShown();
},
showDialog: function() { showDialog: function() {
// Ensure that the stage window is mapped, before taking a grab // Ensure that the stage window is mapped, before taking a grab
// otherwise X errors out // otherwise X errors out
@ -980,7 +993,8 @@ const ScreenShield = new Lang.Class({
_onUnlockFailed: function() { _onUnlockFailed: function() {
this._resetLockScreen({ animateLockScreen: true, this._resetLockScreen({ animateLockScreen: true,
animateLockDialog: false }); animateLockDialog: false,
fadeToBlack: false });
}, },
_resetLockScreen: function(params) { _resetLockScreen: function(params) {
@ -998,6 +1012,8 @@ const ScreenShield = new Lang.Class({
this._lockScreenGroup.show(); this._lockScreenGroup.show();
this._lockScreenState = MessageTray.State.SHOWING; this._lockScreenState = MessageTray.State.SHOWING;
let fadeToBlack = params.fadeToBlack;
if (params.animateLockScreen) { if (params.animateLockScreen) {
this._lockScreenGroup.y = -global.screen_height; this._lockScreenGroup.y = -global.screen_height;
Tweener.removeTweens(this._lockScreenGroup); Tweener.removeTweens(this._lockScreenGroup);
@ -1006,13 +1022,15 @@ const ScreenShield = new Lang.Class({
time: MANUAL_FADE_TIME, time: MANUAL_FADE_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
onComplete: function() { onComplete: function() {
this._lockScreenShown(); this._lockScreenShown({ fadeToBlack: fadeToBlack,
animateFade: true });
}, },
onCompleteScope: this onCompleteScope: this
}); });
} else { } else {
this._lockScreenGroup.fixed_position_set = false; this._lockScreenGroup.fixed_position_set = false;
this._lockScreenShown(); this._lockScreenShown({ fadeToBlack: fadeToBlack,
animateFade: false });
} }
if (params.animateLockDialog) { if (params.animateLockDialog) {
@ -1079,7 +1097,7 @@ const ScreenShield = new Lang.Class({
this._pauseArrowAnimation(); this._pauseArrowAnimation();
}, },
_lockScreenShown: function() { _lockScreenShown: function(params) {
if (this._dialog && !this._isGreeter) { if (this._dialog && !this._isGreeter) {
this._dialog.destroy(); this._dialog.destroy();
this._dialog = null; this._dialog = null;
@ -1101,6 +1119,21 @@ const ScreenShield = new Lang.Class({
this._lockScreenGroup.fixed_position_set = false; this._lockScreenGroup.fixed_position_set = false;
this._lockScreenScrollCounter = 0; this._lockScreenScrollCounter = 0;
if (params.fadeToBlack && params.animateFade) {
// Take a beat
Mainloop.timeout_add(1000 * MANUAL_FADE_TIME, Lang.bind(this, function() {
this._activateFade(this._shortLightbox, MANUAL_FADE_TIME);
}));
} else {
if (params.fadeToBlack)
this._activateFade(this._shortLightbox, 0);
this._completeLockScreenShown();
}
},
_completeLockScreenShown: function() {
let prevIsActive = this._isActive; let prevIsActive = this._isActive;
this._isActive = true; this._isActive = true;
@ -1225,7 +1258,8 @@ const ScreenShield = new Lang.Class({
this._dialog = null; this._dialog = null;
} }
this._lightbox.hide(); this._longLightbox.hide();
this._shortLightbox.hide();
this.actor.hide(); this.actor.hide();
if (this._becameActiveId != 0) { if (this._becameActiveId != 0) {
@ -1260,7 +1294,8 @@ const ScreenShield = new Lang.Class({
} }
this._resetLockScreen({ animateLockScreen: animate, this._resetLockScreen({ animateLockScreen: animate,
animateLockDialog: animate }); animateLockDialog: animate,
fadeToBlack: true });
global.set_runtime_state(LOCKED_STATE_STR, GLib.Variant.new('b', true)); global.set_runtime_state(LOCKED_STATE_STR, GLib.Variant.new('b', true));
// We used to set isActive and emit active-changed here, // We used to set isActive and emit active-changed here,