Deja Window is a GNOME Shell extension that gives you full control over your window geometry. It automatically restores the workspace, size, position, minimized and maximized state, always on top and always on visible workspace of specific applications when they open. 🤔 Why Deja Window? In "vanilla" GNOME, windows typically open in the current workspace either centered or in a upper-left layout. Deja Window bridges this gap by acting as an external memory for your window layout, forcing the desired position, size and states that the OS or the apps themselves cannot natively restore. Deja Window is also very useful for all those applications (such as Ghostty) that do not adequately manage the layout of their windows in Gnome. 🚀 Features - Remembers the last known position, size (included workspace) and states (minimized and maximized, always on top and always on visible workspace) of your windows. - Configure specific rules per window (via WM_CLASS or Window Title). - Supports standard string matching and regular expressions (Regex) for advanced targeting. - Choose to restore workspace, size, position, minimized and maximized state, always on top and always on visible workspace, independently for each app. - Automatically detects and restores windows to the exact monitor they were previously saved on. - Freeze a window's saved layout to maintain your perfect configuration, preventing accidental updates when temporarily moving or resizing windows. - Automatically centers windows that are configured but haven't been saved yet. - Handles the specific timing constraints of window management on Wayland. - Optional Global Defaults ruleset (experimental) to manage every window that has no rule of its own, with its own restore options and an exclude list matched by class, title or regex. - Right-click a window's title bar for a "Deja Window" submenu: a full rule editor to manage it by class or title, toggle every restore option, lock it, save its current state instantly, exclude it, or jump straight to its rule in Preferences. - Turn a rule off without deleting it, from Preferences or from the window menu — its customization is kept and restored when you turn it back on. - Back up and restore your application rules and Global Defaults configuration. - Optional top bar indicator for quick access to Preferences and to pause/resume window tracking without disabling the extension. Compatibility Note: While this extension works with the majority of standard applications, some apps utilize custom layout mechanisms or non-standard toolkits that may override or ignore the extension's positioning attempts. More troubleshooting info can be found in the README.md file on GitHub.
Note: Binary files aren't shown on the web site. To see all files, please download the extension zipfile.
| Version | Status |
|---|---|
| 16 | Active |
| 15 | Active |
| 14 | Rejected |
| 13 | Inactive |
| 12 | Rejected |
| 11 | Inactive |
| 10 | Inactive |
| 9 | Inactive |
| 8 | Rejected |
| 7 | Inactive |
| 6 | Rejected |
| 5 | Rejected |
| 4 | Inactive |
| 3 | Rejected |
| 2 | Inactive |
| 1 | Rejected |
What's the reason for that disable comment? Your extension isn't going to run on lock.
You're right that the extension doesn't run while the session is locked — that's exactly the reason for that line, rather than an attempt to work around it. A lock/unlock is a full disable()/enable() cycle, so enable() runs again on unlock, and at that point it has no way to tell an unlock apart from a normal extension reload. The distinction matters: on a reload, the walk over the already-open windows is what re-adopts and restores them (that's the whole purpose of the walk), while on an unlock those same windows are still on screen and already where the user left them. Restoring them there re-applies maximized and workspace state, and since Mutter's make_above()/unmake_above() both end in meta_window_raise(), it also yanks the app to the front of the stack, which is the bug this commit fixes: a user's terminal jumping to the front after every unlock. disable() is the last moment where that reason is still observable, so it only reads Main.sessionMode.currentMode and stores a single boolean on the extension object. Nothing is connected, scheduled or kept alive while locked: disable() tears down every signal and GLib source exactly as before, and the next enable() uses that boolean only to re-track the still-open windows without re-placing them. If the comment reads as if the extension intends to do something during the lock, I'm happy to reword it (or to use Main.sessionMode.isLocked instead of the mode-name comparison, if that's clearer). Just let me know.