From 73a4e27bf727f71e81604e117e85d07accd1fa86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Hedin=20Br=C3=B8nner?= Date: Sat, 26 Oct 2019 22:48:38 +0200 Subject: [PATCH] action dispatcher: Introduce global pseudo focus while navigating The action dispatcher would only allow actions to operate on tiled windows. However some actions, like cycleWindowWidth, are able to operate on eg. scratch windows, while it at the same time wants context between repeated cycles. To solve this we add an explicitly tracked pseduo focus to the dispatcher. Actions can now return a MetaWindow which then becomes the new focus. This should pave the way for us to integrate eg. alt-tab with the dispatcher. --- keybindings.js | 4 +++- navigator.js | 12 ++++++++++-- tiling.js | 19 +++++++++++-------- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/keybindings.js b/keybindings.js index 59ae4fe..d73ec0b 100644 --- a/keybindings.js +++ b/keybindings.js @@ -250,13 +250,15 @@ function impliedOptions(options) { } /** - * handler: function(metaWindow, space, {binding, display, screen}) -> ignored + * handler: function(metaWindow, space, {binding, display, screen}) -> metaWindow | null * options: { * opensMinimap: true|false Start navigation and open the minimap * opensNavigator: true|false Start navigation (eg. Esc will restore selected space and window) * activeInNavigator: true|false Action is available during navigation * ... * } + * The optionally returned window determines pseudo focus while navigating. Ie. + * the next action will operate on this window. */ function registerAction(actionName, handler, options) { options = impliedOptions(options) diff --git a/navigator.js b/navigator.js index b947cc5..6f7981f 100644 --- a/navigator.js +++ b/navigator.js @@ -57,6 +57,8 @@ var ActionDispatcher = class { this.contexts = new Map(); + this.focus = display.focus_window; + this.actor.connect('key-press-event', this._keyPressEvent.bind(this)); this.actor.connect('key-release-event', this._keyReleaseEvent.bind(this)); @@ -151,7 +153,10 @@ var ActionDispatcher = class { let action = Keybindings.byId(mutterActionId); let space = Tiling.spaces.selectedSpace; - let metaWindow = space.selectedWindow; + // Make sure the window is alive + if (this.focus && !this.focus.get_compositor_private()) + this.focus = space.selectedWindow; + let metaWindow = this.focus; if (this.lastAction !== action) { this.contexts.delete(action); @@ -164,7 +169,10 @@ var ActionDispatcher = class { if (action.options.opensMinimap) { this.navigator._showMinimap(space); } - action.handler(metaWindow, space, {navigator: this.navigator, context}); + let focus = action.handler(metaWindow, space, {navigator: this.navigator, context}); + if (focus && focus.constructor.name.match('MetaWindow')) { + this.focus = focus; + } if (space !== Tiling.spaces.selectedSpace) { this.navigator.minimaps.forEach(m => typeof(m) === 'number' ? Mainloop.source_remove(m) : m.hide()); diff --git a/tiling.js b/tiling.js index a73bb69..19b76b6 100644 --- a/tiling.js +++ b/tiling.js @@ -704,13 +704,13 @@ class Space extends Array { let metaWindow = this.getWindow(index, row); ensureViewport(metaWindow, this); - return true; + return metaWindow; } - switchLeft() { this.switch(Meta.MotionDirection.LEFT) } - switchRight() { this.switch(Meta.MotionDirection.RIGHT) } - switchUp() { this.switch(Meta.MotionDirection.UP) } - switchDown() { this.switch(Meta.MotionDirection.DOWN) } + switchLeft() { return this.switch(Meta.MotionDirection.LEFT) } + switchRight() { return this.switch(Meta.MotionDirection.RIGHT) } + switchUp() { return this.switch(Meta.MotionDirection.UP) } + switchDown() { return this.switch(Meta.MotionDirection.DOWN) } switch(direction) { let space = this; let index = space.selectedIndex(); @@ -747,6 +747,7 @@ class Space extends Array { let metaWindow = space.getWindow(index, row); ensureViewport(metaWindow, space); + return metaWindow; } positionOf(metaWindow) { @@ -1448,7 +1449,7 @@ class Spaces extends Map { let currentSpace = this.monitors.get(monitor); let i = display.get_monitor_neighbor_index(monitor.index, direction); if (i === -1) - return; + return null; let newMonitor = Main.layoutManager.monitors[i]; let space = this.monitors.get(newMonitor); @@ -1478,6 +1479,7 @@ class Spaces extends Map { } else { space.workspace.activate(global.get_current_time()); } + return focus; } switchWorkspace(wm, fromIndex, toIndex) { @@ -1662,6 +1664,7 @@ class Spaces extends Map { }); }); + return newSpace.selectedWindow; } animateToSpace(to, from, callback) { @@ -2824,11 +2827,11 @@ function barf(metaWindow) { } function selectPreviousSpace(mw, space) { - spaces.selectSpace(Meta.MotionDirection.DOWN); + return spaces.selectSpace(Meta.MotionDirection.DOWN); } function selectPreviousSpaceBackwards(mw, space) { - spaces.selectSpace(Meta.MotionDirection.UP); + return spaces.selectSpace(Meta.MotionDirection.UP); } function movePreviousSpace(mw, space) {