You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Locking and unlocking GNOME tears down O-Tiling and reconstructs its layout from window rectangles. This can rearrange windows and lose split relationships and stack ordering.
Capture a plain, session-local layout snapshot before lock teardown and restore it using stable window sequence IDs on unlock. Preserve split directions and proportions, stack order and active tabs, and manual floating overrides. Prune missing or moved windows, tile new windows normally, and fall back to spatial reconstruction when monitor work areas change. Retain pending snapshots if another lock interrupts startup. Ordinary disable clears the snapshot; no live window/actor references or disk persistence are retained.
ESLint, TypeScript checks, and clean make pack builds pass. Both packages contain the required files, have no forbidden extension-process Gdk imports, and meet the 10 MB size limit.
The reporter tested the combined local build on Ubuntu 26.04.1 / GNOME 50.1 and confirmed the reported layout-preservation issue is resolved.
Automated tests use lightweight GNOME boundary doubles. Multi-monitor hotplug and broader environment coverage remain unverified. This change is independent of #113.
Thanks for this, the approach is sound but it still needs major refinement.
Verified
Applies cleanly onto current main (7be3016).
tests/layout-snapshot.test.mjs (9) and tests/lock-layout.test.mjs (7) pass.
ESLint is clean on the changed files. tsc --noEmit shows one error in panel_settings.ts, which main also has, so it is not from this PR.
Every API the PR relies on exists with the expected signature: Forest.create_fork, parents, toplevel, stacks, Fork.set_ratio / prev_ratio, Stack.active_id, AutoTiler.update_stack / update_toplevel, Ext.on_tile_attach / add_tag / monitor_work_area.
Restore mirrors reconstruct.ts. Tab order and the active tab survive because Stack.clear() does not reset active_id.
Not verified
That sessionMode.isLocked is already true when disable() runs on lock.
Real GNOME behavior. The tests mock Node, Stack and the Shell, so they never touch real tab widgets. Please run the manual checklist from the README (nested splits, a stack, a floating window, several lock/unlock cycles, suspend/resume) and note the GNOME version.
EGO review risk const lockLayout = new PendingLayout() is a module-scope instance that intentionally keeps data across disable(). The review guidelines say module-scope class instances must be destroyed and dynamic data cleared in disable(). I would rather not rely on a reviewer accepting an exception, so I suggest a different approach (below).
Suggested approach: save the layout in the extension schema
Instead of keeping a snapshot in module scope, store it in the extension's own GSettings schema and restore the tiling tree from there when the extension is re-enabled.
Add one string key (for example lock-layout, default '') to schemas/org.gnome.shell.extensions.o-tiling.gschema.xml, next to the existing type="s" keys. The schema is already shipped in the zip.
In disable(), when sessionMode.isLocked, write JSON.stringify(captureLayout(ext)) to that key before ext.destroy(), while the settings object is still alive. On an ordinary disable, clear the key.
In enable(), read and parse the key, pass the result to auto_tile_on(false, false, snapshot), and reset the key to '' once restoration finishes.
Delete PendingLayout and the module-scope lockLayout. Nothing then outlives disable() in memory, so the guideline concern goes away.
Two things to handle with this approach:
The window IDs come from get_stable_sequence(), which is only stable within one shell session. Make sure a stale value left in dconf after a crash, logout or reboot is never applied to different windows, for example by clearing the key on fresh startup.
Wrap the JSON parse so a corrupt value falls back to the existing reconstruct path.
Requested changes
Switch to the schema-based persistence above.
restoreWorkspace re-implements link_children from reconstruct.ts. Export that one and reuse it.
Remove if (root.inner.kind !== NodeKind.FORK) return [];. It is unreachable after the wrap and would leave forks behind if it ever fired.
Format the test files like the rest of the repo. The one-line style can read as generated code to EGO reviewers.
Move the new README test section out from under "Happy tiling."
Minor, no action needed: if auto-tiling is soft-disabled, auto_tile_on returns before the snapshot is cleared, so it lingers until the next ordinary disable. The schema approach with an explicit clear on disable covers this too.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Locking and unlocking GNOME tears down O-Tiling and reconstructs its layout from window rectangles. This can rearrange windows and lose split relationships and stack ordering.
Capture a plain, session-local layout snapshot before lock teardown and restore it using stable window sequence IDs on unlock. Preserve split directions and proportions, stack order and active tabs, and manual floating overrides. Prune missing or moved windows, tile new windows normally, and fall back to spatial reconstruction when monitor work areas change. Retain pending snapshots if another lock interrupts startup. Ordinary disable clears the snapshot; no live window/actor references or disk persistence are retained.
Validation:
make packbuilds pass. Both packages contain the required files, have no forbidden extension-process Gdk imports, and meet the 10 MB size limit.Automated tests use lightweight GNOME boundary doubles. Multi-monitor hotplug and broader environment coverage remain unverified. This change is independent of #113.