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) diff --git a/tiling.js b/tiling.js index f1cb8605..a0f37ca3 100644 --- a/tiling.js +++ b/tiling.js @@ -559,10 +559,20 @@ 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) { + space.removeWindow(metaWindow); + } + + metaWindow._workspace = this.workspace; if (row !== undefined && this[index]) { let column = this[index]; @@ -588,6 +598,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) { @@ -616,12 +627,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; @@ -762,6 +773,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); @@ -771,7 +786,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) ) { @@ -819,7 +833,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); @@ -1114,16 +1128,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); + } } } @@ -1420,6 +1438,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 @@ -1746,7 +1767,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) { @@ -2018,16 +2042,16 @@ 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. - 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(); @@ -2065,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 && @@ -2072,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; } @@ -2086,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); @@ -2122,20 +2149,39 @@ 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; + } connectSizeChanged(); showWindow(metaWindow); return; } else if (Scratch.isScratchWindow(metaWindow)){ + log(`make scratch stuck`); // And make sure scratch windows are stuck Scratch.makeScratch(metaWindow); 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); + log(`workspace`, space.actor, workspace.index()); if (!add_filter(metaWindow)) { + log('add floating', metaWindow.title); connectSizeChanged(); space.addFloating(metaWindow); showWindow(metaWindow); @@ -2144,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; @@ -2355,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(); @@ -2410,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(); @@ -2431,6 +2480,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(); /** @@ -2491,9 +2546,9 @@ 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.get_parent() && !metaWindow.unmapped) + if (!metaWindow.clone || (!metaWindow.clone.get_parent() && !metaWindow.unmapped)) return; // HACK: use opacity instead of hidden on new windows @@ -2939,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() +}