[panel] add keyboard navigation of menus
https://bugzilla.gnome.org/show_bug.cgi?id=619008
This commit is contained in:
parent
2179f5836e
commit
9b3e16595b
110
js/ui/panel.js
110
js/ui/panel.js
@ -138,6 +138,7 @@ PanelBaseMenuItem.prototype = {
|
|||||||
x_fill: true,
|
x_fill: true,
|
||||||
y_fill: true,
|
y_fill: true,
|
||||||
x_align: St.Align.START });
|
x_align: St.Align.START });
|
||||||
|
this.actor._delegate = this;
|
||||||
this.active = false;
|
this.active = false;
|
||||||
|
|
||||||
if (reactive) {
|
if (reactive) {
|
||||||
@ -280,6 +281,28 @@ PanelImageMenuItem.prototype = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function mod(a, b) {
|
||||||
|
return (a + b) % b;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findNextInCycle(items, current, direction) {
|
||||||
|
let cur;
|
||||||
|
|
||||||
|
if (items.length == 0)
|
||||||
|
return current;
|
||||||
|
else if (items.length == 1)
|
||||||
|
return items[0];
|
||||||
|
|
||||||
|
if (current)
|
||||||
|
cur = items.indexOf(current);
|
||||||
|
else if (direction == 1)
|
||||||
|
cur = items.length - 1;
|
||||||
|
else
|
||||||
|
cur = 0;
|
||||||
|
|
||||||
|
return items[mod(cur + direction, items.length)];
|
||||||
|
}
|
||||||
|
|
||||||
function PanelMenu(sourceButton) {
|
function PanelMenu(sourceButton) {
|
||||||
this._init(sourceButton);
|
this._init(sourceButton);
|
||||||
}
|
}
|
||||||
@ -294,6 +317,8 @@ PanelMenu.prototype = {
|
|||||||
vertical: true });
|
vertical: true });
|
||||||
this._boxPointer.bin.set_child(this._box);
|
this._boxPointer.bin.set_child(this._box);
|
||||||
this.actor.add_style_class_name('panel-menu');
|
this.actor.add_style_class_name('panel-menu');
|
||||||
|
|
||||||
|
this._activeMenuItem = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
addAction: function(title, callback) {
|
addAction: function(title, callback) {
|
||||||
@ -306,6 +331,15 @@ PanelMenu.prototype = {
|
|||||||
|
|
||||||
addMenuItem: function(menuItem) {
|
addMenuItem: function(menuItem) {
|
||||||
this._box.add(menuItem.actor);
|
this._box.add(menuItem.actor);
|
||||||
|
menuItem.connect('active-changed', Lang.bind(this, function (menuItem, active) {
|
||||||
|
if (active && this._activeMenuItem != menuItem) {
|
||||||
|
if (this._activeMenuItem)
|
||||||
|
this._activeMenuItem.setActive(false);
|
||||||
|
this._activeMenuItem = menuItem;
|
||||||
|
} else if (!active && this._activeMenuItem == menuItem) {
|
||||||
|
this._activeMenuItem = null;
|
||||||
|
}
|
||||||
|
}));
|
||||||
menuItem.connect('activate', Lang.bind(this, function (menuItem, event) {
|
menuItem.connect('activate', Lang.bind(this, function (menuItem, event) {
|
||||||
this.emit('activate');
|
this.emit('activate');
|
||||||
}));
|
}));
|
||||||
@ -317,6 +351,50 @@ PanelMenu.prototype = {
|
|||||||
|
|
||||||
setArrowOrigin: function(origin) {
|
setArrowOrigin: function(origin) {
|
||||||
this._boxPointer.setArrowOrigin(origin);
|
this._boxPointer.setArrowOrigin(origin);
|
||||||
|
},
|
||||||
|
|
||||||
|
open: function() {
|
||||||
|
let panelActor = Main.panel.actor;
|
||||||
|
this.actor.lower(panelActor);
|
||||||
|
|
||||||
|
this.actor.show();
|
||||||
|
this.actor.opacity = 0;
|
||||||
|
this.actor.reactive = true;
|
||||||
|
Tweener.addTween(this.actor, { opacity: 255,
|
||||||
|
transition: "easeOutQuad",
|
||||||
|
time: POPUP_ANIMATION_TIME });
|
||||||
|
},
|
||||||
|
|
||||||
|
close: function() {
|
||||||
|
this.actor.reactive = false;
|
||||||
|
Tweener.addTween(this.actor, { opacity: 0,
|
||||||
|
transition: "easeOutQuad",
|
||||||
|
time: POPUP_ANIMATION_TIME,
|
||||||
|
onComplete: Lang.bind(this, function () { this.actor.hide(); })});
|
||||||
|
if (this._activeMenuItem)
|
||||||
|
this._activeMenuItem.setActive(false);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleKeyPress: function(event) {
|
||||||
|
if (event.get_key_symbol() == Clutter.space ||
|
||||||
|
event.get_key_symbol() == Clutter.Return) {
|
||||||
|
if (this._activeMenuItem)
|
||||||
|
this._activeMenuItem.activate(event);
|
||||||
|
return true;
|
||||||
|
} else if (event.get_key_symbol() == Clutter.Down
|
||||||
|
|| event.get_key_symbol() == 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Signals.addSignalMethods(PanelMenu.prototype);
|
Signals.addSignalMethods(PanelMenu.prototype);
|
||||||
@ -339,6 +417,7 @@ PanelMenuButton.prototype = {
|
|||||||
x_fill: true,
|
x_fill: true,
|
||||||
y_fill: true,
|
y_fill: true,
|
||||||
track_hover: true });
|
track_hover: true });
|
||||||
|
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));
|
||||||
// FIXME - this will trigger a warning about a queued allocation from inside
|
// FIXME - this will trigger a warning about a queued allocation from inside
|
||||||
// allocate; hard to solve without a way to express a high level positioning
|
// allocate; hard to solve without a way to express a high level positioning
|
||||||
@ -358,14 +437,7 @@ PanelMenuButton.prototype = {
|
|||||||
return;
|
return;
|
||||||
this._state = this.State.OPEN;
|
this._state = this.State.OPEN;
|
||||||
|
|
||||||
let panelActor = Main.panel.actor;
|
this.menu.open();
|
||||||
this.menu.actor.lower(panelActor);
|
|
||||||
this.menu.actor.show();
|
|
||||||
this.menu.actor.opacity = 0;
|
|
||||||
this.menu.actor.reactive = true;
|
|
||||||
Tweener.addTween(this.menu.actor, { opacity: 255,
|
|
||||||
transition: "easeOutQuad",
|
|
||||||
time: POPUP_ANIMATION_TIME });
|
|
||||||
this._repositionMenu();
|
this._repositionMenu();
|
||||||
|
|
||||||
this.actor.add_style_pseudo_class('pressed');
|
this.actor.add_style_pseudo_class('pressed');
|
||||||
@ -428,11 +500,7 @@ PanelMenuButton.prototype = {
|
|||||||
if (this._state != this.State.OPEN)
|
if (this._state != this.State.OPEN)
|
||||||
return;
|
return;
|
||||||
this._state = this.State.CLOSED;
|
this._state = this.State.CLOSED;
|
||||||
this.menu.actor.reactive = false;
|
this.menu.close();
|
||||||
Tweener.addTween(this.menu.actor, { opacity: 0,
|
|
||||||
transition: "easeOutQuad",
|
|
||||||
time: POPUP_ANIMATION_TIME,
|
|
||||||
onComplete: Lang.bind(this, function () { this.menu.actor.hide(); })});
|
|
||||||
this.actor.remove_style_pseudo_class('pressed');
|
this.actor.remove_style_pseudo_class('pressed');
|
||||||
this.emit('open-state-changed', false);
|
this.emit('open-state-changed', false);
|
||||||
},
|
},
|
||||||
@ -558,9 +626,25 @@ PanelMenuBar.prototype = {
|
|||||||
this._activeMenuButton.close();
|
this._activeMenuButton.close();
|
||||||
this._closeMenu();
|
this._closeMenu();
|
||||||
return true;
|
return true;
|
||||||
|
} else if (eventType == Clutter.EventType.KEY_PRESS
|
||||||
|
&& this._activeMenuButton != null
|
||||||
|
&& this._activeMenuButton.menu.handleKeyPress(event)) {
|
||||||
|
return true;
|
||||||
|
} else if (eventType == Clutter.EventType.KEY_PRESS
|
||||||
|
&& this._activeMenuButton != null
|
||||||
|
&& (event.get_key_symbol() == Clutter.Left
|
||||||
|
|| event.get_key_symbol() == Clutter.Right)) {
|
||||||
|
let direction = event.get_key_symbol() == Clutter.Right ? 1 : -1;
|
||||||
|
let next = findNextInCycle(this._menus, this._activeMenuButton, direction);
|
||||||
|
if (next != this._activeMenuButton) {
|
||||||
|
this._activeMenuButton.close();
|
||||||
|
next.open();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
} else if (activeMenuContains || this._eventIsOnAnyMenuButton(event)) {
|
} else if (activeMenuContains || this._eventIsOnAnyMenuButton(event)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user