diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js index 506b60d36..d57a94ed3 100644 --- a/js/ui/screenShield.js +++ b/js/ui/screenShield.js @@ -568,6 +568,21 @@ const ScreenShield = new Lang.Class({ } }, + _becomeModal: function() { + if (this._isModal) + return true; + + this._isModal = Main.pushModal(this.actor, { keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN }); + if (this._isModal) + return true; + + // We failed to get a pointer grab, it means that + // something else has it. Try with a keyboard grab only + this._isModal = Main.pushModal(this.actor, { options: Meta.ModalOptions.POINTER_ALREADY_GRABBED, + keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN }); + return this._isModal; + }, + _onLockScreenKeyRelease: function(actor, event) { let symbol = event.get_key_symbol(); @@ -725,10 +740,18 @@ const ScreenShield = new Lang.Class({ } } - if (!this._isModal) { - Main.pushModal(this.actor, { keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN }); - this._isModal = true; - } + if (!this._becomeModal()) { + // We could not become modal, so we can't activate the + // screenshield. The user is probably very upset at this + // point, but any application using global grabs is broken + // Just tell him to stop using this app + // + // XXX: another option is to kick the user into the gdm login + // screen, where we're not affected by grabs + Main.notifyError(_("Unable to lock"), + _("Lock was blocked by an application")); + return; + } if (this._lightbox.actor.visible || this._isActive) { @@ -805,9 +828,10 @@ const ScreenShield = new Lang.Class({ // Ensure that the stage window is mapped, before taking a grab // otherwise X errors out Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { - if (!this._isModal) { - Main.pushModal(this.actor); - this._isModal = true; + if (!this._becomeModal()) { + // In the login screen, this is a hard error. Fail-whale + log('Could not acquire modal grab for the login screen. Aborting login process.'); + Meta.quit(Meta.ExitCode.ERROR); } return false; @@ -1135,9 +1159,11 @@ const ScreenShield = new Lang.Class({ }, lock: function(animate) { - if (!this._isModal) { - Main.pushModal(this.actor, { keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN }); - this._isModal = true; + // Warn the user if we can't become modal + if (!this._becomeModal()) { + Main.notifyError(_("Unable to lock"), + _("Lock was blocked by an application")); + return; } this._isLocked = true;