altTab: Take over cycle-windows/cycle-group keybindings

The code to handle cycling through windows without showing a popup
was removed from mutter a while ago, which left the corresponding
keybindings mostly broken (i.e. they now only switch between two
windows). With the various switch-foo keybindings handled by the
shell, it is now easier to take over the cycle-foo keybindings as
well.

https://bugzilla.gnome.org/show_bug.cgi?id=730739
This commit is contained in:
Florian Müllner 2016-05-19 14:41:24 +02:00
parent 5226d8b086
commit bd6e7f14d1
2 changed files with 113 additions and 0 deletions

View File

@ -354,6 +354,59 @@ const AppSwitcherPopup = new Lang.Class({
} }
}); });
const CyclerPopup = new Lang.Class({
Name: 'CyclerPopup',
Extends: SwitcherPopup.SwitcherPopup,
Abstract: true,
_init : function() {
this.parent();
this._items = this._getWindows();
if (this._items.length == 0)
return;
// We don't show an actual popup, so just provide what SwitcherPopup
// expects instead of inheriting from SwitcherList
this._switcherList = { actor: new St.Widget(),
highlight: Lang.bind(this, this._highlightItem),
connect: function() {} };
},
_highlightItem: function(index, justOutline) {
Main.activateWindow(this._items[index]);
},
_finish: function() {
this._highlightItem(this._selectedIndex);
this.parent();
}
});
const GroupCyclerPopup = new Lang.Class({
Name: 'GroupCyclerPopup',
Extends: CyclerPopup,
_getWindows: function() {
let app = Shell.WindowTracker.get_default().focus_app;
return app ? app.get_windows() : [];
},
_keyPressHandler: function(keysym, action) {
if (action == Meta.KeyBindingAction.CYCLE_GROUP)
this._select(this._next());
else if (action == Meta.KeyBindingAction.CYCLE_GROUP_BACKWARD)
this._select(this._previous());
else
return Clutter.EVENT_PROPAGATE;
return Clutter.EVENT_STOP;
}
});
const WindowSwitcherPopup = new Lang.Class({ const WindowSwitcherPopup = new Lang.Class({
Name: 'WindowSwitcherPopup', Name: 'WindowSwitcherPopup',
Extends: SwitcherPopup.SwitcherPopup, Extends: SwitcherPopup.SwitcherPopup,
@ -401,6 +454,32 @@ const WindowSwitcherPopup = new Lang.Class({
} }
}); });
const WindowCyclerPopup = new Lang.Class({
Name: 'WindowCyclerPopup',
Extends: CyclerPopup,
_init: function() {
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
this.parent();
},
_getWindows: function() {
let workspace = this._settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() : null;
return global.display.get_tab_list(Meta.TabList.NORMAL, workspace);
},
_keyPressHandler: function(keysym, action) {
if (action == Meta.KeyBindingAction.CYCLE_WINDOWS)
this._select(this._next());
else if (action == Meta.KeyBindingAction.CYCLE_WINDOWS_BACKWARD)
this._select(this._previous());
else
return Clutter.EVENT_PROPAGATE;
return Clutter.EVENT_STOP;
}
});
const AppIcon = new Lang.Class({ const AppIcon = new Lang.Class({
Name: 'AppIcon', Name: 'AppIcon',

View File

@ -866,6 +866,18 @@ const WindowManager = new Lang.Class({
this.setCustomKeybindingHandler('switch-windows-backward', this.setCustomKeybindingHandler('switch-windows-backward',
Shell.ActionMode.NORMAL, Shell.ActionMode.NORMAL,
Lang.bind(this, this._startWindowSwitcher)); Lang.bind(this, this._startWindowSwitcher));
this.setCustomKeybindingHandler('cycle-windows',
Shell.ActionMode.NORMAL,
Lang.bind(this, this._startWindowCycler));
this.setCustomKeybindingHandler('cycle-windows-backward',
Shell.ActionMode.NORMAL,
Lang.bind(this, this._startWindowCycler));
this.setCustomKeybindingHandler('cycle-group',
Shell.ActionMode.NORMAL,
Lang.bind(this, this._startGroupCycler));
this.setCustomKeybindingHandler('cycle-group-backward',
Shell.ActionMode.NORMAL,
Lang.bind(this, this._startGroupCycler));
this.setCustomKeybindingHandler('switch-panels', this.setCustomKeybindingHandler('switch-panels',
Shell.ActionMode.NORMAL | Shell.ActionMode.NORMAL |
Shell.ActionMode.OVERVIEW | Shell.ActionMode.OVERVIEW |
@ -1766,6 +1778,28 @@ const WindowManager = new Lang.Class({
tabPopup.destroy(); tabPopup.destroy();
}, },
_startWindowCycler : function(display, screen, window, binding) {
/* prevent a corner case where both popups show up at once */
if (this._workspaceSwitcherPopup != null)
this._workspaceSwitcherPopup.destroy();
let tabPopup = new AltTab.WindowCyclerPopup();
if (!tabPopup.show(binding.is_reversed(), binding.get_name(), binding.get_mask()))
tabPopup.destroy();
},
_startGroupCycler : function(display, screen, window, binding) {
/* prevent a corner case where both popups show up at once */
if (this._workspaceSwitcherPopup != null)
this._workspaceSwitcherPopup.destroy();
let tabPopup = new AltTab.GroupCyclerPopup();
if (!tabPopup.show(binding.is_reversed(), binding.get_name(), binding.get_mask()))
tabPopup.destroy();
},
_startA11ySwitcher : function(display, screen, window, binding) { _startA11ySwitcher : function(display, screen, window, binding) {
Main.ctrlAltTabManager.popup(binding.is_reversed(), binding.get_name(), binding.get_mask()); Main.ctrlAltTabManager.popup(binding.is_reversed(), binding.get_name(), binding.get_mask());
}, },