diff --git a/tiling-assistant@leleat-on-github/extension.js b/tiling-assistant@leleat-on-github/extension.js index 2cd642c..ad155ac 100644 --- a/tiling-assistant@leleat-on-github/extension.js +++ b/tiling-assistant@leleat-on-github/extension.js @@ -274,30 +274,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); @@ -305,24 +281,30 @@ export default class TilingAssistantExtension extends Extension { try { parent.make_directory_with_parents(null); } catch (e) { - if (e.code !== Gio.IOErrorEnum.EXISTS) { + if (e.code !== Gio.IOErrorEnum.EXISTS) throw e; - } } - 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 { file.create(Gio.FileCreateFlags.NONE, null); } catch (e) { - if (e.code !== Gio.IOErrorEnum.EXISTS) { + if (e.code !== Gio.IOErrorEnum.EXISTS) throw e; - } } - file.replace_contents(JSON.stringify(saveObj), null, false, - Gio.FileCreateFlags.REPLACE_DESTINATION, null); + file.replace_contents( + JSON.stringify({ + windows: Object.fromEntries(this._twm.getTileStates()), + tileGroups: Object.fromEntries(this._twm.getTileGroups()) + }), + null, + false, + Gio.FileCreateFlags.REPLACE_DESTINATION, + null + ); } /** @@ -336,7 +318,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; @@ -344,39 +326,40 @@ export default class TilingAssistantExtension extends Extension { try { file.create(Gio.FileCreateFlags.NONE, null); } catch (e) { - if (e.code !== Gio.IOErrorEnum.EXISTS) { + if (e.code !== Gio.IOErrorEnum.EXISTS) throw e; - } } const [success, contents] = file.load_contents(null); 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 keysAsNumbers = entries => entries.map(([key, value]) => [parseInt(key), value]); + const tileGroups = new Map(keysAsNumbers(Object.entries(states.tileGroups))); + const tileStates = new Map(keysAsNumbers(Object.entries(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) - return; + this._twm.setTileGroups(tileGroups); + this._twm.setTileStates(tileStates); - const jsToRect = jsRect => jsRect && new Rect( - jsRect.x, jsRect.y, jsRect.width, jsRect.height - ); + openWindows.forEach(window => { + const tileState = tileStates.get(window.get_id()); - window.isTiled = isTiled; - window.tiledRect = jsToRect(tiledRect); - window.untiledRect = jsToRect(untiledRect); - }); + if (tileState) { + const { isTiled, tiledRect, untiledRect } = tileState; + const jsToRect = jsRect => jsRect && new Rect( + jsRect.x, jsRect.y, jsRect.width, jsRect.height + ); - const tileGroups = new Map(saveObj['tileGroups']); - this._twm.setTileGroups(tileGroups); - openWindows.forEach(w => { - if (tileGroups.has(w.get_id())) { - const group = this._twm.getTileGroupFor(w); + window.isTiled = isTiled; + window.tiledRect = jsToRect(tiledRect); + window.untiledRect = jsToRect(untiledRect); + } + + + if (tileGroups.has(window.get_id())) { + const group = this._twm.getTileGroupFor(window); this._twm.updateTileGroup(group); } }); diff --git a/tiling-assistant@leleat-on-github/src/extension/resizeHandler.js b/tiling-assistant@leleat-on-github/src/extension/resizeHandler.js index debd7ff..559e8f6 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.saveTileState(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.saveTileState(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 0c3294a..0bc3f57 100644 --- a/tiling-assistant@leleat-on-github/src/extension/tilingWindowManager.js +++ b/tiling-assistant@leleat-on-github/src/extension/tilingWindowManager.js @@ -16,6 +16,11 @@ export class TilingWindowManager { // { windowId1: [windowIdX, windowIdY, ...], windowId2: [...], ... } this._tileGroups = new Map(); + /** + * {windowId: {isTiled: boolean, tiledRect: {}, untiledRect: {}}} + */ + this._tileStates = new Map(); + const assertExistenceFor = window => { window.assertExistence = () => {}; @@ -65,6 +70,7 @@ export class TilingWindowManager { }); this._tileGroups.clear(); + this._tileStates.clear(); if (this._openAppTiledTimerId) { GLib.Source.remove(this._openAppTiledTimerId); @@ -246,6 +252,7 @@ export class TilingWindowManager { // Maximized with gaps if (maximize) { this._updateGappedMaxWindowSignals(window); + this.saveTileState(window); // Tiled window } else if (!fakeTile) { @@ -253,12 +260,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.saveTileState(window); return; } // Setup the (new) tileGroup to raise tiled windows as a group const topTileGroup = this._getWindowsForBuildingTileGroup(monitor); this.updateTileGroup(topTileGroup); + this.saveTileState(window); this.emit('window-tiled', window); @@ -334,6 +343,8 @@ export class TilingWindowManager { window.tiledRect = null; window.untiledRect = null; + this.deleteTilingState(window); + this.emit('window-untiled', window); } @@ -392,6 +403,17 @@ export class TilingWindowManager { this.updateTileGroup(tileGroup); } + static getTileStates() { + return this._tileStates; + } + + /** + * @param {Map} states - + */ + static setTileStates(states) { + this._tileStates = states; + } + /** * @returns {Map} * For ex: { windowId1: [windowIdX, windowIdY, ...], windowId2: ... } @@ -1057,6 +1079,34 @@ export class TilingWindowManager { app.open_new_window(-1); } + static saveTileState(window) { + const windowState = this._tileStates.get(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 { + this._tileStates.set( + window.get_id(), + { + isTiled: window.isTiled, + tiledRect: rectToJsObject(window.tiledRect), + untiledRect: rectToJsObject(window.untiledRect) + } + ); + } + } + + static deleteTilingState(window) { + this._tileStates.delete(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.