ScreenShield: try harder to become modal, and catch failures

The screenshield was not checking the return value of pushModal(), meaning
that it believed it was fully locked when it was not. Later, calling
popModal() would fail, causing an exception and blocking the unlock.
Now we do nothing for user initiated actions, and fail with an explanatory
message at idle time.

https://bugzilla.gnome.org/show_bug.cgi?id=689106
This commit is contained in:
Giovanni Campagna 2012-11-26 20:18:57 +01:00 committed by Florian Müllner
parent 450db05b55
commit 7e0f84c7ce

View File

@ -442,6 +442,20 @@ const ScreenShield = new Lang.Class({
this.idleMonitor = Shell.IdleMonitor.get(); this.idleMonitor = Shell.IdleMonitor.get();
}, },
_becomeModal: function() {
if (this._isModal)
return true;
this._isModal = Main.pushModal(this.actor);
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 });
return this._isModal;
},
_onLockScreenKeyRelease: function(actor, event) { _onLockScreenKeyRelease: function(actor, event) {
let symbol = event.get_key_symbol(); let symbol = event.get_key_symbol();
@ -560,9 +574,17 @@ const ScreenShield = new Lang.Class({
} }
} }
if (!this._isModal) { if (!this._becomeModal()) {
Main.pushModal(this.actor); // We could not become modal, so we can't activate the
this._isModal = true; // 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._isActive) { if (!this._isActive) {
@ -604,9 +626,10 @@ const ScreenShield = new Lang.Class({
// 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
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
if (!this._isModal) { if (!this._becomeModal()) {
Main.pushModal(this.actor); // In the login screen, this is a hard error. Fail-whale
this._isModal = true; log('Could not acquire modal grab for the login screen. Aborting login process.');
Meta.quit(Meta.ExitCode.ERROR);
} }
return false; return false;
@ -862,9 +885,11 @@ const ScreenShield = new Lang.Class({
}, },
lock: function(animate) { lock: function(animate) {
if (!this._isModal) { // Warn the user if we can't become modal
Main.pushModal(this.actor); if (!this._becomeModal()) {
this._isModal = true; Main.notifyError("Unable to lock",
"Lock was blocked by an application");
return;
} }
if (this._activationTime == 0) if (this._activationTime == 0)