[gnome-shell] popupMenu: Port to GrabHelper
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] popupMenu: Port to GrabHelper
- Date: Sat, 8 Dec 2012 00:56:49 +0000 (UTC)
commit 9dfc3af9d7760634f390113e8867d903d6ee0a52
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Wed Feb 29 19:09:41 2012 -0500
popupMenu: Port to GrabHelper
https://bugzilla.gnome.org/show_bug.cgi?id=689109
js/ui/appDisplay.js | 1 +
js/ui/grabHelper.js | 13 +++-
js/ui/popupMenu.js | 226 ++++++++-------------------------------------------
3 files changed, 46 insertions(+), 194 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index c7250e1..944b246 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -567,6 +567,7 @@ const AppWellIcon = new Lang.Class({
this.actor.set_hover(true);
this._menu.popup();
+ this._menuManager.ignoreRelease();
return false;
},
diff --git a/js/ui/grabHelper.js b/js/ui/grabHelper.js
index 27e1e58..6e1c54c 100644
--- a/js/ui/grabHelper.js
+++ b/js/ui/grabHelper.js
@@ -92,6 +92,14 @@ const GrabHelper = new Lang.Class({
return this._grabStack[this._grabStack.length - 1] || {};
},
+ get grabbed() {
+ return this._grabStack.length > 0;
+ },
+
+ get grabStack() {
+ return this._grabStack;
+ },
+
_findStackIndex: function(actor) {
if (!actor)
return -1;
@@ -152,6 +160,7 @@ const GrabHelper = new Lang.Class({
params = Params.parse(params, { actor: null,
modal: false,
grabFocus: false,
+ focus: null,
onUngrab: null });
let focus = global.stage.key_focus;
@@ -169,7 +178,9 @@ const GrabHelper = new Lang.Class({
if (params.grabFocus && !this._takeFocusGrab(hadFocus))
return false;
- if (hadFocus || params.grabFocus)
+ if (params.focus)
+ params.focus.grab_key_focus();
+ else if (hadFocus || params.grabFocus)
_navigateActor(newFocus);
this._grabStack.push(params);
diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js
index a469388..a50264e 100644
--- a/js/ui/popupMenu.js
+++ b/js/ui/popupMenu.js
@@ -12,6 +12,7 @@ const St = imports.gi.St;
const Atk = imports.gi.Atk;
const BoxPointer = imports.ui.boxpointer;
+const GrabHelper = imports.ui.grabHelper;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
@@ -1204,7 +1205,6 @@ const PopupMenu = new Lang.Class({
this.actor = this._boxPointer.actor;
this.actor._delegate = this;
this.actor.style_class = 'popup-menu-boxpointer';
- this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
this._boxWrapper = new Shell.GenericContainer();
this._boxWrapper.connect('get-preferred-width', Lang.bind(this, this._boxGetPreferredWidth));
@@ -1234,15 +1234,6 @@ const PopupMenu = new Lang.Class({
this.box.allocate(box, flags);
},
- _onKeyPressEvent: function(actor, event) {
- if (event.get_key_symbol() == Clutter.Escape) {
- this.close(BoxPointer.PopupAnimation.FULL);
- return true;
- }
-
- return false;
- },
-
setArrowOrigin: function(origin) {
this._boxPointer.setArrowOrigin(origin);
},
@@ -1537,7 +1528,6 @@ const PopupComboMenu = new Lang.Class({
this.actor = this.box;
this.actor._delegate = this;
- this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn));
sourceActor.connect('style-changed',
Lang.bind(this, this._onSourceActorStyleChanged));
@@ -1545,15 +1535,6 @@ const PopupComboMenu = new Lang.Class({
global.focus_manager.add_group(this.actor);
},
- _onKeyPressEvent: function(actor, event) {
- if (event.get_key_symbol() == Clutter.Escape) {
- this.close(BoxPointer.PopupAnimation.FULL);
- return true;
- }
-
- return false;
- },
-
_onKeyFocusIn: function(actor) {
let items = this._getMenuItems();
let activeItem = items[this._activeItemPos];
@@ -2044,17 +2025,8 @@ const PopupMenuManager = new Lang.Class({
_init: function(owner) {
this._owner = owner;
- this.grabbed = false;
-
- this._eventCaptureId = 0;
- this._enterEventId = 0;
- this._leaveEventId = 0;
- this._keyFocusNotifyId = 0;
- this._activeMenu = null;
+ this._grabHelper = new GrabHelper.GrabHelper(owner.actor);
this._menus = [];
- this._menuStack = [];
- this._preGrabInputMode = null;
- this._grabbedFromKeynav = false;
},
addMenu: function(menu, position) {
@@ -2073,6 +2045,8 @@ const PopupMenuManager = new Lang.Class({
let source = menu.sourceActor;
if (source) {
+ if (!menu.blockSourceEvents)
+ this._grabHelper.addActor(source);
menudata.enterId = source.connect('enter-event', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
menudata.focusInId = source.connect('key-focus-in', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
}
@@ -2085,7 +2059,7 @@ const PopupMenuManager = new Lang.Class({
removeMenu: function(menu) {
if (menu == this._activeMenu)
- this._closeMenu();
+ this._closeMenu(menu);
let position = this._findMenu(menu);
if (position == -1) // not a menu we manage
@@ -2102,79 +2076,29 @@ const PopupMenuManager = new Lang.Class({
if (menudata.focusInId)
menu.sourceActor.disconnect(menudata.focusInId);
+ if (menu.sourceActor)
+ this._grabHelper.removeActor(menu.sourceActor);
this._menus.splice(position, 1);
},
- _grab: function() {
- Main.pushModal(this._owner.actor);
-
- this._eventCaptureId = global.stage.connect('captured-event', Lang.bind(this, this._onEventCapture));
- // captured-event doesn't see enter/leave events
- this._enterEventId = global.stage.connect('enter-event', Lang.bind(this, this._onEventCapture));
- this._leaveEventId = global.stage.connect('leave-event', Lang.bind(this, this._onEventCapture));
- this._keyFocusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
-
- this.grabbed = true;
+ get activeMenu() {
+ let actor = this._grabHelper.currentGrab.actor;
+ if (actor)
+ return actor._delegate;
+ else
+ return null;
},
- _ungrab: function() {
- global.stage.disconnect(this._eventCaptureId);
- this._eventCaptureId = 0;
- global.stage.disconnect(this._enterEventId);
- this._enterEventId = 0;
- global.stage.disconnect(this._leaveEventId);
- this._leaveEventId = 0;
- global.stage.disconnect(this._keyFocusNotifyId);
- this._keyFocusNotifyId = 0;
-
- this.grabbed = false;
- Main.popModal(this._owner.actor);
+ ignoreRelease: function() {
+ return this._grabHelper.ignoreRelease();
},
_onMenuOpenState: function(menu, open) {
if (open) {
- if (this._activeMenu && this._activeMenu.isChildMenu(menu)) {
- this._menuStack.push(this._activeMenu);
- menu.actor.grab_key_focus();
- }
- this._activeMenu = menu;
+ this._grabHelper.grab({ actor: menu.actor, modal: true, focus: menu.sourceActor,
+ onUngrab: Lang.bind(this, this._closeMenu, menu) });
} else {
- if (this._menuStack.length > 0) {
- this._activeMenu = this._menuStack.pop();
- if (menu.sourceActor)
- menu.sourceActor.grab_key_focus();
- this._didPop = true;
- }
- }
-
- // Check what the focus was before calling pushModal/popModal
- let focus = global.stage.key_focus;
- let hadFocus = focus && this._activeMenuContains(focus);
-
- if (open) {
- if (!this.grabbed) {
- this._preGrabInputMode = global.stage_input_mode;
- this._grabbedFromKeynav = hadFocus;
- this._grab();
- }
-
- if (hadFocus)
- focus.grab_key_focus();
- else
- menu.actor.grab_key_focus();
- } else if (menu == this._activeMenu) {
- if (this.grabbed)
- this._ungrab();
- this._activeMenu = null;
-
- if (this._grabbedFromKeynav) {
- if (this._preGrabInputMode == Shell.StageInputMode.FOCUSED)
- global.stage_input_mode = Shell.StageInputMode.FOCUSED;
- if (hadFocus && menu.sourceActor)
- menu.sourceActor.grab_key_focus();
- else if (focus)
- focus.grab_key_focus();
- }
+ this._grabHelper.ungrab({ actor: menu.actor });
}
},
@@ -2186,87 +2110,37 @@ const PopupMenuManager = new Lang.Class({
this.removeMenu(childMenu);
},
- // change the currently-open menu without dropping grab
_changeMenu: function(newMenu) {
- if (this._activeMenu) {
- // _onOpenMenuState will drop the grab if it sees
- // this._activeMenu being closed; so clear _activeMenu
- // before closing it to keep that from happening
- let oldMenu = this._activeMenu;
- this._activeMenu = null;
- for (let i = this._menuStack.length - 1; i >= 0; i--)
- this._menuStack[i].close(BoxPointer.PopupAnimation.FADE);
- oldMenu.close(BoxPointer.PopupAnimation.FADE);
- newMenu.open(BoxPointer.PopupAnimation.FADE);
- } else
- newMenu.open(BoxPointer.PopupAnimation.FULL);
+ if (this.activeMenu) {
+ this._closeMenu(this.activeMenu);
+ newMenu.open(false);
+ } else {
+ newMenu.open(true);
+ }
},
_onMenuSourceEnter: function(menu) {
- if (!this.grabbed || menu == this._activeMenu)
+ if (!this._grabHelper.grabbed)
return false;
- if (this._activeMenu && this._activeMenu.isChildMenu(menu))
+ if (this._grabHelper.isActorGrabbed(menu.actor))
return false;
- if (this._menuStack.indexOf(menu) != -1)
- return false;
-
- if (this._menuStack.length > 0 && this._menuStack[0].isChildMenu(menu))
+ let isChildMenu = this._grabHelper.grabStack.some(function(grab) {
+ let existingMenu = grab.actor._delegate;
+ return existingMenu.isChildMenu(menu);
+ });
+ if (isChildMenu)
return false;
this._changeMenu(menu);
return false;
},
- _onKeyFocusChanged: function() {
- if (!this.grabbed || !this._activeMenu)
- return;
-
- let focus = global.stage.key_focus;
- if (focus) {
- if (this._activeMenuContains(focus))
- return;
- if (this._menuStack.length > 0)
- return;
- if (focus._delegate && focus._delegate.menu &&
- this._findMenu(focus._delegate.menu) != -1)
- return;
- }
-
- this._closeMenu();
- },
-
_onMenuDestroy: function(menu) {
this.removeMenu(menu);
},
- _activeMenuContains: function(actor) {
- return this._activeMenu != null
- && (this._activeMenu.actor.contains(actor) ||
- (this._activeMenu.sourceActor && this._activeMenu.sourceActor.contains(actor)));
- },
-
- _eventIsOnActiveMenu: function(event) {
- return this._activeMenuContains(event.get_source());
- },
-
- _shouldBlockEvent: function(event) {
- let src = event.get_source();
-
- if (this._activeMenu != null && this._activeMenu.actor.contains(src))
- return false;
-
- for (let i = 0; i < this._menus.length; i++) {
- let menu = this._menus[i].menu;
- if (menu.sourceActor && !menu.blockSourceEvents && menu.sourceActor.contains(src)) {
- return false;
- }
- }
-
- return true;
- },
-
_findMenu: function(item) {
for (let i = 0; i < this._menus.length; i++) {
let menudata = this._menus[i];
@@ -2276,41 +2150,7 @@ const PopupMenuManager = new Lang.Class({
return -1;
},
- _onEventCapture: function(actor, event) {
- if (!this.grabbed)
- return false;
-
- if (this._owner.menuEventFilter &&
- this._owner.menuEventFilter(event))
- return true;
-
- if (this._didPop) {
- this._didPop = false;
- return true;
- }
-
- let activeMenuContains = this._eventIsOnActiveMenu(event);
- let eventType = event.type();
-
- if (eventType == Clutter.EventType.BUTTON_RELEASE) {
- if (activeMenuContains) {
- return false;
- } else {
- this._closeMenu();
- return true;
- }
- } else if (eventType == Clutter.EventType.BUTTON_PRESS && !activeMenuContains) {
- this._closeMenu();
- return true;
- } else if (!this._shouldBlockEvent(event)) {
- return false;
- }
-
- return true;
- },
-
- _closeMenu: function() {
- if (this._activeMenu != null)
- this._activeMenu.close(BoxPointer.PopupAnimation.FULL);
+ _closeMenu: function(menu) {
+ menu.close(BoxPointer.PopupAnimation.FULL);
}
});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]