[gnome-shell] grabHelper: Introduce a stack of grab helpers
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] grabHelper: Introduce a stack of grab helpers
- Date: Mon, 19 Aug 2013 13:35:16 +0000 (UTC)
commit 8d9aa6388dec6ce2c9b7d87c30c594481ce30e53
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Fri Aug 16 20:11:36 2013 -0400
grabHelper: Introduce a stack of grab helpers
GrabHelpers use a 'captured-event' to steal events and emulate
modality or grab-like semantics. There can be issues when you try to
use multiple GrabHelpers stacked on each other. As Clutter follows
the DOM-like semantics of "first come, first serve", when a second
GrabHelper connects to 'captured-event', its callback will only be
processed *after* the first GrabHelper's callback is called.
This breaks the expectation of narrowing modality where new modals
take priority over the old ones.
Solving this globally in a cleaner manner would require a rewrite of
pushModal/GrabHelper. As a stopgap fix for now, use one shared
'captured-event' handler between all GrabHelper instances, and
delegate to the individual GrabHelpers.
https://bugzilla.gnome.org/show_bug.cgi?id=699272
js/ui/grabHelper.js | 33 ++++++++++++++++++++++++++++-----
1 files changed, 28 insertions(+), 5 deletions(-)
---
diff --git a/js/ui/grabHelper.js b/js/ui/grabHelper.js
index 296ce46..b022d1d 100644
--- a/js/ui/grabHelper.js
+++ b/js/ui/grabHelper.js
@@ -10,6 +10,31 @@ const St = imports.gi.St;
const Main = imports.ui.main;
const Params = imports.misc.params;
+let _capturedEventId = 0;
+let _grabHelperStack = [];
+function _onCapturedEvent(actor, event) {
+ let grabHelper = _grabHelperStack[_grabHelperStack.length - 1];
+ return grabHelper.onCapturedEvent(event);
+}
+
+function _pushGrabHelper(grabHelper) {
+ _grabHelperStack.push(grabHelper);
+
+ if (_capturedEventId == 0)
+ _capturedEventId = global.stage.connect('captured-event', _onCapturedEvent);
+}
+
+function _popGrabHelper(grabHelper) {
+ let poppedHelper = _grabHelperStack.pop();
+ if (poppedHelper != grabHelper)
+ throw new Error("incorrect grab helper pop");
+
+ if (_grabHelperStack.length == 0) {
+ global.stage.disconnect(_capturedEventId);
+ _capturedEventId = 0;
+ }
+}
+
// GrabHelper:
// @owner: the actor that owns the GrabHelper
// @params: optional parameters to pass to Main.pushModal()
@@ -31,7 +56,6 @@ const GrabHelper = new Lang.Class({
this._grabStack = [];
this._actors = [];
- this._capturedEventId = 0;
this._ignoreRelease = false;
this._modalCount = 0;
@@ -177,7 +201,7 @@ const GrabHelper = new Lang.Class({
if (!Main.pushModal(this._owner, this._modalParams))
return false;
- this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this,
this._onCapturedEvent));
+ _pushGrabHelper(this);
}
this._modalCount++;
@@ -189,8 +213,7 @@ const GrabHelper = new Lang.Class({
if (this._modalCount > 0)
return;
- global.stage.disconnect(this._capturedEventId);
- this._capturedEventId = 0;
+ _popGrabHelper(this);
this._ignoreRelease = false;
@@ -251,7 +274,7 @@ const GrabHelper = new Lang.Class({
}
},
- _onCapturedEvent: function(actor, event) {
+ onCapturedEvent: function(event) {
let type = event.type();
if (type == Clutter.EventType.KEY_PRESS &&
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]