From 047ec64287a5fb49602ca3e620ea36916651fbae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Hedin=20Br=C3=B8nner?= Date: Sat, 19 Oct 2019 19:21:33 +0200 Subject: [PATCH 01/11] Space: record which space a window is tiled --- tiling.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tiling.js b/tiling.js index f1cb8605..fed45fc4 100644 --- a/tiling.js +++ b/tiling.js @@ -564,6 +564,8 @@ class Space extends Array { if (this.indexOf(metaWindow) !== -1) return false; + metaWindow._workspace = this.workspace; + if (row !== undefined && this[index]) { let column = this[index]; column.splice(row, 0, metaWindow); @@ -588,6 +590,7 @@ class Space extends Array { let index = this.indexOf(metaWindow); if (index === -1) return this.removeFloating(metaWindow); + metaWindow._workspace = null; let selected = this.selectedWindow; if (selected === metaWindow) { @@ -762,6 +765,10 @@ class Space extends Array { return -1; } + includes(metaWindow) { + return metaWindow._workspace === this.workspace; + } + rowOf(metaWindow) { let column = this[this.indexOf(metaWindow)]; return column.indexOf(metaWindow); @@ -1746,7 +1753,10 @@ class Spaces extends Map { }; spaceOfWindow(meta_window) { - return this.get(meta_window.get_workspace()); + let workspace = meta_window._workspace; + if (!workspace) + workspace = meta_window.get_workspace(); + return this.get(workspace); }; spaceOf(workspace) { From c5d651b9e310876b87394782fc8ac73ce2069a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Hedin=20Br=C3=B8nner?= Date: Sat, 19 Oct 2019 21:30:35 +0200 Subject: [PATCH 02/11] window-removed: Delay removal until next addWindow We need to guard against --- tiling.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tiling.js b/tiling.js index fed45fc4..eda71b13 100644 --- a/tiling.js +++ b/tiling.js @@ -564,6 +564,11 @@ class Space extends Array { if (this.indexOf(metaWindow) !== -1) return false; + let space = spaces.spaceOfWindow(metaWindow); + if (space.indexOf(metaWindow) !== -1 && space._populated) { + space.removeWindow(metaWindow); + } + metaWindow._workspace = this.workspace; if (row !== undefined && this[index]) { @@ -2033,11 +2038,11 @@ function remove_handler(workspace, meta_window) { // window has already received the `focus` signal at this point. // Not sure if we can check directly if _this_ window had focus when closed. - let space = spaces.spaceOf(workspace); - space.removeWindow(meta_window); - let actor = meta_window.get_compositor_private(); if (!actor) { + let space = spaces.spaceOf(workspace); + space.removeWindow(meta_window); + signals.disconnect(meta_window); if (meta_window.clone && meta_window.clone.mapped) { meta_window.clone.destroy(); From acee807f370230846c21b6d017980fa40cefdfb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Hedin=20Br=C3=B8nner?= Date: Sat, 19 Oct 2019 21:33:43 +0200 Subject: [PATCH 03/11] Space.init: use the old space for selectedWindow --- tiling.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tiling.js b/tiling.js index eda71b13..a4da0768 100644 --- a/tiling.js +++ b/tiling.js @@ -1126,16 +1126,20 @@ box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, .7); Scratch.makeScratch(meta_window); return; } - if(this.indexOf(meta_window) < 0 && add_filter(meta_window)) { + if(this.includes(meta_window) && add_filter(meta_window)) { this.addWindow(meta_window, this.length); } }) - let tabList = display.get_tab_list(Meta.TabList.NORMAL, workspace) - .filter(metaWindow => { return this.indexOf(metaWindow) !== -1; }); - if (tabList[0]) { - this.selectedWindow = tabList[0] - // ensureViewport(space.selectedWindow, space); + if (oldSpace) { + this.selectedWindow = oldSpace.selectedWindow; + } else { + let tabList = display.get_tab_list(Meta.TabList.NORMAL, workspace) + .filter(metaWindow => { return this.indexOf(metaWindow) !== -1; }); + if (tabList[0]) { + this.selectedWindow = tabList[0] + // ensureViewport(space.selectedWindow, space); + } } } From ab96a09889e21b66eca392efa2d86d289afef01d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Hedin=20Br=C3=B8nner?= Date: Sat, 19 Oct 2019 21:39:41 +0200 Subject: [PATCH 04/11] insertWindow: Do not handle tiled windows that are stuck More only-on-primary work. When a secondary monitor is to the left/right of primary, tiled windows become `stuck` when they're pushed into the secondary monitor. Eg. if `A` and `B` is tiled `B` will become `stuck` by entiring the secondary monitor: |-----primary-----|----secondary------| | |-------------| | |-------------| | | | | | | | | | | | | | | | | | A | | | B | | | | | | | | | | |_____________| | |_____________| | |_________________|___________________| Handle this edge case by not doing anything with such windows. --- tiling.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tiling.js b/tiling.js index a4da0768..223e7a84 100644 --- a/tiling.js +++ b/tiling.js @@ -2144,6 +2144,10 @@ function insertWindow(metaWindow, {existing}) { if (metaWindow.is_on_all_workspaces()) { // Only connect the necessary signals and show windows on shared // secondary monitors. + let space = spaces.spaceOfWindow(metaWindow); + if (space.includes(metaWindow)) { + return; + } connectSizeChanged(); showWindow(metaWindow); return; From 449d87c03aaee23976f49b146fdcdae754b18400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Hedin=20Br=C3=B8nner?= Date: Sat, 19 Oct 2019 22:11:59 +0200 Subject: [PATCH 05/11] showHandle: Avoid some warnings --- tiling.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiling.js b/tiling.js index 223e7a84..1b32c626 100644 --- a/tiling.js +++ b/tiling.js @@ -2516,7 +2516,7 @@ function showHandler(actor) { let metaWindow = actor.meta_window; let onActive = metaWindow.get_workspace() === workspaceManager.get_active_workspace(); - if (!metaWindow.clone.get_parent() && !metaWindow.unmapped) + if (!metaWindow.clone || (!metaWindow.clone.get_parent() && !metaWindow.unmapped)) return; // HACK: use opacity instead of hidden on new windows From c40fc9351f54fe3124ca555b99a480beb06555c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Hedin=20Br=C3=B8nner?= Date: Sat, 19 Oct 2019 22:25:09 +0200 Subject: [PATCH 06/11] workspacesChanged: Remove tiled windows on workspace removal --- tiling.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tiling.js b/tiling.js index 1b32c626..c619ee54 100644 --- a/tiling.js +++ b/tiling.js @@ -1436,6 +1436,9 @@ class Spaces extends Map { for (let [workspace, space] of this) { if (workspaces[space.workspace] !== true) { debug('workspace removed', space.workspace); + space.getWindows().forEach(mw => { + space.removeWindow(mw); + }); this.removeSpace(space); // Maps in javascript (and thus Spaces) remember insertion order From 1df69c1ec962b0c2f28123191fa96c233d77296b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Hedin=20Br=C3=B8nner?= Date: Sun, 20 Oct 2019 17:33:54 +0200 Subject: [PATCH 07/11] moveDone: complete moves in overview --- tiling.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tiling.js b/tiling.js index c619ee54..99b96d58 100644 --- a/tiling.js +++ b/tiling.js @@ -624,12 +624,12 @@ class Space extends Array { if (actor) actor.remove_clip(); - this.layout(); if (selected) { - ensureViewport(selected, this); + this.selectedWindow = selected; } else { this.selectedWindow = null; } + this.layout(); this.emit('window-removed', metaWindow, index, row); return true; @@ -783,7 +783,6 @@ class Space extends Array { if (this.cloneContainer.x !== this.targetX || this.actor.y !== 0 || Navigator.navigating || inPreview || - Main.overview.visible || // Only block on grab if we haven't detached the window yet (inGrab && !inGrab.workspace) ) { @@ -831,7 +830,7 @@ class Space extends Array { const ch = Math.max(0, monitor.y + monitor.height - b.y - y); actor.set_clip(x, y, cw, ch); - showWindow(w); + !Main.overview.visible && showWindow(w); }); this._floating.forEach(showWindow); From 6434bbd682ca841639b065c02e31b111b00a1b6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Hedin=20Br=C3=B8nner?= Date: Sun, 20 Oct 2019 17:34:42 +0200 Subject: [PATCH 08/11] insertWindow: insert in correct workspace --- tiling.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tiling.js b/tiling.js index 99b96d58..dae06077 100644 --- a/tiling.js +++ b/tiling.js @@ -2159,7 +2159,17 @@ function insertWindow(metaWindow, {existing}) { return; } - let space = spaces.spaceOfWindow(metaWindow); + // We now handle windows that are on only one workspace + + /* + The window might have moved workspaces, while still being tiled on an old + space. + + Since we delay removing tiled windows until it's added to another space we + need to look at what _workspace_ the window is on, not which _space_. + */ + let workspace = metaWindow.get_workspace(); + let space = spaces.spaceOf(workspace); if (!add_filter(metaWindow)) { connectSizeChanged(); space.addFloating(metaWindow); From d32767fc562461471644cf775e26f8846aeecab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Hedin=20Br=C3=B8nner?= Date: Sun, 20 Oct 2019 19:12:37 +0200 Subject: [PATCH 09/11] scratch: remove tiled windows manually before setting stuck --- scratch.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scratch.js b/scratch.js index 3568f873..d9c52de8 100644 --- a/scratch.js +++ b/scratch.js @@ -68,6 +68,8 @@ function makeScratch(metaWindow) { metaWindow[float] = true; metaWindow.make_above(); + let space = Tiling.spaces.spaceOfWindow(metaWindow); + space.removeWindow(metaWindow); metaWindow.stick(); // NB! Removes the window from the tiling (synchronously) if (!metaWindow.minimized) From fe3bc59be67e1c6dd88e9b163b0ce305f35067a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Hedin=20Br=C3=B8nner?= Date: Mon, 21 Oct 2019 09:10:45 +0200 Subject: [PATCH 10/11] focus: Do not act on stuck windows when switching to an empty workspace --- tiling.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tiling.js b/tiling.js index dae06077..d1266721 100644 --- a/tiling.js +++ b/tiling.js @@ -2466,6 +2466,12 @@ function focus_handler(metaWindow, user_data) { } let space = spaces.spaceOfWindow(metaWindow); + // Do not act on stuck windows when switching to an empty workspace + if (metaWindow.on_all_workspaces && space !== spaces.selectedSpace && + space.indexOf(metaWindow) !== -1) + { + return; + } space.monitor.clickOverlay.show(); /** From 2d65771481919464c22a269f37f4cad927d73db0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Hedin=20Br=C3=B8nner?= Date: Mon, 21 Oct 2019 09:11:18 +0200 Subject: [PATCH 11/11] debug --- tiling.js | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/tiling.js b/tiling.js index d1266721..a0f37ca3 100644 --- a/tiling.js +++ b/tiling.js @@ -559,10 +559,13 @@ class Space extends Array { } addWindow(metaWindow, index, row) { + log(`add window`, metaWindow.title); if (!this.selectedWindow) this.selectedWindow = metaWindow; - if (this.indexOf(metaWindow) !== -1) + if (this.indexOf(metaWindow) !== -1) { + log(`already added window`, metaWindow.title); return false; + } let space = spaces.spaceOfWindow(metaWindow); if (space.indexOf(metaWindow) !== -1 && space._populated) { @@ -2039,7 +2042,7 @@ function add_filter(meta_window) { Handle windows leaving workspaces. */ function remove_handler(workspace, meta_window) { - debug("window-removed", meta_window, meta_window.title, workspace.index()); + log("window-removed", meta_window, meta_window.title, workspace.index()); // Note: If `meta_window` was closed and had focus at the time, the next // window has already received the `focus` signal at this point. // Not sure if we can check directly if _this_ window had focus when closed. @@ -2086,6 +2089,7 @@ function add_handler(ws, metaWindow) { created to ensure that the WindowActor exists. */ function insertWindow(metaWindow, {existing}) { + log("insert-window", metaWindow.title, metaWindow.on_all_workspaces, existing); // Add newly created windows to the space being previewed if (!existing && @@ -2093,6 +2097,7 @@ function insertWindow(metaWindow, {existing}) { metaWindow.get_workspace() !== spaces.selectedSpace.workspace) { metaWindow.redirected = true; metaWindow.change_workspace(spaces.selectedSpace.workspace); + log(`redirect`, metaWindow.title); return; } @@ -2107,6 +2112,7 @@ function insertWindow(metaWindow, {existing}) { }; if (!existing) { + // Note: Can't trust global.display.focus_window to determine currently focused window. // The mru is more flexible. (global.display.focus_window does not always agree with mru[0]) let mru = display.get_tab_list(Meta.TabList.NORMAL_ALL, null); @@ -2143,9 +2149,11 @@ function insertWindow(metaWindow, {existing}) { } } - if (metaWindow.is_on_all_workspaces()) { + // Windows on all workspaces are a bit wonky + if (metaWindow.on_all_workspaces) { // Only connect the necessary signals and show windows on shared // secondary monitors. + log(metaWindow.title, 'on all', metaWindow.on_all_workspaces); let space = spaces.spaceOfWindow(metaWindow); if (space.includes(metaWindow)) { return; @@ -2154,6 +2162,7 @@ function insertWindow(metaWindow, {existing}) { showWindow(metaWindow); return; } else if (Scratch.isScratchWindow(metaWindow)){ + log(`make scratch stuck`); // And make sure scratch windows are stuck Scratch.makeScratch(metaWindow); return; @@ -2170,7 +2179,9 @@ function insertWindow(metaWindow, {existing}) { */ let workspace = metaWindow.get_workspace(); let space = spaces.spaceOf(workspace); + log(`workspace`, space.actor, workspace.index()); if (!add_filter(metaWindow)) { + log('add floating', metaWindow.title); connectSizeChanged(); space.addFloating(metaWindow); showWindow(metaWindow); @@ -2179,8 +2190,10 @@ function insertWindow(metaWindow, {existing}) { return; } - if (space.indexOf(metaWindow) !== -1) + if (space.indexOf(metaWindow) !== -1) { + log(`window already tiled on`, space.actor); return; + } let clone = metaWindow.clone; let ok, x, y; @@ -2390,6 +2403,7 @@ function grabBegin(metaWindow, type) { return; let space = spaces.spaceOfWindow(metaWindow); inGrab = {window: metaWindow}; + metaWindow.raise(); if (!space || space.indexOf(metaWindow) === -1) return; space.startAnimate(); @@ -2445,7 +2459,7 @@ function getGrab(space, anchor) { // `MetaWindow::focus` handling function focus_handler(metaWindow, user_data) { - debug("focus:", metaWindow.title, utils.framestr(metaWindow.get_frame_rect())); + log("focus:", metaWindow.title, utils.framestr(metaWindow.get_frame_rect())); if (metaWindow.fullscreen) { TopBar.hide(); @@ -2532,7 +2546,7 @@ var minimizeWrapper = utils.dynamic_function_ref('minimizeHandler', Me); */ function showHandler(actor) { let metaWindow = actor.meta_window; - let onActive = metaWindow.get_workspace() === workspaceManager.get_active_workspace(); + let onActive = spaces.spaceOfWindow(metaWindow).workspace === workspaceManager.get_active_workspace(); if (!metaWindow.clone || (!metaWindow.clone.get_parent() && !metaWindow.unmapped)) return; @@ -2980,3 +2994,11 @@ function cycleWorkspaceSettings(dir=1) { function defwinprop(...args) { return Settings.defwinprop(...args); } + + +function repl() { + metaWindow.get_workspace().index() + spaces.spaceOfWindow() + metaWindow._workspace.index() + metaWindow._workspace.index() +}