Enable insertion and removal of menus
This patch adds the method "removeMenu" to PopupMenuManager, to allow for removal of menus after they're inserted. In order to do this, it needs to store along with the menu all the relevant signal connections, that are disconnected when the menu is removed. Also adds a parameter "position" to "addMenu", so that menus can added in arbitrary order (in particular to reintroduce those which were removed). This patch is intended towards dynamic menu users, like extensions for application lists, docks, sidebars showing recent documents or favourites, as well as advanced system tray implementations. https://bugzilla.gnome.org/show_bug.cgi?id=622730
This commit is contained in:
parent
4aa80105ca
commit
d8df46d4a1
@ -429,17 +429,45 @@ PopupMenuManager.prototype = {
|
||||
this._delayedMenus = [];
|
||||
},
|
||||
|
||||
addMenu: function(menu, noGrab) {
|
||||
this._menus.push(menu);
|
||||
menu.connect('open-state-changed', Lang.bind(this, this._onMenuOpenState));
|
||||
menu.connect('activate', Lang.bind(this, this._onMenuActivated));
|
||||
addMenu: function(menu, noGrab, position) {
|
||||
let menudata = {
|
||||
menu: menu,
|
||||
openStateChangeId: menu.connect('open-state-changed', Lang.bind(this, this._onMenuOpenState)),
|
||||
activateId: menu.connect('activate', Lang.bind(this, this._onMenuActivated)),
|
||||
enterId: 0,
|
||||
buttonPressId: 0
|
||||
};
|
||||
|
||||
let source = menu.sourceActor;
|
||||
if (source) {
|
||||
source.connect('enter-event', Lang.bind(this, this._onMenuSourceEnter, menu));
|
||||
menudata.enterId = source.connect('enter-event', Lang.bind(this, this._onMenuSourceEnter, menu));
|
||||
if (!noGrab)
|
||||
source.connect('button-press-event', Lang.bind(this, this._onMenuSourcePress, menu));
|
||||
menudata.buttonPressId = source.connect('button-press-event', Lang.bind(this, this._onMenuSourcePress, menu));
|
||||
}
|
||||
|
||||
if (position == undefined)
|
||||
this._menus.push(menudata);
|
||||
else
|
||||
this._menus.splice(position, 0, menudata);
|
||||
},
|
||||
|
||||
removeMenu: function(menu) {
|
||||
if (menu == this._activeMenu)
|
||||
this._closeMenu();
|
||||
let position = this._findMenu(menu);
|
||||
if (position == -1) // not a menu we manage
|
||||
return;
|
||||
|
||||
let menudata = this._menus[position];
|
||||
menu.disconnect(menudata.openStateChangeId);
|
||||
menu.disconnect(menudata.activateId);
|
||||
|
||||
if (menudata.enterId)
|
||||
menu.sourceActor.disconnect(menudata.enterId);
|
||||
if (menudata.buttonPressId)
|
||||
menu.sourceActor.disconnect(menudata.buttonPressId);
|
||||
|
||||
this._menus.splice(position, 1);
|
||||
},
|
||||
|
||||
grab: function() {
|
||||
@ -505,13 +533,22 @@ PopupMenuManager.prototype = {
|
||||
_eventIsOnAnyMenuSource: function(event) {
|
||||
let src = event.get_source();
|
||||
for (let i = 0; i < this._menus.length; i++) {
|
||||
let menu = this._menus[i];
|
||||
let menu = this._menus[i].menu;
|
||||
if (menu.sourceActor && menu.sourceActor.contains(src))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_findMenu: function(item) {
|
||||
for (let i = 0; i < this._menus.length; i++) {
|
||||
let menudata = this._menus[i];
|
||||
if (item == menudata.menu)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
|
||||
_onEventCapture: function(actor, event) {
|
||||
if (!this.grabbed)
|
||||
return false;
|
||||
@ -542,7 +579,8 @@ PopupMenuManager.prototype = {
|
||||
&& (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._activeMenu, direction);
|
||||
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();
|
||||
|
Loading…
Reference in New Issue
Block a user