From f2eaa31ca55792ae8e7b071f1929e0abb6abff33 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Fri, 1 Dec 2023 21:28:29 +1100 Subject: [PATCH 01/43] FIX: run space.layout when exiting fullscreen. --- tiling.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tiling.js b/tiling.js index ffe22f631..5ac3f0030 100644 --- a/tiling.js +++ b/tiling.js @@ -378,6 +378,12 @@ export class Space extends Array { // update space elements when in/out of fullscreen this.signals.connect(global.display, 'in-fullscreen-changed', () => { this.setSpaceTopbarElementsVisible(true); + const window = display?.focus_window; + if (window) { + if (!window.fullscreen) { + this.layout(false); + } + } }); this.signals.connect(interfaceSettings, "changed::color-scheme", this.updateBackground.bind(this)); From 4e201ccbd7d841293e3a638670952a7e5bd2943d Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Fri, 1 Dec 2023 21:44:47 +1100 Subject: [PATCH 02/43] FIX: for new fullscreen windows, unmake fullscreen for paperwm tiling, then fullscreen on show. --- tiling.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tiling.js b/tiling.js index 5ac3f0030..a138629b7 100644 --- a/tiling.js +++ b/tiling.js @@ -377,13 +377,15 @@ export class Space extends Array { // update space elements when in/out of fullscreen this.signals.connect(global.display, 'in-fullscreen-changed', () => { - this.setSpaceTopbarElementsVisible(true); - const window = display?.focus_window; - if (window) { - if (!window.fullscreen) { - this.layout(false); + const metaWindow = display?.focus_window; + if (metaWindow) { + if (!metaWindow.fullscreen) { + this.layout(); + this.ensureViewport(metaWindow, this); } } + + this.setSpaceTopbarElementsVisible(true); }); this.signals.connect(interfaceSettings, "changed::color-scheme", this.updateBackground.bind(this)); @@ -3313,6 +3315,14 @@ export function insertWindow(metaWindow, { existing }) { activateWindowAfterRendered(actor, metaWindow); return; } + + // address inserting windows that are already fullscreen + if (metaWindow.fullscreen) { + metaWindow.unmake_fullscreen(); + callbackOnActorShow(actor, () => { + metaWindow.make_fullscreen(); + }); + } } if (metaWindow.is_on_all_workspaces()) { From 7f4048c9c59e12290ff438d91722c95ddf34df03 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sun, 3 Dec 2023 22:12:05 +1100 Subject: [PATCH 03/43] Small change to the approach here - unmake_fullscreen then set fullscreen during layout cycle. --- tiling.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tiling.js b/tiling.js index a138629b7..9d3be26dc 100644 --- a/tiling.js +++ b/tiling.js @@ -380,7 +380,7 @@ export class Space extends Array { const metaWindow = display?.focus_window; if (metaWindow) { if (!metaWindow.fullscreen) { - this.layout(); + this.layout(false); this.ensureViewport(metaWindow, this); } } @@ -630,6 +630,13 @@ export class Space extends Array { let y0 = workArea.y; let fixPointAttempCount = 0; + this.getWindows() + .filter(w => w.fullscreenOnLayout) + .forEach(w => { + delete w.fullscreenOnLayout; + w.make_fullscreen(); + }); + for (let i = 0; i < this.length; i++) { let column = this[i]; // Actorless windows are trouble. Layout could conceivable run while a window is dying or being born. @@ -3318,10 +3325,8 @@ export function insertWindow(metaWindow, { existing }) { // address inserting windows that are already fullscreen if (metaWindow.fullscreen) { + metaWindow.fullscreenOnLayout = true; metaWindow.unmake_fullscreen(); - callbackOnActorShow(actor, () => { - metaWindow.make_fullscreen(); - }); } } From 0187cbb8060ce3d16fbea97d7ace5df31db4be9f Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sun, 3 Dec 2023 22:47:46 +1100 Subject: [PATCH 04/43] Small cleanup. --- tiling.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tiling.js b/tiling.js index 9d3be26dc..5cd105617 100644 --- a/tiling.js +++ b/tiling.js @@ -377,6 +377,7 @@ export class Space extends Array { // update space elements when in/out of fullscreen this.signals.connect(global.display, 'in-fullscreen-changed', () => { + this.setSpaceTopbarElementsVisible(true); const metaWindow = display?.focus_window; if (metaWindow) { if (!metaWindow.fullscreen) { @@ -384,8 +385,6 @@ export class Space extends Array { this.ensureViewport(metaWindow, this); } } - - this.setSpaceTopbarElementsVisible(true); }); this.signals.connect(interfaceSettings, "changed::color-scheme", this.updateBackground.bind(this)); @@ -929,7 +928,7 @@ export class Space extends Array { * Returns true iff this space has a currently fullscreened window. */ hasFullScreenWindow() { - return this.getWindows().some(el => el.fullscreen); + return this.getWindows().some(w => w.fullscreen); } swap(direction, metaWindow) { From b3c2229ab353484b8849bda1c5ca373ae36ef8df Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sun, 10 Dec 2023 17:10:59 +1100 Subject: [PATCH 05/43] Delay removing `fullscreenOnLayout` until unfullscreen application. --- tiling.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tiling.js b/tiling.js index 5cd105617..e3acab104 100644 --- a/tiling.js +++ b/tiling.js @@ -380,7 +380,8 @@ export class Space extends Array { this.setSpaceTopbarElementsVisible(true); const metaWindow = display?.focus_window; if (metaWindow) { - if (!metaWindow.fullscreen) { + if (metaWindow.fullscreenOnLayout) { + delete metaWindow.fullscreenOnLayout; this.layout(false); this.ensureViewport(metaWindow, this); } @@ -632,7 +633,6 @@ export class Space extends Array { this.getWindows() .filter(w => w.fullscreenOnLayout) .forEach(w => { - delete w.fullscreenOnLayout; w.make_fullscreen(); }); From 8d71aaf57bb03f3294f9fc53390564569f667741 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Mon, 25 Dec 2023 19:21:10 +1100 Subject: [PATCH 06/43] Moved to using layout 'emit' signal to remove `fullscreenOnLayout`. --- tiling.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tiling.js b/tiling.js index e3acab104..356f15173 100644 --- a/tiling.js +++ b/tiling.js @@ -378,14 +378,15 @@ export class Space extends Array { // update space elements when in/out of fullscreen this.signals.connect(global.display, 'in-fullscreen-changed', () => { this.setSpaceTopbarElementsVisible(true); - const metaWindow = display?.focus_window; - if (metaWindow) { - if (metaWindow.fullscreenOnLayout) { - delete metaWindow.fullscreenOnLayout; - this.layout(false); - this.ensureViewport(metaWindow, this); + }); + + // after layout is complete, remove any residual fullscreenOnLayout + this.signals.connect(this, "layout", () => { + this.getWindows().forEach(w => { + if (w.fullscreenOnLayout) { + delete w.fullscreenOnLayout; } - } + }); }); this.signals.connect(interfaceSettings, "changed::color-scheme", this.updateBackground.bind(this)); @@ -630,6 +631,7 @@ export class Space extends Array { let y0 = workArea.y; let fixPointAttempCount = 0; + // apply fullscreen if windows has fullscreenOnLayout property set this.getWindows() .filter(w => w.fullscreenOnLayout) .forEach(w => { From 7e7414301bdb9b49ab63f01762c016653cb9fcee Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Wed, 27 Dec 2023 08:47:57 +1100 Subject: [PATCH 07/43] WIP: debugging why resizeHandler not called when unfullscreening kodi. --- keybindings.js | 6 ++++-- tiling.js | 28 +++++++++++++++++----------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/keybindings.js b/keybindings.js index c6dc7f621..c8bd851ae 100644 --- a/keybindings.js +++ b/keybindings.js @@ -252,10 +252,12 @@ export function setupActions(settings) { registerPaperAction('paper-toggle-fullscreen', metaWindow => { - if (metaWindow.fullscreen) + if (metaWindow.fullscreen) { metaWindow.unmake_fullscreen(); - else + } + else { metaWindow.make_fullscreen(); + } }, Meta.KeyBindingFlags.PER_WINDOW); } diff --git a/tiling.js b/tiling.js index b4e1c5466..9666788b7 100644 --- a/tiling.js +++ b/tiling.js @@ -380,15 +380,6 @@ export class Space extends Array { this.setSpaceTopbarElementsVisible(true); }); - // after layout is complete, remove any residual fullscreenOnLayout - this.signals.connect(this, "layout", () => { - this.getWindows().forEach(w => { - if (w.fullscreenOnLayout) { - delete w.fullscreenOnLayout; - } - }); - }); - this.signals.connect(interfaceSettings, "changed::color-scheme", this.updateBackground.bind(this)); this.signals.connect(gsettings, 'changed::default-background', this.updateBackground.bind(this)); this.signals.connect(gsettings, 'changed::use-default-background', this.updateBackground.bind(this)); @@ -714,6 +705,17 @@ export class Space extends Array { this.moveDone(); } + Utils.later_add(Meta.LaterType.IDLE, () => { + console.log(`with idle clear fullscreenOnLayout: ${global.get_current_time()}`); + this.getWindows().forEach(w => { + if (w.fullscreenOnLayout) { + resizeHandler(w); + delete w.fullscreenOnLayout; + } + }); + }); + + console.log(`emit layout: ${global.get_current_time()}`); this.emit('layout', this); } @@ -3054,6 +3056,8 @@ export function destroyHandler(actor) { } export function resizeHandler(metaWindow) { + console.log(`resize handler called on ${metaWindow?.title}`); + // if navigator is showing, reset/refresh it after a window has resized if (Navigator.navigating) { Navigator.getNavigator().minimaps.forEach(m => typeof m !== 'number' && m.reset()); @@ -3279,6 +3283,7 @@ export function insertWindow(metaWindow, { existing }) { const space = spaces.spaceOfWindow(metaWindow); const connectSizeChanged = tiled => { + console.log(`resizehandler added ${metaWindow?.title}, tiled: ${tiled}`); if (tiled) { animateWindow(metaWindow); } @@ -3355,8 +3360,9 @@ export function insertWindow(metaWindow, { existing }) { return; } - if (space.indexOf(metaWindow) !== -1) + if (space.indexOf(metaWindow) !== -1) { return; + } let clone = metaWindow.clone; let ok, x, y; @@ -3594,7 +3600,7 @@ export function updateSelection(space, metaWindow) { // ensure window is properly activated (if not activated) if (space === spaces.activeSpace) { - if (metaWindow !== display.focus_windoww) { + if (metaWindow !== display.focus_window) { Main.activateWindow(metaWindow); } } From e8f2b104244f83df7bb992e60f138f95b04947cc Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Thu, 28 Dec 2023 07:36:15 +1100 Subject: [PATCH 08/43] EXPERIMENTAL: save widths from prior to paperwm fullscreens. --- tiling.js | 97 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 75 insertions(+), 22 deletions(-) diff --git a/tiling.js b/tiling.js index 9666788b7..6f498afa8 100644 --- a/tiling.js +++ b/tiling.js @@ -509,6 +509,10 @@ export class Space extends Array { let resizable = !mw.fullscreen && mw.get_maximized() !== Meta.MaximizeFlags.BOTH; + if (mw._fullscreen_width) { + targetWidth = mw._fullscreen_width; + } + if (mw.preferredWidth) { let prop = mw.preferredWidth; if (prop.value <= 0) { @@ -590,8 +594,9 @@ export class Space extends Array { return; // option properties - let ensure = options?.ensure ?? true; - let allocators = options?.customAllocators; + const ensure = options?.ensure ?? true; + const allocators = options?.customAllocators; + const callback = options?.callback; this._inLayout = true; this.startAnimate(); @@ -709,24 +714,34 @@ export class Space extends Array { console.log(`with idle clear fullscreenOnLayout: ${global.get_current_time()}`); this.getWindows().forEach(w => { if (w.fullscreenOnLayout) { - resizeHandler(w); delete w.fullscreenOnLayout; } }); }); console.log(`emit layout: ${global.get_current_time()}`); + if (callback) { + callback(); + } this.emit('layout', this); } - queueLayout(animate = true) { + queueLayout(animate = true, options = {}) { if (this._layoutQueued) return; + const callback = options?.callback; + this._layoutQueued = true; Utils.later_add(Meta.LaterType.RESIZE, () => { this._layoutQueued = false; - this.layout(animate); + + if (callback) { + this.layout(animate, { callback }); + } + else { + this.layout(); + } }); } @@ -1910,6 +1925,7 @@ export const Spaces = class Spaces extends Map { // Fixup allocations on reload allocateClone(w); this.signals.connect(w, 'size-changed', resizeHandler); + this.signals.connect(w, 'position-changed', positionChangeHandler); }); this._initDone = true; @@ -3011,7 +3027,14 @@ export function registerWindow(metaWindow) { }); signals.connect(metaWindow, 'size-changed', allocateClone); // Note: runs before gnome-shell's minimize handling code - signals.connect(metaWindow, 'notify::fullscreen', Topbar.fixTopBar); + signals.connect(metaWindow, 'notify::fullscreen', () => { + /** + * Run resizeHandler here since relying only on window resizing + * to pick-up fullscreen change is trouble (e.g. windows that start as fullscreen). + */ + resizeHandler(metaWindow); + Topbar.fixTopBar(); + }); signals.connect(metaWindow, 'notify::minimized', metaWindow => { minimizeHandler(metaWindow); }); @@ -3055,8 +3078,19 @@ export function destroyHandler(actor) { signals.disconnect(actor); } +export function positionChangeHandler(metaWindow) { + // don't update saved position if fullscreen + if (metaWindow.fullscreen || metaWindow?._fullscreen_lock) { + return; + } + + const f = metaWindow.get_frame_rect(); + metaWindow._fullscreen_x = f.x; + console.log(`_fullscreen_x changed: ${f.x}`); +} + export function resizeHandler(metaWindow) { - console.log(`resize handler called on ${metaWindow?.title}`); + console.error(new Error(`resize handler called on ${metaWindow?.title}`)); // if navigator is showing, reset/refresh it after a window has resized if (Navigator.navigating) { @@ -3067,10 +3101,6 @@ export function resizeHandler(metaWindow) { return; const f = metaWindow.get_frame_rect(); - let needLayout = false; - if (metaWindow._targetWidth !== f.width || metaWindow._targetHeight !== f.height) { - needLayout = true; - } metaWindow._targetWidth = null; metaWindow._targetHeight = null; @@ -3079,28 +3109,48 @@ export function resizeHandler(metaWindow) { return; const selected = metaWindow === space.selectedWindow; + let addCallback = false; let animate = true; let x; // if window is fullscreened, then don't animate background space.container animation etc. - if (metaWindow?.fullscreen) { + if (metaWindow.fullscreen) { + metaWindow._fullscreen_lock = true; + addCallback = true; animate = false; x = 0; - } else { - x = metaWindow.get_frame_rect().x - space.monitor.x; + } + else { + x = metaWindow._fullscreen_x ?? f.x - space.monitor.x; + x = Math.max(x, Settings.prefs.horizontal_margin); + + // if pwm fullscreen previously + if (metaWindow._fullscreen_lock) { + addCallback = true; + delete metaWindow._fullscreen_lock; + } + else { + console.error(new Error('_fullscreen_width saved')); + metaWindow._fullscreen_width = f.width; + console.log(`save _fullscreen_width ${metaWindow?.title}: ${metaWindow?._fullscreen_width}`); + } } - if (!space._inLayout && needLayout) { + if (!space._inLayout) { // Restore window position when eg. exiting fullscreen - if (!Navigator.navigating && selected) { - move_to(space, metaWindow, { - x, - animate, - }); + let callback = () => {}; + if (addCallback && !Navigator.navigating && selected) { + callback = () => { + console.log(`callback! x:${x}`); + move_to(space, metaWindow, { + x, + animate, + }); + }; } // Resizing from within a size-changed signal is troube (#73). Queue instead. - space.queueLayout(animate); + space.queueLayout(animate, { callback }); } } @@ -3287,7 +3337,10 @@ export function insertWindow(metaWindow, { existing }) { if (tiled) { animateWindow(metaWindow); } - metaWindow.unmapped && signals.connect(metaWindow, 'size-changed', resizeHandler); + if (metaWindow.unmapped) { + signals.connect(metaWindow, 'size-changed', resizeHandler); + signals.connect(metaWindow, 'position-changed', positionChangeHandler); + } delete metaWindow.unmapped; }; From 27fd5dd51f9d301b79f98bb81e6d6cdc108b9dcf Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Thu, 28 Dec 2023 11:26:15 +1100 Subject: [PATCH 09/43] Cleanup and remove debug/log writes. --- tiling.js | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/tiling.js b/tiling.js index 6f498afa8..1838412ed 100644 --- a/tiling.js +++ b/tiling.js @@ -711,7 +711,6 @@ export class Space extends Array { } Utils.later_add(Meta.LaterType.IDLE, () => { - console.log(`with idle clear fullscreenOnLayout: ${global.get_current_time()}`); this.getWindows().forEach(w => { if (w.fullscreenOnLayout) { delete w.fullscreenOnLayout; @@ -719,10 +718,7 @@ export class Space extends Array { }); }); - console.log(`emit layout: ${global.get_current_time()}`); - if (callback) { - callback(); - } + callback && callback(); this.emit('layout', this); } @@ -3086,12 +3082,9 @@ export function positionChangeHandler(metaWindow) { const f = metaWindow.get_frame_rect(); metaWindow._fullscreen_x = f.x; - console.log(`_fullscreen_x changed: ${f.x}`); } export function resizeHandler(metaWindow) { - console.error(new Error(`resize handler called on ${metaWindow?.title}`)); - // if navigator is showing, reset/refresh it after a window has resized if (Navigator.navigating) { Navigator.getNavigator().minimaps.forEach(m => typeof m !== 'number' && m.reset()); @@ -3130,9 +3123,8 @@ export function resizeHandler(metaWindow) { delete metaWindow._fullscreen_lock; } else { - console.error(new Error('_fullscreen_width saved')); + // save width for later exit-fullscreen restoring metaWindow._fullscreen_width = f.width; - console.log(`save _fullscreen_width ${metaWindow?.title}: ${metaWindow?._fullscreen_width}`); } } @@ -3141,7 +3133,6 @@ export function resizeHandler(metaWindow) { let callback = () => {}; if (addCallback && !Navigator.navigating && selected) { callback = () => { - console.log(`callback! x:${x}`); move_to(space, metaWindow, { x, animate, @@ -3333,7 +3324,6 @@ export function insertWindow(metaWindow, { existing }) { const space = spaces.spaceOfWindow(metaWindow); const connectSizeChanged = tiled => { - console.log(`resizehandler added ${metaWindow?.title}, tiled: ${tiled}`); if (tiled) { animateWindow(metaWindow); } From 8fd5ccd2efa22bc491787d51301a5e42dc11ebfb Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Thu, 28 Dec 2023 12:02:49 +1100 Subject: [PATCH 10/43] Handle restoring of non-tiled windows size and position. --- tiling.js | 57 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/tiling.js b/tiling.js index 1838412ed..da85ed438 100644 --- a/tiling.js +++ b/tiling.js @@ -509,8 +509,8 @@ export class Space extends Array { let resizable = !mw.fullscreen && mw.get_maximized() !== Meta.MaximizeFlags.BOTH; - if (mw._fullscreen_width) { - targetWidth = mw._fullscreen_width; + if (mw._fullscreen_frame) { + targetWidth = mw._fullscreen_frame.width; } if (mw.preferredWidth) { @@ -3080,8 +3080,7 @@ export function positionChangeHandler(metaWindow) { return; } - const f = metaWindow.get_frame_rect(); - metaWindow._fullscreen_x = f.x; + saveFullscreenFrame(metaWindow); } export function resizeHandler(metaWindow) { @@ -3098,8 +3097,10 @@ export function resizeHandler(metaWindow) { metaWindow._targetHeight = null; const space = spaces.spaceOfWindow(metaWindow); - if (space.indexOf(metaWindow) === -1) + if (space.indexOf(metaWindow) === -1) { + nonTiledSizeHandler(metaWindow); return; + } const selected = metaWindow === space.selectedWindow; let addCallback = false; @@ -3114,17 +3115,17 @@ export function resizeHandler(metaWindow) { x = 0; } else { - x = metaWindow._fullscreen_x ?? f.x - space.monitor.x; + x = metaWindow?._fullscreen_frame?.x ?? f.x - space.monitor.x; x = Math.max(x, Settings.prefs.horizontal_margin); // if pwm fullscreen previously if (metaWindow._fullscreen_lock) { - addCallback = true; delete metaWindow._fullscreen_lock; + addCallback = true; } else { // save width for later exit-fullscreen restoring - metaWindow._fullscreen_width = f.width; + saveFullscreenFrame(metaWindow); } } @@ -3145,6 +3146,46 @@ export function resizeHandler(metaWindow) { } } +/** + * ResizeHandler for non-tiled windows + * @param {*} metaWindow + */ +export function nonTiledSizeHandler(metaWindow) { + // if window is fullscreen ==> set lock + if (metaWindow.fullscreen) { + metaWindow._fullscreen_lock = true; + return; + } + + // if pwm fullscreen previously + if (metaWindow._fullscreen_lock) { + delete metaWindow._fullscreen_lock; + let fsf = metaWindow._fullscreen_frame; + if (fsf) { + metaWindow.move_resize_frame(true, fsf.x, fsf.y, fsf.width, fsf.height); + delete metaWindow._fullscreen_frame; + } + } + else { + saveFullscreenFrame(metaWindow); + } +} + +/** + * Saves a metaWindow's frame x, y ,width, and height for restoring + * after exiting fullscreen mode. + * @param {MetaWindow} metaWindow + */ +export function saveFullscreenFrame(metaWindow) { + const f = metaWindow.get_frame_rect(); + metaWindow._fullscreen_frame = { + x: f.x, + y: f.y, + width: f.width, + height: f.height, + }; +} + /** * Saves current state for controlled restarts of PaperWM. */ From 0ac4bc6bc6e1301792b313f2c0e513423f692ff8 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Thu, 28 Dec 2023 12:35:18 +1100 Subject: [PATCH 11/43] FIX: activiate a scratched window when it is scratched. --- scratch.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/scratch.js b/scratch.js index 547eace31..b50016263 100644 --- a/scratch.js +++ b/scratch.js @@ -112,8 +112,16 @@ export function makeScratch(metaWindow) { if (!metaWindow.minimized) { metaWindow.move_resize_frame(true, f.x, f.y, targetFrame.width, targetFrame.height); - easeScratch(metaWindow, targetFrame.x, targetFrame.y, - { onComplete: () => delete metaWindow[scratchFrame] }); + easeScratch( + metaWindow, + targetFrame.x, + targetFrame.y, + { + onComplete: () => { + delete metaWindow[scratchFrame]; + Main.activateWindow(metaWindow); + }, + }); } else { // Can't restore the scratch geometry immediately since it distort the minimize animation // ASSUMPTION: minimize animation is not disabled and not already done From f3779c7fdb6e90f3c6c321244708c138bb9373f8 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Thu, 28 Dec 2023 13:37:23 +1100 Subject: [PATCH 12/43] Track frame width to restore separately (for tiled/non-tiled). --- tiling.js | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/tiling.js b/tiling.js index da85ed438..35b961c4f 100644 --- a/tiling.js +++ b/tiling.js @@ -509,8 +509,8 @@ export class Space extends Array { let resizable = !mw.fullscreen && mw.get_maximized() !== Meta.MaximizeFlags.BOTH; - if (mw._fullscreen_frame) { - targetWidth = mw._fullscreen_frame.width; + if (mw._fullscreen_frame?.tiledWidth) { + targetWidth = mw._fullscreen_frame.tiledWidth; } if (mw.preferredWidth) { @@ -3125,7 +3125,7 @@ export function resizeHandler(metaWindow) { } else { // save width for later exit-fullscreen restoring - saveFullscreenFrame(metaWindow); + saveFullscreenFrame(metaWindow, true); } } @@ -3176,14 +3176,19 @@ export function nonTiledSizeHandler(metaWindow) { * after exiting fullscreen mode. * @param {MetaWindow} metaWindow */ -export function saveFullscreenFrame(metaWindow) { +export function saveFullscreenFrame(metaWindow, tiled) { const f = metaWindow.get_frame_rect(); - metaWindow._fullscreen_frame = { - x: f.x, - y: f.y, - width: f.width, - height: f.height, - }; + const fsf = metaWindow._fullscreen_frame ?? {}; + metaWindow._fullscreen_frame = fsf; + fsf.x = f.x; + fsf.y = f.y; + fsf.width = f.width; + fsf.height = f.height; + + // if from tiled, save tiledWidth for tiling width tracking + if (tiled) { + fsf.tiledWidth = f.width; + } } /** From 46543edd0ff79b3e34a4ae8f26e80cae55889694 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Thu, 28 Dec 2023 21:06:20 +1100 Subject: [PATCH 13/43] Center window in space if it's just one (was previously on insertion, but moved to `layout`). --- tiling.js | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/tiling.js b/tiling.js index 35b961c4f..78ec971c3 100644 --- a/tiling.js +++ b/tiling.js @@ -596,6 +596,7 @@ export class Space extends Array { // option properties const ensure = options?.ensure ?? true; const allocators = options?.customAllocators; + const centerIfOne = options?.centerIfOne ?? true; const callback = options?.callback; this._inLayout = true; @@ -718,6 +719,12 @@ export class Space extends Array { }); }); + // if only one window on space, then centre it + if (centerIfOne && this.getWindows().length === 1) { + const mw = this.getWindows()[0]; + centerWindowHorizontally(mw); + } + callback && callback(); this.emit('layout', this); } @@ -3477,13 +3484,6 @@ export function insertWindow(metaWindow, { existing }) { // run a simple layout in pre-prepare layout space.layout(false); - // if only one window on space, then centre it - const centre = () => { - if (space.getWindows().length === 1) { - centerWindowHorizontally(metaWindow); - } - }; - /** * If window is new, then setup and ensure is in view * after actor is shown on stage. @@ -3504,8 +3504,6 @@ export function insertWindow(metaWindow, { existing }) { Main.activateWindow(metaWindow); ensureViewport(space.selectedWindow, space); - - centre(); }); return; @@ -3520,8 +3518,6 @@ export function insertWindow(metaWindow, { existing }) { } else { ensureViewport(space.selectedWindow, space); } - - centre(); } /** @@ -4249,16 +4245,6 @@ export function centerWindowHorizontally(metaWindow) { const workArea = space.workArea(); const targetX = workArea.x + Math.round((workArea.width - frame.width) / 2); - const dx = targetX - (metaWindow.clone.targetX + space.targetX); - - let [pointerX, pointerY, mask] = global.get_pointer(); - let relPointerX = pointerX - monitor.x - space.cloneContainer.x; - let relPointerY = pointerY - monitor.y - space.cloneContainer.y; - /* don't know why we would want to warp pointer on centering window... disabling - if (Utils.isPointInsideActor(metaWindow.clone, relPointerX, relPointerY)) { - Utils.warpPointer(pointerX + dx, pointerY); - } - */ if (space.indexOf(metaWindow) === -1) { metaWindow.move_frame(true, targetX + monitor.x, frame.y); } else { From 6218a4952150b9c3a85f2fed97d49e8f8042f8df Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Thu, 28 Dec 2023 22:55:54 +1100 Subject: [PATCH 14/43] Set queueLayout options as passthrough. --- tiling.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/tiling.js b/tiling.js index 78ec971c3..29d0d0d0e 100644 --- a/tiling.js +++ b/tiling.js @@ -733,18 +733,10 @@ export class Space extends Array { if (this._layoutQueued) return; - const callback = options?.callback; - this._layoutQueued = true; Utils.later_add(Meta.LaterType.RESIZE, () => { this._layoutQueued = false; - - if (callback) { - this.layout(animate, { callback }); - } - else { - this.layout(); - } + this.layout(animate, options); }); } From da05de690e5fc572cfb48805cc933ded0f5a08f3 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Fri, 29 Dec 2023 19:34:22 +1100 Subject: [PATCH 15/43] FIX: account for monitor offset for restoring window to position. --- tiling.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tiling.js b/tiling.js index 29d0d0d0e..0f751b69c 100644 --- a/tiling.js +++ b/tiling.js @@ -1731,7 +1731,7 @@ border-radius: ${borderWidth}px; // transforms break if there's no height this.cloneContainer.height = this.monitor.height; - this.layout(); + this.layout(true, { centerIfOne: false }); this.emit('monitor-changed'); } @@ -3179,7 +3179,8 @@ export function saveFullscreenFrame(metaWindow, tiled) { const f = metaWindow.get_frame_rect(); const fsf = metaWindow._fullscreen_frame ?? {}; metaWindow._fullscreen_frame = fsf; - fsf.x = f.x; + // offset by space's monitor.x + fsf.x = f.x - spaces.spaceOfWindow(metaWindow)?.monitor?.x ?? 0; fsf.y = f.y; fsf.width = f.width; fsf.height = f.height; From 2a8547726c1a08f98b469a7ca9a014bf1deb8d9d Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Fri, 29 Dec 2023 20:14:38 +1100 Subject: [PATCH 16/43] FIX: restore position for non-tiled windows. --- tiling.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tiling.js b/tiling.js index 0f751b69c..d9ba0f909 100644 --- a/tiling.js +++ b/tiling.js @@ -3114,7 +3114,8 @@ export function resizeHandler(metaWindow) { x = 0; } else { - x = metaWindow?._fullscreen_frame?.x ?? f.x - space.monitor.x; + x = metaWindow?._fullscreen_frame?.x ?? f.x; + x -= space.monitor.x; x = Math.max(x, Settings.prefs.horizontal_margin); // if pwm fullscreen previously @@ -3141,7 +3142,7 @@ export function resizeHandler(metaWindow) { } // Resizing from within a size-changed signal is troube (#73). Queue instead. - space.queueLayout(animate, { callback }); + space.queueLayout(animate, { callback, centerIfOne: false }); } } @@ -3180,7 +3181,7 @@ export function saveFullscreenFrame(metaWindow, tiled) { const fsf = metaWindow._fullscreen_frame ?? {}; metaWindow._fullscreen_frame = fsf; // offset by space's monitor.x - fsf.x = f.x - spaces.spaceOfWindow(metaWindow)?.monitor?.x ?? 0; + fsf.x = f.x; fsf.y = f.y; fsf.width = f.width; fsf.height = f.height; From 881929a5cec0deab31d40abd03827c55004d51b5 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Fri, 29 Dec 2023 22:50:01 +1100 Subject: [PATCH 17/43] Hide window selection when fullscreening (and undo on unfullscreen). --- tiling.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tiling.js b/tiling.js index d9ba0f909..db1c03427 100644 --- a/tiling.js +++ b/tiling.js @@ -3109,11 +3109,13 @@ export function resizeHandler(metaWindow) { // if window is fullscreened, then don't animate background space.container animation etc. if (metaWindow.fullscreen) { metaWindow._fullscreen_lock = true; + space.hideSelection(); addCallback = true; animate = false; x = 0; } else { + space.showSelection(); x = metaWindow?._fullscreen_frame?.x ?? f.x; x -= space.monitor.x; x = Math.max(x, Settings.prefs.horizontal_margin); @@ -3859,6 +3861,7 @@ export function focus_handler(metaWindow, user_data) { } let space = spaces.spaceOfWindow(metaWindow); + metaWindow.fullscreen ? space.hideSelection() : space.showSelection(); space.monitor.clickOverlay.show(); /** From 64784e66b5625de3e9c1312bbf47abd9afc1c4c3 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sat, 30 Dec 2023 11:25:03 +1100 Subject: [PATCH 18/43] Set guards to can't add multiple resizeHandlers to connection. --- tiling.js | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/tiling.js b/tiling.js index db1c03427..d9f45596d 100644 --- a/tiling.js +++ b/tiling.js @@ -1919,8 +1919,8 @@ export const Spaces = class Spaces extends Map { registerWindow(w); // Fixup allocations on reload allocateClone(w); - this.signals.connect(w, 'size-changed', resizeHandler); - this.signals.connect(w, 'position-changed', positionChangeHandler); + addResizeHandler(w); + addPositionHandler(w); }); this._initDone = true; @@ -3073,6 +3073,13 @@ export function destroyHandler(actor) { signals.disconnect(actor); } +export function addPositionHandler(metaWindow) { + if (metaWindow._positionHandlerAdded) { + return; + } + signals.connect(metaWindow, 'position-changed', positionChangeHandler); + metaWindow._positionHandlerAdded = true; +} export function positionChangeHandler(metaWindow) { // don't update saved position if fullscreen if (metaWindow.fullscreen || metaWindow?._fullscreen_lock) { @@ -3082,6 +3089,13 @@ export function positionChangeHandler(metaWindow) { saveFullscreenFrame(metaWindow); } +export function addResizeHandler(metaWindow) { + if (metaWindow._resizeHandlerAdded) { + return; + } + signals.connect(metaWindow, 'size-changed', resizeHandler); + metaWindow._resizeHandlerAdded = true; +} export function resizeHandler(metaWindow) { // if navigator is showing, reset/refresh it after a window has resized if (Navigator.navigating) { @@ -3376,10 +3390,9 @@ export function insertWindow(metaWindow, { existing }) { if (tiled) { animateWindow(metaWindow); } - if (metaWindow.unmapped) { - signals.connect(metaWindow, 'size-changed', resizeHandler); - signals.connect(metaWindow, 'position-changed', positionChangeHandler); - } + addResizeHandler(metaWindow); + addPositionHandler(metaWindow); + delete metaWindow.unmapped; }; From a00d774312d9c7c3ec14df70a0febeb819f163c0 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sat, 30 Dec 2023 13:38:32 +1100 Subject: [PATCH 19/43] FIX: resize handler should actually be called on gnome metalater RESIZE stage. --- tiling.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tiling.js b/tiling.js index d9f45596d..0208bf4dd 100644 --- a/tiling.js +++ b/tiling.js @@ -3022,12 +3022,12 @@ export function registerWindow(metaWindow) { }); signals.connect(metaWindow, 'size-changed', allocateClone); // Note: runs before gnome-shell's minimize handling code - signals.connect(metaWindow, 'notify::fullscreen', () => { + signals.connect(metaWindow, 'notify::fullscreen', mw => { /** * Run resizeHandler here since relying only on window resizing * to pick-up fullscreen change is trouble (e.g. windows that start as fullscreen). */ - resizeHandler(metaWindow); + resizeHandler(mw, true); Topbar.fixTopBar(); }); signals.connect(metaWindow, 'notify::minimized', metaWindow => { @@ -3093,7 +3093,11 @@ export function addResizeHandler(metaWindow) { if (metaWindow._resizeHandlerAdded) { return; } - signals.connect(metaWindow, 'size-changed', resizeHandler); + signals.connect(metaWindow, 'size-changed', mw => { + Utils.later_add(Meta.LaterType.RESIZE, () => { + resizeHandler(mw); + }); + }); metaWindow._resizeHandlerAdded = true; } export function resizeHandler(metaWindow) { From d4c011b638c43769fb51649a07b56e43f7078fcd Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sat, 30 Dec 2023 14:05:51 +1100 Subject: [PATCH 20/43] WIP: Placing guards on layout/queuelayout (only when needed based on previous saved size). --- tiling.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/tiling.js b/tiling.js index 0208bf4dd..21db2ce1e 100644 --- a/tiling.js +++ b/tiling.js @@ -3027,7 +3027,9 @@ export function registerWindow(metaWindow) { * Run resizeHandler here since relying only on window resizing * to pick-up fullscreen change is trouble (e.g. windows that start as fullscreen). */ - resizeHandler(mw, true); + Utils.later_add(Meta.LaterType.CHECK_FULLSCREEN, () => { + resizeHandler(mw); + }); Topbar.fixTopBar(); }); signals.connect(metaWindow, 'notify::minimized', metaWindow => { @@ -3119,11 +3121,21 @@ export function resizeHandler(metaWindow) { return; } + const fsf = metaWindow?._fullscreen_frame; const selected = metaWindow === space.selectedWindow; let addCallback = false; let animate = true; let x; + let needLayout = false; + if (fsf) { + // if is same size as saved (previously) then don't need a layout + if (fsf.width !== f.width || fsf.height !== f.height) { + console.log(`different width/height --> layout`); + needLayout = true; + } + } + // if window is fullscreened, then don't animate background space.container animation etc. if (metaWindow.fullscreen) { metaWindow._fullscreen_lock = true; @@ -3131,6 +3143,12 @@ export function resizeHandler(metaWindow) { addCallback = true; animate = false; x = 0; + move_to(space, metaWindow, { + x, + animate, + }); + console.log(`is fullscreen --> move to`); + return; } else { space.showSelection(); @@ -3141,6 +3159,7 @@ export function resizeHandler(metaWindow) { // if pwm fullscreen previously if (metaWindow._fullscreen_lock) { delete metaWindow._fullscreen_lock; + needLayout = true; addCallback = true; } else { @@ -3149,7 +3168,7 @@ export function resizeHandler(metaWindow) { } } - if (!space._inLayout) { + if (needLayout && !space._inLayout) { // Restore window position when eg. exiting fullscreen let callback = () => {}; if (addCallback && !Navigator.navigating && selected) { From 7353788ed3d0e1e31c0c5546a8f4c76b2ed76251 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sat, 30 Dec 2023 17:44:05 +1100 Subject: [PATCH 21/43] WIP: behaviour improved - handling osu! and other fullscreen behaviours. --- keybindings.js | 1 + tiling.js | 32 +++++++++++--------------------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/keybindings.js b/keybindings.js index c8bd851ae..7a396ee6c 100644 --- a/keybindings.js +++ b/keybindings.js @@ -258,6 +258,7 @@ export function setupActions(settings) { else { metaWindow.make_fullscreen(); } + Tiling.resizeHandler(metaWindow); }, Meta.KeyBindingFlags.PER_WINDOW); } diff --git a/tiling.js b/tiling.js index 21db2ce1e..e3bdcd4e5 100644 --- a/tiling.js +++ b/tiling.js @@ -3022,16 +3022,7 @@ export function registerWindow(metaWindow) { }); signals.connect(metaWindow, 'size-changed', allocateClone); // Note: runs before gnome-shell's minimize handling code - signals.connect(metaWindow, 'notify::fullscreen', mw => { - /** - * Run resizeHandler here since relying only on window resizing - * to pick-up fullscreen change is trouble (e.g. windows that start as fullscreen). - */ - Utils.later_add(Meta.LaterType.CHECK_FULLSCREEN, () => { - resizeHandler(mw); - }); - Topbar.fixTopBar(); - }); + signals.connect(metaWindow, 'notify::fullscreen', Topbar.fixTopBar); signals.connect(metaWindow, 'notify::minimized', metaWindow => { minimizeHandler(metaWindow); }); @@ -3136,17 +3127,18 @@ export function resizeHandler(metaWindow) { } } - // if window is fullscreened, then don't animate background space.container animation etc. - if (metaWindow.fullscreen) { - metaWindow._fullscreen_lock = true; - space.hideSelection(); - addCallback = true; - animate = false; - x = 0; + const moveTo = (x, animate) => { move_to(space, metaWindow, { x, animate, }); + }; + + // if window is fullscreened, then don't animate background space.container animation etc. + if (metaWindow.fullscreen) { + metaWindow._fullscreen_lock = true; + space.hideSelection(); + moveTo(0, false); console.log(`is fullscreen --> move to`); return; } @@ -3170,13 +3162,11 @@ export function resizeHandler(metaWindow) { if (needLayout && !space._inLayout) { // Restore window position when eg. exiting fullscreen + console.error(new Error(`do layout on resize`)); let callback = () => {}; if (addCallback && !Navigator.navigating && selected) { callback = () => { - move_to(space, metaWindow, { - x, - animate, - }); + moveTo(x, animate); }; } From eb69401ab0097c6e5329036a3366a81dd0850601 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sat, 30 Dec 2023 20:00:13 +1100 Subject: [PATCH 22/43] Cleanup. --- tiling.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tiling.js b/tiling.js index e3bdcd4e5..4c45ff3cb 100644 --- a/tiling.js +++ b/tiling.js @@ -3115,14 +3115,12 @@ export function resizeHandler(metaWindow) { const fsf = metaWindow?._fullscreen_frame; const selected = metaWindow === space.selectedWindow; let addCallback = false; - let animate = true; let x; let needLayout = false; if (fsf) { // if is same size as saved (previously) then don't need a layout if (fsf.width !== f.width || fsf.height !== f.height) { - console.log(`different width/height --> layout`); needLayout = true; } } @@ -3139,7 +3137,6 @@ export function resizeHandler(metaWindow) { metaWindow._fullscreen_lock = true; space.hideSelection(); moveTo(0, false); - console.log(`is fullscreen --> move to`); return; } else { @@ -3162,16 +3159,15 @@ export function resizeHandler(metaWindow) { if (needLayout && !space._inLayout) { // Restore window position when eg. exiting fullscreen - console.error(new Error(`do layout on resize`)); let callback = () => {}; if (addCallback && !Navigator.navigating && selected) { callback = () => { - moveTo(x, animate); + moveTo(x, true); }; } // Resizing from within a size-changed signal is troube (#73). Queue instead. - space.queueLayout(animate, { callback, centerIfOne: false }); + space.queueLayout(true, { callback, centerIfOne: false }); } } From cb59a5c835c997cb175c56a6debbb97e517d8cea Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sat, 30 Dec 2023 20:25:27 +1100 Subject: [PATCH 23/43] FIX: remove handler flags on destroy and init. --- tiling.js | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/tiling.js b/tiling.js index 4c45ff3cb..1b5072eaf 100644 --- a/tiling.js +++ b/tiling.js @@ -1832,6 +1832,7 @@ border-radius: ${borderWidth}px; } destroy() { + this.getWindows().forEach(w => removeHandlerFlags(w)); this.signals.destroy(); this.signals = null; this.background.destroy(); @@ -1916,6 +1917,9 @@ export const Spaces = class Spaces extends Map { // Clone and hook up existing windows display.get_tab_list(Meta.TabList.NORMAL_ALL, null) .forEach(w => { + // remove handler flags + removeHandlerFlags(w); + registerWindow(w); // Fixup allocations on reload allocateClone(w); @@ -3066,6 +3070,15 @@ export function destroyHandler(actor) { signals.disconnect(actor); } +/** + * Removes resize and position handler flags. + * @param {MetaWindow} metaWindow + */ +export function removeHandlerFlags(metaWindow) { + delete metaWindow._resizeHandlerAdded; + delete metaWindow._positionHandlerAdded; +} + export function addPositionHandler(metaWindow) { if (metaWindow._positionHandlerAdded) { return; @@ -3073,14 +3086,6 @@ export function addPositionHandler(metaWindow) { signals.connect(metaWindow, 'position-changed', positionChangeHandler); metaWindow._positionHandlerAdded = true; } -export function positionChangeHandler(metaWindow) { - // don't update saved position if fullscreen - if (metaWindow.fullscreen || metaWindow?._fullscreen_lock) { - return; - } - - saveFullscreenFrame(metaWindow); -} export function addResizeHandler(metaWindow) { if (metaWindow._resizeHandlerAdded) { @@ -3093,6 +3098,16 @@ export function addResizeHandler(metaWindow) { }); metaWindow._resizeHandlerAdded = true; } + +export function positionChangeHandler(metaWindow) { + // don't update saved position if fullscreen + if (metaWindow.fullscreen || metaWindow?._fullscreen_lock) { + return; + } + + saveFullscreenFrame(metaWindow); +} + export function resizeHandler(metaWindow) { // if navigator is showing, reset/refresh it after a window has resized if (Navigator.navigating) { From 325504da756d1debdf2b393b87f664ba7a936109 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sat, 30 Dec 2023 20:30:37 +1100 Subject: [PATCH 24/43] FIX: also if target width differs ==> do a queued layout. --- tiling.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tiling.js b/tiling.js index 1b5072eaf..221503755 100644 --- a/tiling.js +++ b/tiling.js @@ -3133,8 +3133,13 @@ export function resizeHandler(metaWindow) { let x; let needLayout = false; + // if target width differs ==> layout + if (metaWindow._targetWidth !== f.width || metaWindow._targetHeight !== f.height) { + needLayout = true; + } + + // if saved size differs ==> layout if (fsf) { - // if is same size as saved (previously) then don't need a layout if (fsf.width !== f.width || fsf.height !== f.height) { needLayout = true; } From e8121606c2560a3c012849d88de6f3439c8c9c53 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sun, 31 Dec 2023 16:31:08 +1100 Subject: [PATCH 25/43] Cleanup and on fullscreen run normal layout with move_to callback. --- tiling.js | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/tiling.js b/tiling.js index 221503755..aa72be5bc 100644 --- a/tiling.js +++ b/tiling.js @@ -711,7 +711,7 @@ export class Space extends Array { this.moveDone(); } - Utils.later_add(Meta.LaterType.IDLE, () => { + Utils.later_add(Meta.LaterType.RESIZE, () => { this.getWindows().forEach(w => { if (w.fullscreenOnLayout) { delete w.fullscreenOnLayout; @@ -3156,25 +3156,24 @@ export function resizeHandler(metaWindow) { if (metaWindow.fullscreen) { metaWindow._fullscreen_lock = true; space.hideSelection(); - moveTo(0, false); + space.layout(false, { callback: moveTo(0, false), centerIfOne: false }); return; } + + space.showSelection(); + x = metaWindow?._fullscreen_frame?.x ?? f.x; + x -= space.monitor.x; + x = Math.max(x, Settings.prefs.horizontal_margin); + + // if pwm fullscreen previously + if (metaWindow._fullscreen_lock) { + delete metaWindow._fullscreen_lock; + needLayout = true; + addCallback = true; + } else { - space.showSelection(); - x = metaWindow?._fullscreen_frame?.x ?? f.x; - x -= space.monitor.x; - x = Math.max(x, Settings.prefs.horizontal_margin); - - // if pwm fullscreen previously - if (metaWindow._fullscreen_lock) { - delete metaWindow._fullscreen_lock; - needLayout = true; - addCallback = true; - } - else { - // save width for later exit-fullscreen restoring - saveFullscreenFrame(metaWindow, true); - } + // save width for later exit-fullscreen restoring + saveFullscreenFrame(metaWindow, true); } if (needLayout && !space._inLayout) { From e05fbf99b597b19809766752ae87909d432a2049 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sun, 31 Dec 2023 18:58:03 +1100 Subject: [PATCH 26/43] Replaced with simpler workaround - unfullscreen/fullscreen on window show. --- tiling.js | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/tiling.js b/tiling.js index aa72be5bc..04df760dd 100644 --- a/tiling.js +++ b/tiling.js @@ -628,13 +628,6 @@ export class Space extends Array { let y0 = workArea.y; let fixPointAttempCount = 0; - // apply fullscreen if windows has fullscreenOnLayout property set - this.getWindows() - .filter(w => w.fullscreenOnLayout) - .forEach(w => { - w.make_fullscreen(); - }); - for (let i = 0; i < this.length; i++) { let column = this[i]; // Actorless windows are trouble. Layout could conceivable run while a window is dying or being born. @@ -711,14 +704,6 @@ export class Space extends Array { this.moveDone(); } - Utils.later_add(Meta.LaterType.RESIZE, () => { - this.getWindows().forEach(w => { - if (w.fullscreenOnLayout) { - delete w.fullscreenOnLayout; - } - }); - }); - // if only one window on space, then centre it if (centerIfOne && this.getWindows().length === 1) { const mw = this.getWindows()[0]; @@ -3462,11 +3447,21 @@ export function insertWindow(metaWindow, { existing }) { return; } - // address inserting windows that are already fullscreen: windows will be inserted - // as normal (non-fullscreen) and will be fullscreened on layout. + /** + * Address inserting windows that are already fullscreen: windows will be inserted + * as normal (non-fullscreen) and will be fullscreened on layout. + * see https://github.com/paperwm/PaperWM/issues/638 + */ if (metaWindow.fullscreen) { - metaWindow.fullscreenOnLayout = true; - metaWindow.unmake_fullscreen(); + animateWindow(metaWindow); + callbackOnActorShow(actor, () => { + GLib.timeout_add(GLib.PRIORITY_DEFAULT, 100, () => { + metaWindow.unmake_fullscreen(); + showWindow(metaWindow); + metaWindow.make_fullscreen(); + return false; // on return false destroys timeout + }); + }); } } From 91de5513777d5e7e5d07a983ceb08acfc2b3596a Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sun, 31 Dec 2023 21:42:43 +1100 Subject: [PATCH 27/43] Remove Glib timeout used for timeout to un/fullscreen. --- tiling.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tiling.js b/tiling.js index 04df760dd..82930a8d8 100644 --- a/tiling.js +++ b/tiling.js @@ -89,7 +89,7 @@ let signals, backgroundGroup, grabSignals; let gsettings, backgroundSettings, interfaceSettings; let displayConfig; let saveState; -let startupTimeoutId, timerId; +let startupTimeoutId, timerId, fullscrenStartTimeout; let workspaceSettings; export let inGrab; export function enable(extension) { @@ -189,6 +189,8 @@ export function disable () { startupTimeoutId = null; Utils.timeout_remove(timerId); timerId = null; + Utils.timeout_remove(fullscrenStartTimeout); + fullscrenStartTimeout = null; grabSignals.destroy(); grabSignals = null; @@ -704,7 +706,7 @@ export class Space extends Array { this.moveDone(); } - // if only one window on space, then centre it + // if only one window on space, then center it if (centerIfOne && this.getWindows().length === 1) { const mw = this.getWindows()[0]; centerWindowHorizontally(mw); @@ -3449,16 +3451,17 @@ export function insertWindow(metaWindow, { existing }) { /** * Address inserting windows that are already fullscreen: windows will be inserted - * as normal (non-fullscreen) and will be fullscreened on layout. + * as normal (non-fullscreen) and will be fullscreened after a timeout on actor show. * see https://github.com/paperwm/PaperWM/issues/638 */ if (metaWindow.fullscreen) { animateWindow(metaWindow); callbackOnActorShow(actor, () => { - GLib.timeout_add(GLib.PRIORITY_DEFAULT, 100, () => { + fullscrenStartTimeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 100, () => { metaWindow.unmake_fullscreen(); showWindow(metaWindow); metaWindow.make_fullscreen(); + fullscrenStartTimeout = null; return false; // on return false destroys timeout }); }); From d05363215b3214dd304cd5ee7c0a69c44639fe41 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Mon, 1 Jan 2024 14:00:30 +1100 Subject: [PATCH 28/43] FIX: stop setting topbar style on update space elements. --- tiling.js | 45 ++++++++------------------------------------- 1 file changed, 8 insertions(+), 37 deletions(-) diff --git a/tiling.js b/tiling.js index 82930a8d8..7ecae1360 100644 --- a/tiling.js +++ b/tiling.js @@ -1404,38 +1404,12 @@ border-radius: ${borderWidth}px; } } - /** - * Shows or hides this space's window position bar. Useful for temporarily - * hiding the position bar (e.g. for fullscreen mode). - * @param {boolean} show - */ - showWindowPositionBar(show = true) { - if (show) { - [this.windowPositionBarBackdrop, this.windowPositionBar] - .forEach(i => i.show()); - } - else { - [this.windowPositionBarBackdrop, this.windowPositionBar] - .forEach(i => i.hide()); - } - } - updateWindowPositionBar() { // if pref show-window-position-bar, exit if (!Settings.prefs.show_window_position_bar) { return; } - // space has a fullscreen window, hide window position bar - if (this.hasFullScreenWindow()) { - this.showWindowPositionBar(false); - return; - } - else { - // if here has no fullscreen window, show as per usual - this.showWindowPositionBar(); - } - // show space duplicate elements if not primary monitor if (!this.hasTopBar) { Utils.actor_raise(this.workspaceIndicator); @@ -1469,7 +1443,6 @@ border-radius: ${borderWidth}px; * @param {boolean} visible */ setSpaceTopbarElementsVisible(visible = false, options = {}) { - const changeTopBarStyle = options?.changeTopBarStyle ?? true; const force = options?.force ?? false; const setVisible = v => { if (v) { @@ -1483,21 +1456,16 @@ border-radius: ${borderWidth}px; } }; + if (this.hasTopBar && inPreview) { + Topbar.setTransparentStyle(); + } + // if windowPositionBar is disabled ==> don't show elements if (!Settings.prefs.show_window_position_bar) { setVisible(false); return; } - if (changeTopBarStyle) { - if (visible && this.hasTopBar) { - Topbar.setTransparentStyle(); - } - else { - Topbar.setNoBackgroundStyle(); - } - } - // if on different monitor then override to show elements if (!this.hasTopBar) { visible = true; @@ -2667,8 +2635,11 @@ export const Spaces = class Spaces extends Map { inPreview = PreviewMode.NONE; Topbar.updateWorkspaceIndicator(to.index); - this.selectedSpace = to; + if (to.hasTopBar) { + Topbar.setNoBackgroundStyle(); + } + this.selectedSpace = to; to.show(); let selected = to.selectedWindow; if (selected) From 0b789c1ae97cfec9d0efa280c1c39fcbd93a42a2 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Mon, 1 Jan 2024 22:42:08 +1100 Subject: [PATCH 29/43] Added temporary workaround for swap monitors with fullscreen. --- tiling.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tiling.js b/tiling.js index 7ecae1360..18654cff5 100644 --- a/tiling.js +++ b/tiling.js @@ -2200,6 +2200,19 @@ export const Spaces = class Spaces extends Map { // final switch with warp this.switchMonitor(direction); + /** + * Fullscreen monitor workaround. + * see https://github.com/paperwm/PaperWM/issues/638 + */ + this.forEach(space => { + space.getWindows().filter(w => w.fullscreen).forEach(w => { + animateWindow(w); + w.unmake_fullscreen(); + w.make_fullscreen(); + showWindow(w); + }); + }); + // ensure after swapping that the space elements are shown correctly this.setSpaceTopbarElementsVisible(true, { force: true }); } From f3505fc6b74a887f60c0d6054460ac878767e83c Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Tue, 2 Jan 2024 09:02:21 +1100 Subject: [PATCH 30/43] FIX: disable window position bar when fullscreen window is focused. --- tiling.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tiling.js b/tiling.js index 18654cff5..e1c0916e6 100644 --- a/tiling.js +++ b/tiling.js @@ -1393,7 +1393,10 @@ border-radius: ${borderWidth}px; * @param {boolean} enable */ enableWindowPositionBar(enable = true) { - if (enable) { + const add = + enable && + Settings.prefs.show_window_position_bar; + if (add) { [this.windowPositionBarBackdrop, this.windowPositionBar] .forEach(i => this.actor.add_actor(i)); this.updateWindowPositionBar(); @@ -3138,6 +3141,7 @@ export function resizeHandler(metaWindow) { // if pwm fullscreen previously if (metaWindow._fullscreen_lock) { + space.enableWindowPositionBar(); delete metaWindow._fullscreen_lock; needLayout = true; addCallback = true; @@ -3884,7 +3888,14 @@ export function focus_handler(metaWindow, user_data) { } let space = spaces.spaceOfWindow(metaWindow); - metaWindow.fullscreen ? space.hideSelection() : space.showSelection(); + if (metaWindow.fullscreen) { + space.enableWindowPositionBar(false); + space.hideSelection(); + } + else { + space.enableWindowPositionBar(); + space.showSelection(); + } space.monitor.clickOverlay.show(); /** From c0153754f82f5245023061042d818b35dcc772ba Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Tue, 2 Jan 2024 16:23:17 +1100 Subject: [PATCH 31/43] FIX: Update position bar when window closes. --- tiling.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tiling.js b/tiling.js index e1c0916e6..d99e87c63 100644 --- a/tiling.js +++ b/tiling.js @@ -3340,6 +3340,7 @@ export function remove_handler(workspace, meta_window) { let space = spaces.spaceOf(workspace); space.removeWindow(meta_window); + space.enableWindowPositionBar(); let actor = meta_window.get_compositor_private(); if (!actor) { From 0be164fe27828d1c3eafb03bc63238e0f24899bf Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Thu, 4 Jan 2024 09:04:29 +1100 Subject: [PATCH 32/43] Unfullscreen tiled window when selecting another window on same space. --- tiling.js | 117 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 96 insertions(+), 21 deletions(-) diff --git a/tiling.js b/tiling.js index d99e87c63..d856c9f73 100644 --- a/tiling.js +++ b/tiling.js @@ -89,7 +89,8 @@ let signals, backgroundGroup, grabSignals; let gsettings, backgroundSettings, interfaceSettings; let displayConfig; let saveState; -let startupTimeoutId, timerId, fullscrenStartTimeout; +let startupTimeoutId, timerId; +let fullscrenStartTimeout, fullscreenRelatedTimeout; let workspaceSettings; export let inGrab; export function enable(extension) { @@ -191,6 +192,8 @@ export function disable () { timerId = null; Utils.timeout_remove(fullscrenStartTimeout); fullscrenStartTimeout = null; + Utils.timeout_remove(fullscreenRelatedTimeout); + fullscreenRelatedTimeout = null; grabSignals.destroy(); grabSignals = null; @@ -932,6 +935,52 @@ export class Space extends Array { return this.getWindows().some(w => w.fullscreen); } + /** + * Unfullscreens windows. + * @param {MetaWindow} sourceWindow + */ + unfullscreenWindows(sourceWindow) { + if (!this.hasFullScreenWindow()) { + return; + } + Navigator.dismissDispatcher(Clutter.GrabState.KEYBOARD); + Navigator.getNavigator().finish(); + this.getWindows() + .forEach(w => { + w.unmaximize(Meta.MaximizeFlags.BOTH); + if (w.fullscreen) { + w.unmake_fullscreen(); + animateDown(w, { + callback: () => { + // need a delayed timeout here, otherwise window gets stuck in weird state + fullscreenRelatedTimeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, + 250, + () => { + /** + * need to resovle to unfullscreened window first + * (otherwise can get stuck in weird, half unfullscreened state). + * Last callback to so select the source (calling) window again. + */ + this.queueLayout(false, { + callback: () => { + ensureViewport(w, this, { + callback: () => { + if (sourceWindow) { + ensureViewport(sourceWindow, this); + } + }, + }); + }, + }); + fullscreenRelatedTimeout = null; + return false; // stops timeout recurrence + }); + }, + }); + } + }); + } + swap(direction, metaWindow) { metaWindow = metaWindow || this.selectedWindow; @@ -3569,12 +3618,15 @@ export function getOpenWindowPositionIndex(space) { } } -export function animateDown(metaWindow) { +export function animateDown(metaWindow, options = {}) { let space = spaces.spaceOfWindow(metaWindow); let workArea = space.workArea(); + let callback = options?.callback ?? function() {}; + Easer.addEase(metaWindow.clone, { y: workArea.y, time: Settings.prefs.animation_time, + onComplete: () => callback(), }); } @@ -3636,45 +3688,66 @@ export function ensureViewport(meta_window, space, options = {}) { space = space || spaces.spaceOfWindow(meta_window); let force = options?.force ?? false; let moveto = options?.moveto ?? true; + let select = options.select ?? true; let animate = options?.animate ?? true; + let callback = options?.callback ?? function() {}; + let ensureAnimation = options.ensureAnimation ?? Settings.EnsureViewportAnimation.TRANSLATE; let index = space.indexOf(meta_window); if (index === -1 || space.length === 0) return undefined; + let callbacked = false; if (space.selectedWindow.fullscreen && !meta_window.fullscreen) { - animateDown(space.selectedWindow); + callbacked = true; + animateDown(space.selectedWindow, callback); } let x = ensuredX(meta_window, space); - space.selectedWindow = meta_window; - let selected = space.selectedWindow; - if (!inPreview && selected.fullscreen) { - let y = 0; - let ty = selected.clone.get_transition('y'); - if (!space.isVisible(selected)) { - selected.clone.y = y; - } else if (!ty || ty.get_interval().final !== y) { - Easer.addEase(selected.clone, - { - y, - time: Settings.prefs.animation_time, - onComplete: space.moveDone.bind(space), - }); + let selected; + if (select) { + space.selectedWindow = meta_window; + selected = space.selectedWindow; + if (!inPreview && selected.fullscreen) { + let y = 0; + let ty = selected.clone.get_transition('y'); + if (!space.isVisible(selected)) { + selected.clone.y = y; + } else if (!ty || ty.get_interval().final !== y) { + callbacked = true; + Easer.addEase(selected.clone, + { + y, + time: Settings.prefs.animation_time, + onComplete: () => { + space.moveDone(); + callback(); + }, + }); + } } } if (moveto) { move_to(space, meta_window, { - x, force, animate, ensureAnimation, + x, + force, + animate, + ensureAnimation, + callback, }); } - selected.raise(); - Utils.actor_raise(selected.clone); - updateSelection(space, meta_window); + if (select && selected) { + selected.raise(); + Utils.actor_raise(selected.clone); + updateSelection(space, meta_window); + } + + // callback if hasn't been called + !callbacked && callback(); space.emit('select'); } @@ -3894,6 +3967,8 @@ export function focus_handler(metaWindow, user_data) { space.hideSelection(); } else { + // unfullscreen others windows on this space + space.unfullscreenWindows(metaWindow); space.enableWindowPositionBar(); space.showSelection(); } From 4a436eef6badbd9b5d2d7ea94a9da0b4d3a9375c Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Fri, 5 Jan 2024 02:10:48 +1100 Subject: [PATCH 33/43] FIX: multimonitor remove "bobble" of topbar positioning momemtarily showing. --- tiling.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tiling.js b/tiling.js index d856c9f73..f13a65ebb 100644 --- a/tiling.js +++ b/tiling.js @@ -619,8 +619,11 @@ export class Space extends Array { return; } + if (this.hasFullScreenWindow()) { + workArea.y = 0; + } // compensate to keep window position bar on all monitors - if (Settings.prefs.show_window_position_bar) { + else if (Settings.prefs.show_window_position_bar) { const panelBoxHeight = Topbar.panelBox.height; const monitor = Main.layoutManager.primaryMonitor; if (monitor !== this.monitor) { From cff6f73976b906d24503894ffa8ea726a1d505be Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Fri, 5 Jan 2024 02:24:13 +1100 Subject: [PATCH 34/43] FIX: multimonitor, when moving to another monitor (mouse), don't show window position bar on leaving monitor when it has fullscreen. --- tiling.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tiling.js b/tiling.js index f13a65ebb..4243c16e5 100644 --- a/tiling.js +++ b/tiling.js @@ -1511,6 +1511,12 @@ border-radius: ${borderWidth}px; } }; + if (this.hasFullScreenWindow()) { + setVisible(false); + this.enableWindowPositionBar(false); + return; + } + if (this.hasTopBar && inPreview) { Topbar.setTransparentStyle(); } From 05ee292e49fb179e6d2b13072d5995de7a7dfea9 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Fri, 5 Jan 2024 08:02:17 +1100 Subject: [PATCH 35/43] Revert "Unfullscreen tiled window when selecting another window on same" This reverts commit 0be164fe27828d1c3eafb03bc63238e0f24899bf. --- tiling.js | 117 ++++++++++-------------------------------------------- 1 file changed, 21 insertions(+), 96 deletions(-) diff --git a/tiling.js b/tiling.js index 4243c16e5..730f2f344 100644 --- a/tiling.js +++ b/tiling.js @@ -89,8 +89,7 @@ let signals, backgroundGroup, grabSignals; let gsettings, backgroundSettings, interfaceSettings; let displayConfig; let saveState; -let startupTimeoutId, timerId; -let fullscrenStartTimeout, fullscreenRelatedTimeout; +let startupTimeoutId, timerId, fullscrenStartTimeout; let workspaceSettings; export let inGrab; export function enable(extension) { @@ -192,8 +191,6 @@ export function disable () { timerId = null; Utils.timeout_remove(fullscrenStartTimeout); fullscrenStartTimeout = null; - Utils.timeout_remove(fullscreenRelatedTimeout); - fullscreenRelatedTimeout = null; grabSignals.destroy(); grabSignals = null; @@ -938,52 +935,6 @@ export class Space extends Array { return this.getWindows().some(w => w.fullscreen); } - /** - * Unfullscreens windows. - * @param {MetaWindow} sourceWindow - */ - unfullscreenWindows(sourceWindow) { - if (!this.hasFullScreenWindow()) { - return; - } - Navigator.dismissDispatcher(Clutter.GrabState.KEYBOARD); - Navigator.getNavigator().finish(); - this.getWindows() - .forEach(w => { - w.unmaximize(Meta.MaximizeFlags.BOTH); - if (w.fullscreen) { - w.unmake_fullscreen(); - animateDown(w, { - callback: () => { - // need a delayed timeout here, otherwise window gets stuck in weird state - fullscreenRelatedTimeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, - 250, - () => { - /** - * need to resovle to unfullscreened window first - * (otherwise can get stuck in weird, half unfullscreened state). - * Last callback to so select the source (calling) window again. - */ - this.queueLayout(false, { - callback: () => { - ensureViewport(w, this, { - callback: () => { - if (sourceWindow) { - ensureViewport(sourceWindow, this); - } - }, - }); - }, - }); - fullscreenRelatedTimeout = null; - return false; // stops timeout recurrence - }); - }, - }); - } - }); - } - swap(direction, metaWindow) { metaWindow = metaWindow || this.selectedWindow; @@ -3627,15 +3578,12 @@ export function getOpenWindowPositionIndex(space) { } } -export function animateDown(metaWindow, options = {}) { +export function animateDown(metaWindow) { let space = spaces.spaceOfWindow(metaWindow); let workArea = space.workArea(); - let callback = options?.callback ?? function() {}; - Easer.addEase(metaWindow.clone, { y: workArea.y, time: Settings.prefs.animation_time, - onComplete: () => callback(), }); } @@ -3697,66 +3645,45 @@ export function ensureViewport(meta_window, space, options = {}) { space = space || spaces.spaceOfWindow(meta_window); let force = options?.force ?? false; let moveto = options?.moveto ?? true; - let select = options.select ?? true; let animate = options?.animate ?? true; - let callback = options?.callback ?? function() {}; - let ensureAnimation = options.ensureAnimation ?? Settings.EnsureViewportAnimation.TRANSLATE; let index = space.indexOf(meta_window); if (index === -1 || space.length === 0) return undefined; - let callbacked = false; if (space.selectedWindow.fullscreen && !meta_window.fullscreen) { - callbacked = true; - animateDown(space.selectedWindow, callback); + animateDown(space.selectedWindow); } let x = ensuredX(meta_window, space); - let selected; - if (select) { - space.selectedWindow = meta_window; - selected = space.selectedWindow; - if (!inPreview && selected.fullscreen) { - let y = 0; - let ty = selected.clone.get_transition('y'); - if (!space.isVisible(selected)) { - selected.clone.y = y; - } else if (!ty || ty.get_interval().final !== y) { - callbacked = true; - Easer.addEase(selected.clone, - { - y, - time: Settings.prefs.animation_time, - onComplete: () => { - space.moveDone(); - callback(); - }, - }); - } + space.selectedWindow = meta_window; + let selected = space.selectedWindow; + if (!inPreview && selected.fullscreen) { + let y = 0; + let ty = selected.clone.get_transition('y'); + if (!space.isVisible(selected)) { + selected.clone.y = y; + } else if (!ty || ty.get_interval().final !== y) { + Easer.addEase(selected.clone, + { + y, + time: Settings.prefs.animation_time, + onComplete: space.moveDone.bind(space), + }); } } if (moveto) { move_to(space, meta_window, { - x, - force, - animate, - ensureAnimation, - callback, + x, force, animate, ensureAnimation, }); } - if (select && selected) { - selected.raise(); - Utils.actor_raise(selected.clone); - updateSelection(space, meta_window); - } - - // callback if hasn't been called - !callbacked && callback(); + selected.raise(); + Utils.actor_raise(selected.clone); + updateSelection(space, meta_window); space.emit('select'); } @@ -3976,8 +3903,6 @@ export function focus_handler(metaWindow, user_data) { space.hideSelection(); } else { - // unfullscreen others windows on this space - space.unfullscreenWindows(metaWindow); space.enableWindowPositionBar(); space.showSelection(); } From 443dcd121a3cf6f89539aefad51e28ad710be4ef Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Fri, 5 Jan 2024 08:30:26 +1100 Subject: [PATCH 36/43] Revert "FIX: multimonitor remove "bobble" of topbar positioning momemtarily" This reverts commit 4a436eef6badbd9b5d2d7ea94a9da0b4d3a9375c. --- tiling.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tiling.js b/tiling.js index 730f2f344..a42758862 100644 --- a/tiling.js +++ b/tiling.js @@ -616,11 +616,8 @@ export class Space extends Array { return; } - if (this.hasFullScreenWindow()) { - workArea.y = 0; - } // compensate to keep window position bar on all monitors - else if (Settings.prefs.show_window_position_bar) { + if (Settings.prefs.show_window_position_bar) { const panelBoxHeight = Topbar.panelBox.height; const monitor = Main.layoutManager.primaryMonitor; if (monitor !== this.monitor) { From 8e506b8d659cc271b895a4d200eb22c143063019 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Fri, 5 Jan 2024 09:34:56 +1100 Subject: [PATCH 37/43] Updated space element vis check to be if has fullscreen that is active on space. --- tiling.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiling.js b/tiling.js index a42758862..45710d43f 100644 --- a/tiling.js +++ b/tiling.js @@ -1459,7 +1459,7 @@ border-radius: ${borderWidth}px; } }; - if (this.hasFullScreenWindow()) { + if (this.selectedWindow?.fullscreen) { setVisible(false); this.enableWindowPositionBar(false); return; From 9e77deacae06df56830c048a6877087cbba52cb6 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sat, 6 Jan 2024 19:50:24 +1100 Subject: [PATCH 38/43] FIX: for "bobble" issue (flash of topbar spacing when moving mouse to another monitor. --- settings.js | 3 ++- tiling.js | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/settings.js b/settings.js index 19727a6eb..6cbcf9892 100644 --- a/settings.js +++ b/settings.js @@ -31,7 +31,8 @@ export function enable(extension) { acceleratorParse = new AcceleratorParse(); _overriddingConflicts = false; prefs = {}; - ['window-gap', 'vertical-margin', 'vertical-margin-bottom', 'horizontal-margin', + [ + 'window-gap', 'vertical-margin', 'vertical-margin-bottom', 'horizontal-margin', 'workspace-colors', 'default-background', 'animation-time', 'default-show-top-bar', 'swipe-sensitivity', 'swipe-friction', 'cycle-width-steps', 'cycle-height-steps', 'maximize-width-percent', 'minimap-scale', 'edge-preview-scale', diff --git a/tiling.js b/tiling.js index 45710d43f..cb063abe1 100644 --- a/tiling.js +++ b/tiling.js @@ -616,8 +616,15 @@ export class Space extends Array { return; } + /** + * If current window is fullscreened, then treat workarea as fullscreen (y = 0). + * This a "flash of topbar spacing") before consecutive layout call resolves. + */ + if (this.selectedWindow?.fullscreen) { + workArea.y = 0; + } // compensate to keep window position bar on all monitors - if (Settings.prefs.show_window_position_bar) { + else if (Settings.prefs.show_window_position_bar) { const panelBoxHeight = Topbar.panelBox.height; const monitor = Main.layoutManager.primaryMonitor; if (monitor !== this.monitor) { @@ -3896,11 +3903,36 @@ export function focus_handler(metaWindow, user_data) { let space = spaces.spaceOfWindow(metaWindow); if (metaWindow.fullscreen) { + space.setSpaceTopbarElementsVisible(false); space.enableWindowPositionBar(false); space.hideSelection(); } else { - space.enableWindowPositionBar(); + /** + * For non-topbar spaces, bring down fullscreen windows to mimic + * gnome behaviour with a topbar. + */ + if (!space.hasTopBar) { + space.getWindows() + .filter(w => w.fullscreen) + .forEach(w => { w.clone.y = metaWindow.clone.y; }); + } + + /** + * if there then clone.y shouldn't be 0. This can happen though if a window + * is fullscreened when `layout` is called. In this case, when we focuse on a + * window that isn't fullscreen but has clone.y 0 ==> need a layout call. + */ + if ( + metaWindow.clone.y === 0 && + Settings.prefs.vertical_margin !== 0 && + Settings.prefs.window_gap !== 0 + ) { + space.layout(false); + } + + space.setSpaceTopbarElementsVisible(true); + space.enableWindowPositionBar(true); space.showSelection(); } space.monitor.clickOverlay.show(); From c073c539d8c68805f700b74d406ca310a08a62e3 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sun, 7 Jan 2024 13:24:18 +1100 Subject: [PATCH 39/43] FIX: when fullscreen window and mouse move to another monitor, ensure space elements are hidden as well. --- tiling.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tiling.js b/tiling.js index cb063abe1..e53200948 100644 --- a/tiling.js +++ b/tiling.js @@ -622,6 +622,7 @@ export class Space extends Array { */ if (this.selectedWindow?.fullscreen) { workArea.y = 0; + this.setSpaceTopbarElementsVisible(false); } // compensate to keep window position bar on all monitors else if (Settings.prefs.show_window_position_bar) { From 86c733355cca9a04267c2f5f008f1a10f3caa171 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sun, 7 Jan 2024 13:43:55 +1100 Subject: [PATCH 40/43] Cleanup and fullscreen display on spaces with tiled and fullscreen windows. --- tiling.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tiling.js b/tiling.js index e53200948..d4c8cb207 100644 --- a/tiling.js +++ b/tiling.js @@ -3909,14 +3909,14 @@ export function focus_handler(metaWindow, user_data) { space.hideSelection(); } else { + let needLayout = false; /** * For non-topbar spaces, bring down fullscreen windows to mimic * gnome behaviour with a topbar. */ - if (!space.hasTopBar) { - space.getWindows() - .filter(w => w.fullscreen) - .forEach(w => { w.clone.y = metaWindow.clone.y; }); + if (!space.hasTopBar && + space.hasFullScreenWindow()) { + needLayout = true; } /** @@ -3929,6 +3929,10 @@ export function focus_handler(metaWindow, user_data) { Settings.prefs.vertical_margin !== 0 && Settings.prefs.window_gap !== 0 ) { + needLayout = true; + } + + if (needLayout) { space.layout(false); } From 42b426519be0b9b1e1aed5ce1841ac3e66411e0c Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sun, 7 Jan 2024 18:54:32 +1100 Subject: [PATCH 41/43] Cleanup logs (adding check to stop writing about actor adding/removing for topbar enabling/disabling. --- tiling.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tiling.js b/tiling.js index d4c8cb207..377f84ca5 100644 --- a/tiling.js +++ b/tiling.js @@ -1406,12 +1406,20 @@ border-radius: ${borderWidth}px; Settings.prefs.show_window_position_bar; if (add) { [this.windowPositionBarBackdrop, this.windowPositionBar] - .forEach(i => this.actor.add_actor(i)); + .forEach(i => { + if (!i.get_parent()) { + this.actor.add_child(i); + } + }); this.updateWindowPositionBar(); } else { [this.windowPositionBarBackdrop, this.windowPositionBar] - .forEach(i => this.actor.remove_actor(i)); + .forEach(i => { + if (i.get_parent()) { + this.actor.remove_child(i); + } + }); } } @@ -3904,8 +3912,8 @@ export function focus_handler(metaWindow, user_data) { let space = spaces.spaceOfWindow(metaWindow); if (metaWindow.fullscreen) { - space.setSpaceTopbarElementsVisible(false); space.enableWindowPositionBar(false); + space.setSpaceTopbarElementsVisible(false); space.hideSelection(); } else { From 257dc5bb93203865b2344cf4077526704195458c Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sun, 7 Jan 2024 18:58:41 +1100 Subject: [PATCH 42/43] FIX: corner case: fullscreen, create/insert new window => show space elements. --- tiling.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tiling.js b/tiling.js index 377f84ca5..244097397 100644 --- a/tiling.js +++ b/tiling.js @@ -3550,6 +3550,7 @@ export function insertWindow(metaWindow, { existing }) { Main.activateWindow(metaWindow); ensureViewport(space.selectedWindow, space); + space.setSpaceTopbarElementsVisible(true); }); return; From 438319050f3184ed2772eb2ff08d0da589f94cd0 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sun, 7 Jan 2024 19:57:07 +1100 Subject: [PATCH 43/43] FIX: corner-case, multiple fullscreen windows on space, unfullscreening one => space elements not shown. --- tiling.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tiling.js b/tiling.js index 244097397..71a1f0da1 100644 --- a/tiling.js +++ b/tiling.js @@ -377,11 +377,6 @@ export class Space extends Array { setFocusMode(getDefaultFocusMode(), this); }); - // update space elements when in/out of fullscreen - this.signals.connect(global.display, 'in-fullscreen-changed', () => { - this.setSpaceTopbarElementsVisible(true); - }); - this.signals.connect(interfaceSettings, "changed::color-scheme", this.updateBackground.bind(this)); this.signals.connect(gsettings, 'changed::default-background', this.updateBackground.bind(this)); this.signals.connect(gsettings, 'changed::use-default-background', this.updateBackground.bind(this)); @@ -3022,7 +3017,10 @@ export function registerWindow(metaWindow) { }); signals.connect(metaWindow, 'size-changed', allocateClone); // Note: runs before gnome-shell's minimize handling code - signals.connect(metaWindow, 'notify::fullscreen', Topbar.fixTopBar); + signals.connect(metaWindow, 'notify::fullscreen', () => { + Topbar.fixTopBar(); + spaces.spaceOfWindow(metaWindow)?.setSpaceTopbarElementsVisible(true); + }); signals.connect(metaWindow, 'notify::minimized', metaWindow => { minimizeHandler(metaWindow); });