A GNOME Shell extension that automatically moves maximized and fullscreen windows to empty workspaces, keeping your workflow organized without manual intervention. Includes per-application filtering and multi-monitor support.
- Automatic workspace isolation — Maximized and fullscreen windows move to empty workspaces, one window per space
- Configurable trigger behavior — Choose whether maximize, fullscreen, or both trigger workspace isolation via dropdown selector
- Override modifier key — Hold Alt/Super/Ctrl/Shift while maximizing/fullscreening to bypass ScreenToSpace and use GNOME's default behavior
- Flexible workspace placement — Insert new workspace after current (with restore to original) or use the last empty workspace
- Smart workspace reordering — Minimized disruption to existing window layout when creating or destroying isolated workspaces
- Focus preservation — Moved/restored windows automatically gain focus and raise to prevent being hidden behind other windows
- Multi-monitor aware — Respects GNOME's "workspaces on primary display only" setting; handles per-monitor workspace assignment correctly
- Blacklist mode (default) — Exclude specific apps from automatic workspace management (e.g., Telegram, WhatsApp, Brave)
- Whitelist mode — Only manage explicitly listed apps; all others remain in their current workspace
- Multi-select app chooser — Select multiple applications at once with search and checkbox UI
- Per-app granularity — Filter by desktop app ID with automatic normalization (strips
.desktopsuffix for matching)
Configure window behavior and filter mode:
View and manage blacklisted/whitelisted applications:
Select multiple apps at once with search:
Extension information and version details:
- GNOME Shell 49
- Standard GNOME Shell extension runtime (no additional dependencies)
git clone https://github.com/DilZhaan/ScreenToSpace.git
cd ScreenToSpaceCompile schemas and install:
glib-compile-schemas src/schemas
mkdir -p ~/.local/share/gnome-shell/extensions/screentospace@dilzhan.dev
rsync -av --delete src/ ~/.local/share/gnome-shell/extensions/screentospace@dilzhan.dev/Enable the extension:
gnome-extensions enable screentospace@dilzhan.devRestart GNOME Shell:
- X11:
Alt+F2, typer, press Enter - Wayland: Log out and back in
./scripts/makezip.sh
gnome-extensions install build/screentospace@dilzhan.dev.zip --force
gnome-extensions enable screentospace@dilzhan.devOpen preferences via GNOME Extensions app or:
gnome-extensions prefs screentospace@dilzhan.devWindow Behavior
- Behavior — Dropdown to choose trigger mode:
- Maximized — Only maximized windows trigger workspace isolation
- Full Screen — Only fullscreen windows trigger workspace isolation
- Both (default) — Both maximized and fullscreen windows trigger workspace isolation
- Override modifier — Choose a modifier key (None/Alt/Super/Ctrl/Shift) that, when held during maximize/fullscreen, bypasses ScreenToSpace and uses GNOME's default behavior
- Insert workspace after current — When enabled, places the new workspace immediately after the current one (instead of at the end) and restores windows back to their exact original workspace. When disabled, uses the last empty workspace with smart reordering
App Filtering
- Filter mode — Choose Blacklist (ignore listed apps) or Whitelist (manage only listed apps)
- Configured apps — Shows current app count; click through to App List tab to manage
Add Application (top section)
- Opens multi-select dialog with search bar
- Filter by app name or desktop ID
- Select multiple apps with checkboxes; click "Add Selected (N)" to confirm
Blacklisted/Whitelisted Apps (bottom section)
- Shows app icon, name, and desktop ID for each entry
- Remove button (circular trash icon) per app
- Empty state prompts to add apps using button above
Extension metadata: name, author, version, repository link
Placement (window enters maximized/fullscreen state):
- Extension detects size-change signal from window manager
- Check if override modifier is pressed; if so, bypass ScreenToSpace (GNOME default behavior)
WindowFilterchecks if window qualifies: normal window type, matches app filter rules, matches configured trigger behavior (maximize/fullscreen/both)WorkspaceManagerscans for empty workspace on the same monitorWindowPlacementHandlerplaces window using configured mode:- Insert after current mode: Takes the last completely empty workspace, reorders it to position after current workspace, moves only the isolated window there, stores reference to original workspace
- Reorder mode (default): Swaps empty workspace with current workspace, other windows stay in place, stores reference to home workspace
- Window is explicitly focused and raised to ensure visibility
Return (window exits maximized/fullscreen state):
- Extension detects size-change signal indicating unmaximize/unfullscreen
- Retrieve stored workspace reference (original/home workspace)
WindowPlacementHandlerrestores window using identity-based lookup:- If the stored workspace still exists (verified by object identity), move window back to it
- If the workspace was removed (dynamic workspaces), fall back to existing restore heuristic (last occupied / nearest workspace)
- Window is explicitly focused and raised to prevent being hidden behind other windows
- Workspace is activated so user follows the restored window
- App IDs are normalized: lowercased,
.desktopsuffix stripped - Window IDs resolved via
get_gtk_application_id(),get_wm_class_instance(), orget_wm_class()(first non-null match) - Blacklist mode: If app ID is in blacklist, skip workspace isolation (window stays in current workspace regardless of maximize/fullscreen)
- Whitelist mode: If whitelist is non-empty, only manage windows whose app ID is in the whitelist; all others are ignored
- Empty whitelist in whitelist mode = manage nothing (explicit opt-in required)
Respects GNOME's "Workspaces on primary display only" setting:
- Primary-only mode: Only the primary monitor's workspace changes trigger isolation; other monitors' windows are left alone
- All-monitors mode: Each monitor has independent workspace stacks; extension manages workspaces per-monitor (checks
window.get_monitor()and only scans workspaces for windows on that monitor)
Modular design following Single Responsibility Principle:
src/
├── extension.js # Entry point, signal wiring, lifecycle
├── constants.js # Centralized string literals and settings keys
├── eventHandler.js # Window manager signal dispatcher
├── windowFilter.js # Eligibility predicate (window type, app filter, state checks)
├── windowPlacement.js # Workspace reorder logic, window movement
├── workspaceManager.js # Workspace queries (find empty, find occupied)
├── prefs.js # Preferences UI (Adw, three-tab layout)
└── schemas/
└── org.gnome.shell.extensions.screentospace.gschema.xml
Key modules:
WindowFilter—isManagedWindow(window)combines type check + app filter logic;shouldPlaceOnSizeChange(window, change)checks maximize/fullscreen triggers independently; app ID normalization and blacklist/whitelist evaluation happen hereWindowPlacementHandler—placeWindowOnWorkspace(window),returnWindowToOldWorkspace(window)encapsulate workspace operations; supports both reorder mode and insert-after-current mode; stores workspace references for identity-based restore; handles focus/raise after movesWorkspaceManager—getFirstFreeWorkspace(manager, monitor),getLastOccupiedWorkspace(manager, currentIndex, monitor),getLastCompletelyEmptyWorkspace(manager)abstract workspace discoveryWindowEventHandler— Bridges window manager signals (map,size-change,minimize, etc.) to placement/filter logic; checks override modifier state; tracks pending actions betweensize-changeandsize-changedsignals
# Check status
gnome-extensions info screentospace@dilzhan.dev
# View logs
journalctl -f -o cat /usr/bin/gnome-shell | grep -i screentospace
# Reset settings
dconf reset -f /org/gnome/shell/extensions/screentospace/# Recompile schemas in installed extension
glib-compile-schemas ~/.local/share/gnome-shell/extensions/screentospace@dilzhan.dev/schemas/
# Restart GNOME Shell (X11: Alt+F2, r; Wayland: relog)- Verify extension is enabled:
gnome-extensions list | grep screentospace - Check "Behavior" dropdown is set correctly (not disabled for the window state you're testing)
- Ensure you're not holding the override modifier key while maximizing/fullscreening
- If using whitelist mode, ensure target app is in the whitelist
- Confirm GNOME dynamic workspaces are enabled (Settings → Multitasking → Workspaces)
- The extension matches against desktop app IDs (e.g.,
org.telegram.desktop,brave-browser) - IDs are normalized (lowercased,
.desktopstripped) - If an app doesn't have a desktop ID, it may not be filterable
- Check app's actual ID:
Gio.DesktopAppInfo.new('app-name.desktop').get_id()in Looking Glass (Alt+F2,lg)
git clone https://github.com/DilZhaan/ScreenToSpace.git
cd ScreenToSpace
# Compile schemas
glib-compile-schemas src/schemas
# Build zip
./scripts/makezip.sh
# Output: build/screentospace@dilzhan.dev.zip# Deploy to local extensions directory
rsync -av --delete src/ ~/.local/share/gnome-shell/extensions/screentospace@dilzhan.dev/
glib-compile-schemas ~/.local/share/gnome-shell/extensions/screentospace@dilzhan.dev/schemas/
# Restart GNOME Shell (X11)
# Alt+F2, r
# Watch logs
journalctl -f -o cat /usr/bin/gnome-shell- ES modules (
import/export) - 4-space indentation
- JSDoc for public methods
- Descriptive variable names (
currentWorkspace, notws) - No abbreviations in identifiers except standard ones (
appId,wm)
- All window manager signals wired in
extension.js:_connectSignals() - Settings keys defined in
constants.jsto avoid typos - App filtering entirely contained in
windowFilter.js:_isAppAllowed() - Preferences UI uses Adw (libadwaita widgets); three-page layout with
Adw.PreferencesPageinstances
GPL-2.0-or-later
Copyright (C) 2025 DilZhaan
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
Full license text: LICENSE
DilZhaan
GitHub: @DilZhaan
Repository: github.com/DilZhaan/ScreenToSpace
Support: buymeacoffee.com/dilzhan
v9 (2025-12-28)
- Behavior dropdown: Configure maximize/fullscreen triggers independently (Maximized, Full Screen, or Both)
- Override modifier: Hold Alt/Super/Ctrl/Shift while maximizing/fullscreening to bypass ScreenToSpace
- Insert workspace after current: Optional mode to place new workspace right after current (with restore to exact original workspace)
- Unified restore behavior: Always returns to original workspace if it exists, with fallback to last occupied/nearest
- Focus preservation: Moved/restored windows are explicitly focused and raised to prevent being hidden
- Identity-based workspace tracking: Robust handling of dynamic workspace removal
- One-time settings migration: Automatic upgrade from legacy single toggle to new separate triggers
v8 (2025-12-24)
- Added per-application blacklist/whitelist filtering
- Multi-select app chooser with search functionality
- Redesigned preferences UI (three-tab layout)
- App ID normalization for reliable matching
- Configurable filter mode (blacklist/whitelist toggle)
v7 (Previous)
- Initial public release
- Core workspace isolation functionality
- Multi-monitor support
- Maximize/fullscreen window handling
Note: This extension is developed and tested on Fedora/RHEL-based systems running GNOME Shell 49. Community contributions and bug reports welcome.



