PopupMenu: redo keynav using St.FocusManager
Each menu is a focus manager group, but there is also some explicit focus handling between non-hierarchically-related widgets. Eg, to move between menus, or from a menubutton into its menu. https://bugzilla.gnome.org/show_bug.cgi?id=621671
This commit is contained in:
parent
5a83ef8325
commit
548a23a969
@ -501,11 +501,10 @@ AppWellIcon.prototype = {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this._menuManager.addMenu(this._menu, true);
|
this._menuManager.addMenu(this._menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._menu.popup();
|
this._menu.popup();
|
||||||
this._menuManager.grab();
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
@ -744,7 +744,8 @@ Panel.prototype = {
|
|||||||
let label = new St.Label({ text: _("Activities") });
|
let label = new St.Label({ text: _("Activities") });
|
||||||
this.button = new St.Clickable({ name: 'panelActivities',
|
this.button = new St.Clickable({ name: 'panelActivities',
|
||||||
style_class: 'panel-button',
|
style_class: 'panel-button',
|
||||||
reactive: true });
|
reactive: true,
|
||||||
|
can_focus: true });
|
||||||
this.button.set_child(label);
|
this.button.set_child(label);
|
||||||
|
|
||||||
this._leftBox.add(this.button);
|
this._leftBox.add(this.button);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const PopupMenu = imports.ui.popupMenu;
|
const PopupMenu = imports.ui.popupMenu;
|
||||||
@ -13,11 +14,13 @@ Button.prototype = {
|
|||||||
_init: function(menuAlignment) {
|
_init: function(menuAlignment) {
|
||||||
this.actor = new St.Bin({ style_class: 'panel-button',
|
this.actor = new St.Bin({ style_class: 'panel-button',
|
||||||
reactive: true,
|
reactive: true,
|
||||||
|
can_focus: true,
|
||||||
x_fill: true,
|
x_fill: true,
|
||||||
y_fill: false,
|
y_fill: false,
|
||||||
track_hover: true });
|
track_hover: true });
|
||||||
this.actor._delegate = this;
|
this.actor._delegate = this;
|
||||||
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
||||||
|
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPress));
|
||||||
this.menu = new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP, /* FIXME */ 0);
|
this.menu = new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP, /* FIXME */ 0);
|
||||||
this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
|
this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
|
||||||
Main.chrome.addActor(this.menu.actor, { visibleInOverview: true,
|
Main.chrome.addActor(this.menu.actor, { visibleInOverview: true,
|
||||||
@ -29,10 +32,27 @@ Button.prototype = {
|
|||||||
this.menu.toggle();
|
this.menu.toggle();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_onKeyPress: function(actor, event) {
|
||||||
|
let symbol = event.get_key_symbol();
|
||||||
|
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
|
||||||
|
this.menu.toggle();
|
||||||
|
return true;
|
||||||
|
} else if (symbol == Clutter.KEY_Down) {
|
||||||
|
if (!this.menu.isOpen)
|
||||||
|
this.menu.toggle();
|
||||||
|
this.menu.activateFirst();
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
_onOpenStateChanged: function(menu, open) {
|
_onOpenStateChanged: function(menu, open) {
|
||||||
if (open)
|
if (open) {
|
||||||
this.actor.add_style_pseudo_class('pressed');
|
this.actor.add_style_pseudo_class('pressed');
|
||||||
else
|
let focus = global.stage.get_key_focus();
|
||||||
|
if (!focus || (focus != this.actor && !menu.contains(focus)))
|
||||||
|
this.actor.grab_key_focus();
|
||||||
|
} else
|
||||||
this.actor.remove_style_pseudo_class('pressed');
|
this.actor.remove_style_pseudo_class('pressed');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -58,7 +58,8 @@ PopupBaseMenuItem.prototype = {
|
|||||||
hover: true });
|
hover: true });
|
||||||
this.actor = new Shell.GenericContainer({ style_class: 'popup-menu-item',
|
this.actor = new Shell.GenericContainer({ style_class: 'popup-menu-item',
|
||||||
reactive: params.reactive,
|
reactive: params.reactive,
|
||||||
track_hover: params.reactive });
|
track_hover: params.reactive,
|
||||||
|
can_focus: params.reactive });
|
||||||
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||||
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||||
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
||||||
@ -72,19 +73,39 @@ PopupBaseMenuItem.prototype = {
|
|||||||
this.active = false;
|
this.active = false;
|
||||||
|
|
||||||
if (params.reactive && params.activate) {
|
if (params.reactive && params.activate) {
|
||||||
this.actor.connect('button-release-event', Lang.bind(this, function (actor, event) {
|
this.actor.connect('button-release-event', Lang.bind(this, this._onButtonReleaseEvent));
|
||||||
this.emit('activate', event);
|
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
if (params.reactive && params.hover)
|
if (params.reactive && params.hover)
|
||||||
this.actor.connect('notify::hover', Lang.bind(this, this._hoverChanged));
|
this.actor.connect('notify::hover', Lang.bind(this, this._onHoverChanged));
|
||||||
|
if (params.reactive)
|
||||||
|
this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn));
|
||||||
},
|
},
|
||||||
|
|
||||||
_onStyleChanged: function (actor) {
|
_onStyleChanged: function (actor) {
|
||||||
this._spacing = actor.get_theme_node().get_length('spacing');
|
this._spacing = actor.get_theme_node().get_length('spacing');
|
||||||
},
|
},
|
||||||
|
|
||||||
_hoverChanged: function (actor) {
|
_onButtonReleaseEvent: function (actor, event) {
|
||||||
|
this.emit('activate', event);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onKeyPressEvent: function (actor, event) {
|
||||||
|
let symbol = event.get_key_symbol();
|
||||||
|
|
||||||
|
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
|
||||||
|
this.emit('activate', event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onKeyFocusIn: function (actor) {
|
||||||
|
this.setActive(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onHoverChanged: function (actor) {
|
||||||
this.setActive(actor.hover);
|
this.setActive(actor.hover);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -97,9 +118,10 @@ PopupBaseMenuItem.prototype = {
|
|||||||
|
|
||||||
if (activeChanged) {
|
if (activeChanged) {
|
||||||
this.active = active;
|
this.active = active;
|
||||||
if (active)
|
if (active) {
|
||||||
this.actor.add_style_pseudo_class('active');
|
this.actor.add_style_pseudo_class('active');
|
||||||
else
|
this.actor.grab_key_focus();
|
||||||
|
} else
|
||||||
this.actor.remove_style_pseudo_class('active');
|
this.actor.remove_style_pseudo_class('active');
|
||||||
this.emit('active-changed', active);
|
this.emit('active-changed', active);
|
||||||
}
|
}
|
||||||
@ -110,10 +132,6 @@ PopupBaseMenuItem.prototype = {
|
|||||||
this.emit('destroy');
|
this.emit('destroy');
|
||||||
},
|
},
|
||||||
|
|
||||||
handleKeyPress: function(event) {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
// true if non descendant content includes @actor
|
// true if non descendant content includes @actor
|
||||||
contains: function(actor) {
|
contains: function(actor) {
|
||||||
return false;
|
return false;
|
||||||
@ -337,6 +355,8 @@ PopupSliderMenuItem.prototype = {
|
|||||||
_init: function(value) {
|
_init: function(value) {
|
||||||
PopupBaseMenuItem.prototype._init.call(this, { activate: false });
|
PopupBaseMenuItem.prototype._init.call(this, { activate: false });
|
||||||
|
|
||||||
|
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
|
||||||
|
|
||||||
if (isNaN(value))
|
if (isNaN(value))
|
||||||
// Avoid spreading NaNs around
|
// Avoid spreading NaNs around
|
||||||
throw TypeError('The slider value must be a number');
|
throw TypeError('The slider value must be a number');
|
||||||
@ -482,10 +502,10 @@ PopupSliderMenuItem.prototype = {
|
|||||||
return this._value;
|
return this._value;
|
||||||
},
|
},
|
||||||
|
|
||||||
handleKeyPress: function(event) {
|
_onKeyPressEvent: function (actor, event) {
|
||||||
let key = event.get_key_symbol();
|
let key = event.get_key_symbol();
|
||||||
if (key == Clutter.Right || key == Clutter.Left) {
|
if (key == Clutter.KEY_Right || key == Clutter.KEY_Left) {
|
||||||
let delta = key == Clutter.Right ? 0.1 : -0.1;
|
let delta = key == Clutter.KEY_Right ? 0.1 : -0.1;
|
||||||
this._value = Math.max(0, Math.min(this._value + delta, 1));
|
this._value = Math.max(0, Math.min(this._value + delta, 1));
|
||||||
this._slider.queue_repaint();
|
this._slider.queue_repaint();
|
||||||
this.emit('value-changed', this._value);
|
this.emit('value-changed', this._value);
|
||||||
@ -611,6 +631,14 @@ PopupMenu.prototype = {
|
|||||||
this._boxWrapper.add_actor(this._box);
|
this._boxWrapper.add_actor(this._box);
|
||||||
this.actor.add_style_class_name('popup-menu');
|
this.actor.add_style_class_name('popup-menu');
|
||||||
|
|
||||||
|
global.focus_manager.add_group(this.actor);
|
||||||
|
|
||||||
|
if (sourceActor._delegate instanceof PopupSubMenuMenuItem) {
|
||||||
|
this._isSubMenu = true;
|
||||||
|
this.actor.reactive = true;
|
||||||
|
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
|
||||||
|
}
|
||||||
|
|
||||||
this.isOpen = false;
|
this.isOpen = false;
|
||||||
this._activeMenuItem = null;
|
this._activeMenuItem = null;
|
||||||
},
|
},
|
||||||
@ -709,12 +737,10 @@ PopupMenu.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
open: function(submenu) {
|
open: function() {
|
||||||
if (this.isOpen)
|
if (this.isOpen)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.emit('opening');
|
|
||||||
|
|
||||||
let primary = global.get_primary_monitor();
|
let primary = global.get_primary_monitor();
|
||||||
|
|
||||||
// We need to show it now to force an allocation,
|
// We need to show it now to force an allocation,
|
||||||
@ -730,7 +756,7 @@ PopupMenu.prototype = {
|
|||||||
let menuWidth = natWidth, menuHeight = natHeight;
|
let menuWidth = natWidth, menuHeight = natHeight;
|
||||||
|
|
||||||
// Position the non-pointing axis
|
// Position the non-pointing axis
|
||||||
if (submenu) {
|
if (this._isSubmenu) {
|
||||||
if (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM) {
|
if (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM) {
|
||||||
// vertical submenu
|
// vertical submenu
|
||||||
if (sourceY + sourceHeigth + menuHeight + this._gap < primary.y + primary.height)
|
if (sourceY + sourceHeigth + menuHeight + this._gap < primary.y + primary.height)
|
||||||
@ -763,8 +789,6 @@ PopupMenu.prototype = {
|
|||||||
if (!this.isOpen)
|
if (!this.isOpen)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.emit('closing');
|
|
||||||
|
|
||||||
if (this._activeMenuItem)
|
if (this._activeMenuItem)
|
||||||
this._activeMenuItem.setActive(false);
|
this._activeMenuItem.setActive(false);
|
||||||
this.actor.reactive = false;
|
this.actor.reactive = false;
|
||||||
@ -773,7 +797,6 @@ PopupMenu.prototype = {
|
|||||||
this.emit('open-state-changed', false);
|
this.emit('open-state-changed', false);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
toggle: function() {
|
toggle: function() {
|
||||||
if (this.isOpen)
|
if (this.isOpen)
|
||||||
this.close();
|
this.close();
|
||||||
@ -781,36 +804,16 @@ PopupMenu.prototype = {
|
|||||||
this.open();
|
this.open();
|
||||||
},
|
},
|
||||||
|
|
||||||
handleKeyPress: function(event, submenu) {
|
_onKeyPressEvent: function(actor, event) {
|
||||||
if (!this.isOpen || (submenu && !this._activeMenuItem))
|
// Move focus back to parent menu if the user types Left.
|
||||||
return false;
|
// (This handler is only connected if the PopupMenu is a
|
||||||
if (this._activeMenuItem && this._activeMenuItem.handleKeyPress(event))
|
// submenu.)
|
||||||
return true;
|
if (this.isOpen &&
|
||||||
switch (event.get_key_symbol()) {
|
this._activeMenuItem &&
|
||||||
case Clutter.space:
|
event.get_key_symbol() == Clutter.KEY_Left) {
|
||||||
case Clutter.Return:
|
|
||||||
if (this._activeMenuItem)
|
|
||||||
this._activeMenuItem.activate(event);
|
|
||||||
return true;
|
|
||||||
case Clutter.Down:
|
|
||||||
case Clutter.Up:
|
|
||||||
let items = this._box.get_children().filter(function (child) { return child.visible && child.reactive; });
|
|
||||||
let current = this._activeMenuItem ? this._activeMenuItem.actor : null;
|
|
||||||
let direction = event.get_key_symbol() == Clutter.Down ? 1 : -1;
|
|
||||||
|
|
||||||
let next = findNextInCycle(items, current, direction);
|
|
||||||
if (next) {
|
|
||||||
next._delegate.setActive(true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Clutter.Left:
|
|
||||||
if (submenu) {
|
|
||||||
this._activeMenuItem.setActive(false);
|
this._activeMenuItem.setActive(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
@ -844,6 +847,7 @@ PopupSubMenuMenuItem.prototype = {
|
|||||||
_init: function(text) {
|
_init: function(text) {
|
||||||
PopupBaseMenuItem.prototype._init.call(this, { activate: false, hover: false });
|
PopupBaseMenuItem.prototype._init.call(this, { activate: false, hover: false });
|
||||||
this.actor.connect('enter-event', Lang.bind(this, this._mouseEnter));
|
this.actor.connect('enter-event', Lang.bind(this, this._mouseEnter));
|
||||||
|
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
|
||||||
|
|
||||||
this.label = new St.Label({ text: text });
|
this.label = new St.Label({ text: text });
|
||||||
this.addActor(this.label);
|
this.addActor(this.label);
|
||||||
@ -888,7 +892,7 @@ PopupSubMenuMenuItem.prototype = {
|
|||||||
setActive: function(active) {
|
setActive: function(active) {
|
||||||
if (this.menu) {
|
if (this.menu) {
|
||||||
if (active)
|
if (active)
|
||||||
this.menu.open(true);
|
this.menu.open();
|
||||||
else
|
else
|
||||||
this.menu.close();
|
this.menu.close();
|
||||||
}
|
}
|
||||||
@ -896,14 +900,14 @@ PopupSubMenuMenuItem.prototype = {
|
|||||||
PopupBaseMenuItem.prototype.setActive.call(this, active);
|
PopupBaseMenuItem.prototype.setActive.call(this, active);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleKeyPress: function(event) {
|
_onKeyPressEvent: function(actor, event) {
|
||||||
if (!this.menu)
|
if (!this.menu)
|
||||||
return false;
|
return false;
|
||||||
if (event.get_key_symbol() == Clutter.Right) {
|
if (event.get_key_symbol() == Clutter.KEY_Right) {
|
||||||
this.menu.activateFirst();
|
this.menu.activateFirst();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return this.menu.handleKeyPress(event, true);
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
contains: function(actor) {
|
contains: function(actor) {
|
||||||
@ -929,6 +933,7 @@ PopupMenuManager.prototype = {
|
|||||||
this.grabbed = false;
|
this.grabbed = false;
|
||||||
|
|
||||||
this._eventCaptureId = 0;
|
this._eventCaptureId = 0;
|
||||||
|
this._keyPressEventId = 0;
|
||||||
this._enterEventId = 0;
|
this._enterEventId = 0;
|
||||||
this._leaveEventId = 0;
|
this._leaveEventId = 0;
|
||||||
this._activeMenu = null;
|
this._activeMenu = null;
|
||||||
@ -936,21 +941,20 @@ PopupMenuManager.prototype = {
|
|||||||
this._delayedMenus = [];
|
this._delayedMenus = [];
|
||||||
},
|
},
|
||||||
|
|
||||||
addMenu: function(menu, noGrab, position) {
|
addMenu: function(menu, position) {
|
||||||
let menudata = {
|
let menudata = {
|
||||||
menu: menu,
|
menu: menu,
|
||||||
openStateChangeId: menu.connect('open-state-changed', Lang.bind(this, this._onMenuOpenState)),
|
openStateChangeId: menu.connect('open-state-changed', Lang.bind(this, this._onMenuOpenState)),
|
||||||
activateId: menu.connect('activate', Lang.bind(this, this._onMenuActivated)),
|
activateId: menu.connect('activate', Lang.bind(this, this._onMenuActivated)),
|
||||||
destroyId: menu.connect('destroy', Lang.bind(this, this._onMenuDestroy)),
|
destroyId: menu.connect('destroy', Lang.bind(this, this._onMenuDestroy)),
|
||||||
enterId: 0,
|
enterId: 0,
|
||||||
buttonPressId: 0
|
focusId: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
let source = menu.sourceActor;
|
let source = menu.sourceActor;
|
||||||
if (source) {
|
if (source) {
|
||||||
menudata.enterId = source.connect('enter-event', Lang.bind(this, this._onMenuSourceEnter, menu));
|
menudata.enterId = source.connect('enter-event', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
|
||||||
if (!noGrab)
|
menudata.focusId = source.connect('key-focus-in', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
|
||||||
menudata.buttonPressId = source.connect('button-press-event', Lang.bind(this, this._onMenuSourcePress, menu));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (position == undefined)
|
if (position == undefined)
|
||||||
@ -974,8 +978,8 @@ PopupMenuManager.prototype = {
|
|||||||
|
|
||||||
if (menudata.enterId)
|
if (menudata.enterId)
|
||||||
menu.sourceActor.disconnect(menudata.enterId);
|
menu.sourceActor.disconnect(menudata.enterId);
|
||||||
if (menudata.buttonPressId)
|
if (menudata.focusId)
|
||||||
menu.sourceActor.disconnect(menudata.buttonPressId);
|
menu.sourceActor.disconnect(menudata.focusId);
|
||||||
|
|
||||||
this._menus.splice(position, 1);
|
this._menus.splice(position, 1);
|
||||||
},
|
},
|
||||||
@ -984,6 +988,7 @@ PopupMenuManager.prototype = {
|
|||||||
Main.pushModal(this._owner.actor);
|
Main.pushModal(this._owner.actor);
|
||||||
|
|
||||||
this._eventCaptureId = global.stage.connect('captured-event', Lang.bind(this, this._onEventCapture));
|
this._eventCaptureId = global.stage.connect('captured-event', Lang.bind(this, this._onEventCapture));
|
||||||
|
this._keyPressEventId = global.stage.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
|
||||||
// captured-event doesn't see enter/leave events
|
// captured-event doesn't see enter/leave events
|
||||||
this._enterEventId = global.stage.connect('enter-event', Lang.bind(this, this._onEventCapture));
|
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._leaveEventId = global.stage.connect('leave-event', Lang.bind(this, this._onEventCapture));
|
||||||
@ -994,24 +999,30 @@ PopupMenuManager.prototype = {
|
|||||||
ungrab: function() {
|
ungrab: function() {
|
||||||
global.stage.disconnect(this._eventCaptureId);
|
global.stage.disconnect(this._eventCaptureId);
|
||||||
this._eventCaptureId = 0;
|
this._eventCaptureId = 0;
|
||||||
|
global.stage.disconnect(this._keyPressEventId);
|
||||||
|
this._keyPressEventId = 0;
|
||||||
global.stage.disconnect(this._enterEventId);
|
global.stage.disconnect(this._enterEventId);
|
||||||
this._enterEventId = 0;
|
this._enterEventId = 0;
|
||||||
global.stage.disconnect(this._leaveEventId);
|
global.stage.disconnect(this._leaveEventId);
|
||||||
this._leaveEventId = 0;
|
this._leaveEventId = 0;
|
||||||
|
|
||||||
Main.popModal(this._owner.actor);
|
|
||||||
|
|
||||||
this.grabbed = false;
|
this.grabbed = false;
|
||||||
|
Main.popModal(this._owner.actor);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onMenuOpenState: function(menu, open) {
|
_onMenuOpenState: function(menu, open) {
|
||||||
if (!open && menu == this._activeMenu)
|
if (open) {
|
||||||
this._activeMenu = null;
|
|
||||||
else if (open)
|
|
||||||
this._activeMenu = menu;
|
this._activeMenu = menu;
|
||||||
|
if (!this.grabbed)
|
||||||
|
this.grab();
|
||||||
|
} else if (menu == this._activeMenu) {
|
||||||
|
this._activeMenu = null;
|
||||||
|
if (this.grabbed)
|
||||||
|
this.ungrab();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_onMenuSourceEnter: function(actor, event, menu) {
|
_onMenuSourceEnter: function(menu) {
|
||||||
if (!this.grabbed || menu == this._activeMenu)
|
if (!this.grabbed || menu == this._activeMenu)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -1021,13 +1032,6 @@ PopupMenuManager.prototype = {
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onMenuSourcePress: function(actor, event, menu) {
|
|
||||||
if (this.grabbed)
|
|
||||||
return false;
|
|
||||||
this.grab();
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onMenuActivated: function(menu, item) {
|
_onMenuActivated: function(menu, item) {
|
||||||
if (this.grabbed)
|
if (this.grabbed)
|
||||||
this.ungrab();
|
this.ungrab();
|
||||||
@ -1084,23 +1088,6 @@ PopupMenuManager.prototype = {
|
|||||||
|| (eventType == Clutter.EventType.KEY_PRESS && event.get_key_symbol() == Clutter.Escape)) {
|
|| (eventType == Clutter.EventType.KEY_PRESS && event.get_key_symbol() == Clutter.Escape)) {
|
||||||
this._closeMenu();
|
this._closeMenu();
|
||||||
return true;
|
return true;
|
||||||
} else if (eventType == Clutter.EventType.KEY_PRESS
|
|
||||||
&& this._activeMenu != null
|
|
||||||
&& this._activeMenu.handleKeyPress(event, false)) {
|
|
||||||
return true;
|
|
||||||
} else if (eventType == Clutter.EventType.KEY_PRESS
|
|
||||||
&& this._activeMenu != null
|
|
||||||
&& (event.get_key_symbol() == Clutter.Left
|
|
||||||
|| event.get_key_symbol() == Clutter.Right)) {
|
|
||||||
let direction = event.get_key_symbol() == Clutter.Right ? 1 : -1;
|
|
||||||
let pos = this._findMenu(this._activeMenu);
|
|
||||||
let next = this._menus[mod(pos + direction, this._menus.length)].menu;
|
|
||||||
if (next != this._activeMenu) {
|
|
||||||
this._activeMenu.close();
|
|
||||||
next.open(false);
|
|
||||||
next.activateFirst();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else if (activeMenuContains || this._eventIsOnAnyMenuSource(event)) {
|
} else if (activeMenuContains || this._eventIsOnAnyMenuSource(event)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1108,9 +1095,32 @@ PopupMenuManager.prototype = {
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_onKeyPressEvent: function(actor, event) {
|
||||||
|
if (!this.grabbed || !this._activeMenu)
|
||||||
|
return false;
|
||||||
|
if (!this._eventIsOnActiveMenu(event))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
let symbol = event.get_key_symbol();
|
||||||
|
if (symbol == Clutter.Left || symbol == Clutter.Right) {
|
||||||
|
let direction = symbol == Clutter.Right ? 1 : -1;
|
||||||
|
let pos = this._findMenu(this._activeMenu);
|
||||||
|
let next = this._menus[mod(pos + direction, this._menus.length)].menu;
|
||||||
|
if (next != this._activeMenu) {
|
||||||
|
let oldMenu = this._activeMenu;
|
||||||
|
this._activeMenu = next;
|
||||||
|
oldMenu.close();
|
||||||
|
next.open();
|
||||||
|
next.activateFirst();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
_closeMenu: function() {
|
_closeMenu: function() {
|
||||||
if (this._activeMenu != null)
|
if (this._activeMenu != null)
|
||||||
this._activeMenu.close();
|
this._activeMenu.close();
|
||||||
this.ungrab();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user