diff --git a/tiling-assistant@leleat-on-github/extension.js b/tiling-assistant@leleat-on-github/extension.js index 2cd642c..00c5ddd 100644 --- a/tiling-assistant@leleat-on-github/extension.js +++ b/tiling-assistant@leleat-on-github/extension.js @@ -25,7 +25,7 @@ import KeybindingHandler from './src/extension/keybindingHandler.js'; import LayoutsManager from './src/extension/layoutsManager.js'; import ActiveWindowHint from './src/extension/activeWindowHint.js'; import AltTabOverride from './src/extension/altTab.js'; -import { Rect } from './src/extension/utility.js'; +import { Rect, TilingStates } from './src/extension/utility.js'; /** * 2 entry points: @@ -229,6 +229,8 @@ export default class TilingAssistantExtension extends Extension { // them after the session is unlocked again. this._saveBeforeSessionLock(); + TilingStates.clear(); + this._settingsOverrider.destroy(); this._settingsOverrider = null; this._moveHandler.destroy(); @@ -274,30 +276,6 @@ export default class TilingAssistantExtension extends Extension { this._wasLocked = true; - const rectToJsObj = rect => rect && { - x: rect.x, - y: rect.y, - width: rect.width, - height: rect.height - }; - - // can't just check for isTiled because maximized windows may - // have an untiledRect as well in case window gaps are used - const openWindows = this._twm.getWindows(true); - const savedWindows = openWindows.filter(w => w.untiledRect).map(w => { - return { - windowId: w.get_stable_sequence(), - isTiled: w.isTiled, - tiledRect: rectToJsObj(w.tiledRect), - untiledRect: rectToJsObj(w.untiledRect) - }; - }); - - const saveObj = { - 'windows': savedWindows, - 'tileGroups': Array.from(this._twm.getTileGroups()) - }; - const userPath = GLib.get_user_config_dir(); const parentPath = GLib.build_filenamev([userPath, '/tiling-assistant']); const parent = Gio.File.new_for_path(parentPath); @@ -310,7 +288,7 @@ export default class TilingAssistantExtension extends Extension { } } - const path = GLib.build_filenamev([parentPath, '/tiledSessionRestore.json']); + const path = GLib.build_filenamev([parentPath, '/tiledSessionRestore2.json']); const file = Gio.File.new_for_path(path); try { @@ -321,7 +299,7 @@ export default class TilingAssistantExtension extends Extension { } } - file.replace_contents(JSON.stringify(saveObj), null, false, + file.replace_contents(JSON.stringify(Object.fromEntries(TilingStates)), null, false, Gio.FileCreateFlags.REPLACE_DESTINATION, null); } @@ -336,7 +314,7 @@ export default class TilingAssistantExtension extends Extension { this._wasLocked = false; const userPath = GLib.get_user_config_dir(); - const path = GLib.build_filenamev([userPath, '/tiling-assistant/tiledSessionRestore.json']); + const path = GLib.build_filenamev([userPath, '/tiling-assistant/tiledSessionRestore2.json']); const file = Gio.File.new_for_path(path); if (!file.query_exists(null)) return; @@ -353,16 +331,17 @@ export default class TilingAssistantExtension extends Extension { if (!success || !contents.length) return; - const openWindows = this._twm.getWindows(true); - const saveObj = JSON.parse(new TextDecoder().decode(contents)); + const states = JSON.parse(new TextDecoder().decode(contents)); + const windowObjects = states.windows; + const openWindows = global.display.list_all_windows(); - const windowObjects = saveObj['windows']; - windowObjects.forEach(wObj => { - const { windowId, isTiled, tiledRect, untiledRect } = wObj; - const window = openWindows.find(w => w.get_stable_sequence() === windowId); - if (!window) + openWindows.forEach(window => { + const savedState = windowObjects[window.get_id()]; + + if (!savedState) return; + const { isTiled, tiledRect, untiledRect } = savedState; const jsToRect = jsRect => jsRect && new Rect( jsRect.x, jsRect.y, jsRect.width, jsRect.height ); @@ -372,7 +351,7 @@ export default class TilingAssistantExtension extends Extension { window.untiledRect = jsToRect(untiledRect); }); - const tileGroups = new Map(saveObj['tileGroups']); + const tileGroups = new Map(states.tileGroups); this._twm.setTileGroups(tileGroups); openWindows.forEach(w => { if (tileGroups.has(w.get_id())) { @@ -380,5 +359,8 @@ export default class TilingAssistantExtension extends Extension { this._twm.updateTileGroup(group); } }); + + TilingStates.set('windows', states.windows); + TilingStates.set('tileGroups', states.tileGroups); } } diff --git a/tiling-assistant@leleat-on-github/src/extension/resizeHandler.js b/tiling-assistant@leleat-on-github/src/extension/resizeHandler.js index debd7ff..77caf41 100644 --- a/tiling-assistant@leleat-on-github/src/extension/resizeHandler.js +++ b/tiling-assistant@leleat-on-github/src/extension/resizeHandler.js @@ -352,6 +352,8 @@ export default class TilingResizeHandler { newGrabbedTiledRectHeight ); + Twm.updateSavedTilingState(window); + // Now calculate the new tiledRects for the windows, which were resized // along the window based on the diff of the window's tiledRect pre // and after the grab. @@ -379,6 +381,8 @@ export default class TilingResizeHandler { win.tiledRect.y += isResizingS ? tiledRectDiffHeight : 0; win.tiledRect.height -= tiledRectDiffHeight; } + + Twm.updateSavedTilingState(win); }); this._preGrabRects.clear(); diff --git a/tiling-assistant@leleat-on-github/src/extension/tilingWindowManager.js b/tiling-assistant@leleat-on-github/src/extension/tilingWindowManager.js index 84c1aac..4d82b89 100644 --- a/tiling-assistant@leleat-on-github/src/extension/tilingWindowManager.js +++ b/tiling-assistant@leleat-on-github/src/extension/tilingWindowManager.js @@ -3,7 +3,7 @@ import { Main } from '../dependencies/shell.js'; import { getWindows } from '../dependencies/unexported/altTab.js'; import { Orientation, Settings } from '../common.js'; -import { Rect, Util } from './utility.js'; +import { Rect, TilingStates, Util } from './utility.js'; /** * Singleton responsible for tiling. Implement the signals in a separate Clutter @@ -220,6 +220,7 @@ export class TilingWindowManager { // Maximized with gaps if (maximize) { this._updateGappedMaxWindowSignals(window); + this.updateSavedTilingState(window); // Tiled window } else if (!fakeTile) { @@ -227,12 +228,14 @@ export class TilingWindowManager { // resizing or raising together. Also don't call the Tiling Popup. if (Settings.getBoolean('disable-tile-groups') || ignoreTA) { this.updateTileGroup([window]); + this.updateSavedTilingState(window); return; } // Setup the (new) tileGroup to raise tiled windows as a group const topTileGroup = this._getWindowsForBuildingTileGroup(monitor); this.updateTileGroup(topTileGroup); + this.updateSavedTilingState(window); this.emit('window-tiled', window); @@ -308,6 +311,8 @@ export class TilingWindowManager { window.tiledRect = null; window.untiledRect = null; + this.deleteSavedTilingState(window); + this.emit('window-untiled', window); } @@ -1032,6 +1037,55 @@ export class TilingWindowManager { app.open_new_window(-1); } + static updateSavedTilingState(window) { + // window state + const windowState = TilingStates.get('windows')[window.get_id()]; + const rectToJsObject = rect => { + return rect + ? { x: rect.x, y: rect.y, width: rect.width, height: rect.height } + : undefined; + }; + + if (windowState) { + windowState.isTiled = window.isTiled; + windowState.tiledRect = rectToJsObject(window.tiledRect); + windowState.untiledRect = rectToJsObject(window.untiledRect); + } else { + TilingStates.get('windows')[window.get_id()] = { + isTiled: window.isTiled, + tiledRect: rectToJsObject(window.tiledRect), + untiledRect: rectToJsObject(window.untiledRect) + }; + } + + // tile groups + const tileGroups = TilingStates.get('tileGroups'); + const group = tileGroups.find(g => g[0] === window.get_id()); + + if (group) { + group.splice(1); + group.push(this._tileGroups.get(window.get_id())); + } else { + tileGroups.push([ + window.get_id(), + this._tileGroups.get(window.get_id()) + ]); + } + } + + static deleteSavedTilingState(window) { + const savedTilingState = TilingStates.get('windows'); + + if (!savedTilingState[window.get_id()]) + return; + + delete savedTilingState[window.get_id()]; + + TilingStates.set('tileGroups', TilingStates.get('tileGroups').filter(group => { + return group[0] !== window.get_id(); + })); + } + /** * Gets the top windows, which are supposed to be in a tile group. That * means windows, which are tiled, and don't overlap each other. diff --git a/tiling-assistant@leleat-on-github/src/extension/utility.js b/tiling-assistant@leleat-on-github/src/extension/utility.js index af41d1c..0da8d40 100644 --- a/tiling-assistant@leleat-on-github/src/extension/utility.js +++ b/tiling-assistant@leleat-on-github/src/extension/utility.js @@ -3,6 +3,20 @@ import { Main } from '../dependencies/shell.js'; import { Direction, Orientation, Settings } from '../common.js'; +/** + * The states of the windows tiling states during the runtime of the extension. + * It is used for for saving/restoring the states when un/locking the session. + */ +export const TilingStates = new Map([ + // `windows` value will map the window.id to an object with isTiled, + // tiledRect, and untiledRect props + ['windows', {}], + // `tileGroups` value will be an array of tuples (arrays). The first value + // in a tuple will be the window.id. The second tuple value is an array of + // window.ids of the windows in the tile group. + ['tileGroups', []] +]); + /** * Library of commonly used functions for the extension.js' files * (and *not* the prefs files)