From 8cf9baa132c9fcdfc924f06dd0c2ebb5a8e57142 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Sun, 26 Aug 2012 16:53:08 +0200 Subject: [PATCH] ScreenShield: move lock status handling to use session mode Have distinct session modes for the lock screen and the unlock dialog, and rework the logic in ScreenShield to have the lock-screen mode stack onto the unlock-dialog mode (where applicable) https://bugzilla.gnome.org/show_bug.cgi?id=682542 --- js/ui/messageTray.js | 19 +++------- js/ui/screenShield.js | 87 +++++++++++++++++++++++-------------------- js/ui/sessionMode.js | 24 +++++++++++- js/ui/shellDBus.js | 4 +- 4 files changed, 76 insertions(+), 58 deletions(-) diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js index 1a6036651..fe04def49 100644 --- a/js/ui/messageTray.js +++ b/js/ui/messageTray.js @@ -1513,8 +1513,7 @@ const MessageTray = new Lang.Class({ this._updateState(); })); - this._isScreenLocked = false; - Main.screenShield.connect('lock-status-changed', Lang.bind(this, this._onScreenLockStatusChanged)); + Main.sessionMode.connect('updated', Lang.bind(this, this._updateState)); global.display.add_keybinding('toggle-message-tray', new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }), @@ -1688,11 +1687,6 @@ const MessageTray = new Lang.Class({ this._notificationQueue.splice(index, 1); }, - _onScreenLockStatusChanged: function(screenShield, locked) { - this._isScreenLocked = locked; - this._updateState(); - }, - _lock: function() { this._locked = true; }, @@ -1919,15 +1913,12 @@ const MessageTray = new Lang.Class({ _updateState: function() { // Notifications let notificationQueue = this._notificationQueue.filter(Lang.bind(this, function(notification) { - if (this._isScreenLocked) - return notification.showWhenLocked; - else - return true; + return notification.showWhenLocked || Main.sessionMode.hasNotifications; })); let notificationUrgent = notificationQueue.length > 0 && notificationQueue[0].urgency == Urgency.CRITICAL; // notificationsLimited is false when the screen is locked, because they go through // different filtering, and we want to show non urgent messages at times - let notificationsLimited = (this._busy || this._inFullscreen) && !this._isScreenLocked; + let notificationsLimited = (this._busy || this._inFullscreen) && Main.sessionMode.hasNotifications; let notificationsPending = notificationQueue.length > 0 && (!notificationsLimited || notificationUrgent); let nextNotification = notificationQueue.length > 0 ? notificationQueue[0] : null; let notificationPinned = this._pointerInTray && !this._pointerInSummary && !this._notificationRemoved; @@ -1938,7 +1929,7 @@ const MessageTray = new Lang.Class({ !this._pointerInTray && !this._locked && !(this._pointerInKeyboard && notificationExpanded); - let notificationLockedOut = this._isScreenLocked && (this._notification && !this._notification.showWhenLocked); + let notificationLockedOut = !Main.sessionMode.hasNotifications && (this._notification && !this._notification.showWhenLocked); // TODO: how to deal with locked out notiifcations if want to keep showing notifications?! let notificationMustClose = this._notificationRemoved || notificationLockedOut || (notificationExpired && this._userActiveWhileNotificationShown) || this._notificationClosed; let canShowNotification = notificationsPending && this._summaryState == State.HIDDEN; @@ -1968,7 +1959,7 @@ const MessageTray = new Lang.Class({ let summaryOptionalInOverview = this._overviewVisible && !this._locked && !summaryHovered; let mustHideSummary = (notificationsPending && (notificationUrgent || summaryOptionalInOverview)) - || notificationsVisible || this._isScreenLocked; + || notificationsVisible || !Main.sessionMode.hasNotifications; if (this._summaryState == State.HIDDEN && !mustHideSummary && summarySummoned) this._showSummary(); diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js index 1f6913ad2..3111047ef 100644 --- a/js/ui/screenShield.js +++ b/js/ui/screenShield.js @@ -422,8 +422,9 @@ const ScreenShield = new Lang.Class({ this._settings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA }); this._isModal = false; - this._isLocked = false; this._hasLockScreen = false; + this._isGreeter = false; + this._isActive = false; this._lightbox = new Lightbox.Lightbox(Main.uiGroup, { inhibitEvents: true, @@ -519,7 +520,7 @@ const ScreenShield = new Lang.Class({ // If we have a unlock dialog, cancel it if (this._dialog) { this._dialog.cancel(); - if (!this._keepDialog) { + if (!this._isGreeter) { this._dialog = null; } } @@ -530,7 +531,7 @@ const ScreenShield = new Lang.Class({ if (status == GnomeSession.PresenceStatus.IDLE) { if (this._dialog) { this._dialog.cancel(); - if (!this._keepDialog) { + if (!this._isGreeter) { this._dialog = null; } } @@ -540,14 +541,14 @@ const ScreenShield = new Lang.Class({ this._isModal = true; } - if (!this._isLocked) + if (!this._isActive) this._lightbox.show(); } else { let lightboxWasShown = this._lightbox.shown; this._lightbox.hide(); let shouldLock = lightboxWasShown && this._settings.get_boolean(LOCK_ENABLED_KEY); - if (shouldLock || this._isLocked) { + if (shouldLock || this._isActive) { this.lock(false); } else if (this._isModal) { this.unlock(); @@ -556,7 +557,13 @@ const ScreenShield = new Lang.Class({ }, showDialog: function() { - this.lock(true); + if (!this._isModal) { + Main.pushModal(this.actor); + this._isModal = true; + } + + this.actor.show(); + this._isGreeter = Main.sessionMode.isGreeter; this._ensureUnlockDialog(); this._hideLockScreen(false); }, @@ -590,25 +597,24 @@ const ScreenShield = new Lang.Class({ time: time, transition: 'linear', onComplete: function() { - this._lockScreenHidden(); + this._lockScreenState = MessageTray.State.HIDDEN; + this._lockScreenGroup.hide(); }, onCompleteScope: this, }); } else { - this._lockScreenHidden(); + this._lockScreenState = MessageTray.State.HIDDEN; + this._lockScreenGroup.hide(); } - }, - _lockScreenHidden: function() { - this._lockScreenState = MessageTray.State.HIDDEN; - this._lockScreenGroup.hide(); + if (Main.sessionMode.currentMode == 'lock-screen') + Main.sessionMode.popMode('lock-screen'); }, _ensureUnlockDialog: function() { if (!this._dialog) { let constructor = Main.sessionMode.unlockDialog; this._dialog = new constructor(this._lockDialogGroup); - this._keepDialog = Main.sessionMode.isGreeter; if (!this._dialog) { // This session mode has no locking capabilities this.unlock(); @@ -625,15 +631,6 @@ const ScreenShield = new Lang.Class({ this._dialog.connect('failed', Lang.bind(this, this._onUnlockFailed)); this._dialog.connect('unlocked', Lang.bind(this, this._onUnlockSucceded)); } - - if (Main.sessionMode.isGreeter) { - // Notify the other components that even though we are showing the - // screenshield, we're not in a locked state - // (this happens for the gdm greeter) - - this._isLocked = false; - this.emit('lock-status-changed', false); - } }, _onUnlockFailed: function() { @@ -648,6 +645,7 @@ const ScreenShield = new Lang.Class({ }, _resetLockScreen: function(animate) { + this._ensureLockScreen(); this._lockDialogGroup.scale_x = 1; this._lockDialogGroup.scale_y = 1; @@ -679,6 +677,9 @@ const ScreenShield = new Lang.Class({ } this._lockScreenGroup.grab_key_focus(); + + if (Main.sessionMode.currentMode != 'lock-screen') + Main.sessionMode.pushMode('lock-screen'); }, _lockScreenShown: function() { @@ -696,7 +697,10 @@ const ScreenShield = new Lang.Class({ // Some of the actors in the lock screen are heavy in // resources, so we only create them when needed - _prepareLockScreen: function() { + _ensureLockScreen: function() { + if (this._hasLockScreen) + return; + this._lockScreenContentsBox = new St.BoxLayout({ x_align: Clutter.ActorAlign.CENTER, y_align: Clutter.ActorAlign.CENTER, x_expand: true, @@ -738,7 +742,7 @@ const ScreenShield = new Lang.Class({ }, get locked() { - return this._isLocked; + return this._isActive; }, _tweenUnlocked: function() { @@ -760,13 +764,10 @@ const ScreenShield = new Lang.Class({ }, unlock: function() { - if (!this._isLocked) - return; - if (this._hasLockScreen) this._clearLockScreen(); - if (this._dialog && !this._keepDialog) { + if (this._dialog && !this._isGreeter) { this._dialog.destroy(); this._dialog = null; } @@ -778,30 +779,36 @@ const ScreenShield = new Lang.Class({ this._isModal = false; } - this._isLocked = false; + this.actor.hide(); - this.emit('lock-status-changed', false); - Main.sessionMode.popMode('lock-screen'); + if (Main.sessionMode.currentMode == 'lock-screen') + Main.sessionMode.popMode('lock-screen'); + if (Main.sessionMode.currentMode == 'unlock-dialog') + Main.sessionMode.popMode('unlock-dialog'); + + this._isActive = false; + this.emit('lock-status-changed'); }, lock: function(animate) { - if (this._isLocked) - return; - - if (!this._hasLockScreen) - this._prepareLockScreen(); - if (!this._isModal) { Main.pushModal(this.actor); this._isModal = true; } - this._isLocked = true; this.actor.show(); + + if (Main.sessionMode.currentMode != 'unlock-dialog' && + Main.sessionMode.currentMode != 'lock-screen') { + this._isGreeter = Main.sessionMode.isGreeter; + if (!this._isGreeter) + Main.sessionMode.pushMode('unlock-dialog'); + } + this._resetLockScreen(animate); - this.emit('lock-status-changed', true); - Main.sessionMode.pushMode('lock-screen'); + this._isActive = true; + this.emit('lock-status-changed'); }, }); Signals.addSignalMethods(ScreenShield.prototype); diff --git a/js/ui/sessionMode.js b/js/ui/sessionMode.js index 27c81a89f..14e1ff1f8 100644 --- a/js/ui/sessionMode.js +++ b/js/ui/sessionMode.js @@ -18,6 +18,7 @@ const _modes = { hasRunDialog: false, hasWorkspaces: false, hasWindows: false, + hasNotifications: false, isLocked: false, isGreeter: false, isPrimary: false, @@ -32,6 +33,7 @@ const _modes = { 'gdm': { allowKeybindingsWhenModal: true, + hasNotifications: true, isGreeter: true, isPrimary: true, unlockDialog: imports.gdm.loginDialog.LoginDialog, @@ -46,7 +48,6 @@ const _modes = { 'lock-screen': { isLocked: true, - isGreeter: undefined, unlockDialog: undefined, components: ['networkAgent', 'polkitAgent', 'telepathyClient'], panel: { @@ -56,6 +57,17 @@ const _modes = { }, }, + 'unlock-dialog': { + isLocked: true, + unlockDialog: undefined, + components: ['networkAgent', 'polkitAgent', 'telepathyClient'], + panel: { + left: ['userMenu'], + center: [], + right: ['a11y', 'keyboard', 'lockScreen'] + }, + }, + 'initial-setup': { isPrimary: true, components: ['keyring'], @@ -74,9 +86,10 @@ const _modes = { hasRunDialog: true, hasWorkspaces: true, hasWindows: true, - unlockDialog: imports.ui.unlockDialog.UnlockDialog, + hasNotifications: true, isLocked: false, isPrimary: true, + unlockDialog: imports.ui.unlockDialog.UnlockDialog, components: ['networkAgent', 'polkitAgent', 'telepathyClient', 'keyring', 'recorder', 'autorunManager', 'automountManager'], panel: { @@ -118,6 +131,13 @@ const SessionMode = new Lang.Class({ this._sync(); }, + switchMode: function(to) { + if (this.currentMode == to) + return; + this._modeStack[this._modeStack.length - 1] = to; + this._sync(); + }, + get currentMode() { return this._modeStack[this._modeStack.length - 1]; }, diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js index e85eabe65..5a43353fa 100644 --- a/js/ui/shellDBus.js +++ b/js/ui/shellDBus.js @@ -343,8 +343,8 @@ const ScreenSaverDBus = new Lang.Class({ _init: function() { this.parent(); - Main.screenShield.connect('lock-status-changed', Lang.bind(this, function(shield, locked) { - this._dbusImpl.emit_signal('ActiveChanged', GLib.Variant.new('(b)', [locked])); + Main.screenShield.connect('lock-status-changed', Lang.bind(this, function(shield) { + this._dbusImpl.emit_signal('ActiveChanged', GLib.Variant.new('(b)', [shield.locked])); })); this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreenSaverIface, this);