# Tiling WM Experience Spec This document describes the tiling window manager experience I am targeting. ## Priority Levels - Required: daily-driver behavior. - Important: expected for parity, but a rough first version is acceptable. - Nice: useful polish or compatibility. Priority describes the target experience, not implementation order. A first usable implementation may ship a smaller daily-driver subset as long as it does not choose designs that block required behavior later. ## Implementation Phases Phase 1 should establish the core daily-driver loop: - Global numbered workspaces across monitors. - Dynamic equal-width columns and tabbed/fullscreen-style layout. - Directional window focus, directional movement, and directional monitor focus. - Direct numbered workspace move/follow bindings. - Focus-follows-mouse and mouse-follows-focus. - Basic rofi launcher, terminal, close, reload, and session-exit bindings. - Basic status-bar workspace and focused-window state. Phase 2 should restore high-frequency workflow parity: - Per-monitor workspace history and history cycling. - Scratchpads. - Minimization. - Go-to-window, bring-window, and replace-window pickers. - Browser raise-or-spawn and class-aware gather workflows. - Status-bar window lists, class/title/icon metadata, and special-workspace filtering. Phase 3 should add visual discovery and polish: - Visual window overview. - Visual workspace expose. - Overview go/bring/replace actions. - Smart gaps, smart borders, dimming, wallpaper, lock, screenshot, clipboard, DDC/input switching, and other session utilities. ## Terms and Semantics - First-class operation means the action has a direct command or binding. It does not require opening a picker, manually moving focus, or chaining multiple unrelated commands. - Preserving useful focus means the operation leaves keyboard focus in a predictable place. Non-following moves keep focus on the source monitor or source workspace. Following moves focus the moved window on its destination. - Directional focus uses visible window geometry when windows have distinct rectangles. In tabbed or fullscreen-style layouts where geometry overlaps, directional focus may use a stable logical order instead, but repeated directional actions must cycle predictably through the windows. - Near-fullscreen scratchpads are centered floating windows large enough to dominate the current monitor without taking compositor fullscreen state. - Robust scratchpad behavior means toggling a named scratchpad finds or launches the intended app even when the app starts slowly, changes class or title after launch, is minimized, or is currently on another workspace. - Approximate window position means enough geometry or ordering information for status-bar window strips and expose-like previews. Pixel-perfect compositor geometry is useful but not required. - Normal workspaces are the bounded user-facing workspaces. Special, scratchpad, minimized, hidden, internal, and out-of-range workspaces are not normal workspaces. ## Modifier Terminology - `Super` names the physical modifier key often labeled Windows, Command, GUI, or OS depending on the keyboard. - `Hyper` means a higher-order logical modifier layer used for monitor, workspace, utility, and cross-context operations. - Prefer implementing `Hyper` as its own virtual modifier or equivalent logical mask when the environment supports that. - If a dedicated virtual `Hyper` mask is not practical, `Ctrl+Alt+Super` is the fallback chord. - The fallback `Hyper` chord intentionally does not include `Shift`; portable `Hyper` bindings only use the plain `Hyper` layer and the `Hyper+Shift` layer. - Do not require `Hyper+Ctrl`, `Hyper+Alt`, or `Hyper+Super` bindings. Those modifiers may already be part of the fallback `Hyper` chord. - Binding descriptions should use `Super` and `Hyper` rather than hardware-vendor names. ## Workspaces and Monitors Required behavior: - Workspaces are a shared global set, not independent per-monitor namespaces. - Focusing workspace `N` shows workspace `N` on the currently focused monitor. - Moving a window to workspace `N` does not require caring which monitor currently owns that workspace. - Sending the focused window to workspace `N` without following it is a first-class operation. - Moving the focused window to workspace `N` and following it is a first-class operation. - Sending the focused window to the next empty workspace without following it is a first-class operation. - Moving the focused window to the next empty workspace and following it is a first-class operation. - Normal workspaces are bounded to `1..9`. Important behavior: - Workspace history is tracked per monitor. - Last-workspace toggle uses the current monitor's workspace history. - Workspace history cycling works on the current monitor within the bounded workspace set. - Swapping the current workspace contents with another workspace is available. - Moving a window to an empty workspace on another monitor is available. - Moving the focused window to another monitor without following keeps keyboard focus on the original monitor. - Moving the focused window to another monitor and following it moves keyboard focus to the destination monitor. - Hidden/special workspaces exist for scratchpad state. - Hidden/special workspaces exist for minimized state. - Hidden/special workspaces are excluded from ordinary workspace cycling. - Hidden/special workspaces are excluded from the status bar's normal workspace list. ### Workspace History Cycling Important behavior: - The model is most-recently-used workspace switching, scoped to the monitor where the action starts. - Each monitor has its own ordered workspace history. The focused monitor's history is not shared with other monitors. - Only ordinary bounded workspaces are candidates. Special, scratchpad, minimized, hidden, and out-of-range workspaces are excluded. - Starting a cycle freezes the candidate list for that cycle. Previewing workspaces while the cycle is active must not rewrite the history order. - Starting a cycle previews the previous workspace for the current monitor. - Repeating the forward cycle action continues farther back through that monitor's frozen history. - A reverse cycle action moves through the same frozen history in the opposite direction. - Releasing the initiating modifier key commits the currently previewed workspace and updates history exactly once. - A cancel path may return to the workspace where the cycle started. This behavior is important for workflow continuity, but it is not a hard requirement for a minimal daily-driver window manager. ## Directional Navigation Required behavior: - Directional window focus is available. - Directional window swapping or movement is available. - Directional move-to-monitor is available while preserving useful focus. - Directional monitor focus is available. - Directional window movement between monitors is available. - Moving the focused window to an empty workspace on the monitor in a direction is available. - Directional bindings are defined in the Binding Appendix. Required directional actions must not depend on `Hyper+Ctrl`, because `Ctrl` may already be part of the fallback `Hyper` chord. Important behavior: - Keyboard resize remains available, but it should not displace the directional move-to-monitor binding. ## Pointer Focus Required behavior: - Focus-follows-mouse, or an equivalent pointer-driven focus model, is enabled. - Moving the pointer over a managed window focuses that window without requiring a click. - Mouse-follows-focus is also enabled: keyboard or programmatic focus changes move the pointer into the newly focused window. ## Layouts Required behavior: - Tiling is dynamic. - Primary layout is equal-width vertical columns. - Scrolling layouts are not acceptable. - All ordinary splits are vertical. - Adding windows dynamically redistributes all tiled windows evenly. - Newly tiled windows are inserted near the currently focused tile, not appended to the far end of the workspace. - Removing windows dynamically redistributes all tiled windows evenly. - Ordinary use should not require manually managing a split tree. - Tabbed/fullscreen-style monocle layout is available. - Directional window navigation bindings continue to switch windows in tabbed/fullscreen mode. - The important layouts are columns and tabbed/fullscreen. - Dialogs float. - Dialogs are centered. - There is a command to jump directly to the columns layout and one to jump directly to the tabbed/fullscreen layout. - `Super+Ctrl+Space` jumps directly to the tabbed/fullscreen layout. - Direct fullscreen or floating-fullscreen behavior should not have a keybinding. - Layout state is per workspace when the compositor supports it. Important behavior: - One-window workspaces should have no visible gaps or use smart gaps. Nice behavior: - Gaps can be toggled. - Smart borders can be toggled. - Layout-related modifiers remain available for experiments. - Inactive windows are slightly dimmed when supported. ## Overview and Discovery Required behavior: - There is a visual window overview for inspecting open windows before jumping. - There is a visual workspace expose for inspecting normal workspaces before jumping. - There is a rofi-style window picker. - Window picker entries show icons. - Window picker entries show titles. - Window picker entries show workspace labels. - Go-to-window focuses the selected window wherever it currently lives. - Bring-window moves a selected non-visible window to the current workspace and focuses it. - Replace-window swaps the focused window with a selected window where feasible. Important behavior: - Overview supports both "go" and "bring" workflows. - Window overview and workspace expose are distinct surfaces, because window selection and workspace selection are different navigation tasks. - Window overview supports directional keyboard selection with the same `w/a/s/d` spatial model as ordinary window focus. - Window overview supports direct go, bring, and replace-window actions from the selection UI. - Workspace expose shows bounded normal workspaces, including empty workspaces, with visible workspace numbers. - Workspace expose can be opened in a bring-window-oriented mode when supported. - Window switchers hide scratchpad windows unless the user is explicitly using a scratchpad picker. - Window switchers hide minimized windows unless the user is explicitly using a minimized picker. - Window switchers hide internal windows. - Go/bring actions unminimize selected windows when needed. - Selecting a minimized window or hidden scratchpad from the visual window overview recovers it onto the current workspace before focusing it. ## Scratchpads Required behavior: - A named scratchpad exists for codex. - A named scratchpad exists for element. - A named scratchpad exists for htop. - A named scratchpad exists for slack. - A named scratchpad exists for spotify. - A named scratchpad exists for T3 Code. - A named scratchpad exists for volume. - A named scratchpad exists for x.com. - Scratchpads appear near-fullscreen and centered by default. - Floating scratchpad behavior is a state of a window, not a property of its application class. Floating any window at scratchpad geometry enters that state; tiling it leaves that state. - Invoking a scratchpad replaces only another window currently in floating scratchpad mode. Other floating windows are left alone. - Regular scratchpad targets can be tiled into the normal workspace when desired, while retaining their shortcut association. - Summoning a scratchpad target with its shortcut always restores floating scratchpad mode, even if the window was previously tiled. - Toggling a scratchpad deactivates fullscreen/tabbed state first. - Floating scratchpads are hidden from normal workspace and window listings. Important behavior: - A dropdown terminal scratchpad exists. - Scratchpad matching handles delayed class/title assignment. - Scratchpad behavior is robust when the app is already running. - Scratchpad behavior is robust when the app is minimized. - Scratchpad behavior is robust when the app is on another workspace. ## Minimization Required behavior: - Focused window can be minimized. - Last minimized window can be restored to the current workspace and focused. - Minimized windows are excluded from normal layout. - Minimized windows are excluded from ordinary go/bring lists. Important behavior: - A minimized picker mode exists. - Restore-all-minimized exists. - Other classes in the current workspace can be minimized. - Windows of the focused class can be restored. - All minimized windows can be restored. ## Class-Aware Workflows Important behavior: - Gather all windows of the focused class onto the current workspace. - Raise-or-spawn exists for the browser. - Window menus show class. - Window menus show title. - Window menus show workspace. - Window menus show icon. ## Status Bar Contract Required behavior: - The status bar can list normal workspaces. - The status bar can identify the active workspace per monitor. - The status bar can list windows per workspace. - The status bar can expose class hints for each listed window. - The status bar can expose title for each listed window. - The status bar can expose active state for each listed window. - The status bar can expose minimized state when available. - The status bar can expose urgency when available. - The status bar can expose approximate window position when available. - Scratchpad workspaces are marked as special or filtered out. - Minimized workspaces are marked as special or filtered out. - Internal workspaces are marked as special or filtered out. Important behavior: - Workspace labels are stable. - Workspace icons are stable. - Window positioning information is available enough for workspace icon strips and future expose-like views. - Layout information is available enough for workspace icon strips and future expose-like views. - Layout name is exposed if practical. - Layout state is exposed if practical. ## Session and Utility Behavior Important behavior: - Terminal is `ghostty --gtk-single-instance=false`. - Launcher is `rofi -show drun -show-icons`. - Run menu is `rofi -show run`. - Browser raise/spawn behavior exists. - Border width is effectively zero. - The status bar can be toggled per monitor. - Session startup integrates with the normal graphical-session target. - Session startup integrates with any required session-specific user target. Nice behavior: - Wallpaper behavior remains consistent. - Wallpaper selection uses `Hyper+comma`; `Hyper+w/a/s/d` are reserved for directional monitor focus. - Idle behavior remains consistent. - Lock behavior remains consistent. - Clipboard history behavior remains consistent. - Screenshot behavior remains consistent. - Monitor DDC/input switching remains consistent. - Rofi utility bindings remain consistent. - Media keys remain consistent. ## Binding Appendix Required behavior: - `Hyper` bindings should remain available from a single physical key where practical, even if that key emits the fallback chord internally. - Extra modifiers on `Hyper` are limited to `Shift` for portable bindings. Important behavior: - `Hyper` utility bindings must not displace required directional monitor bindings on `Hyper+w/a/s/d`. ### Core Bindings Required behavior: - `Super+p` opens the application launcher. - `Super+Shift+p` opens the run menu. - `Super+Shift+Return` opens a terminal. - `Super+q` reloads the window manager config. - `Super+Shift+c` closes the focused window. - `Super+Shift+q` exits the window manager session. - `Super+x` opens the command picker with `rofi_command.sh`. - `Super+g` opens the go-to-window picker. - `Super+b` opens the bring-window picker. - `Super+Shift+b` opens the replace-window picker. - `Super+Shift+e` moves the focused window to the next empty workspace and follows it. - `Hyper+e` focuses the next empty workspace. - `Hyper+1` toggles inactive-window opacity reduction for the focused window. - `Hyper+5` swaps the current workspace with a selected workspace. - `Hyper+g` gathers windows of the focused class onto the current workspace. Important behavior: - `Super+Tab` opens the visual window overview. - `Super+Shift+Tab` opens the visual window overview scoped to non-visible windows or bring-window mode when supported. - `Alt+Tab` opens the visual workspace expose. - `Alt+Shift+Tab` opens the visual workspace expose in bring-window mode when supported. - Within visual window overview, `w/a/s/d`, `h/j/k/l`, and arrow keys move the selection directionally. - Within visual window overview, `Return`, `Space`, `g`, or `f` activates the selected window. - Within visual window overview, `b`, `Shift+Return`, or `Shift+Space` brings the selected window to the current workspace. - Within visual window overview, `Shift+b` replaces the focused window with the selected window when supported. - Within visual window overview, `Escape` or `q` closes the overview. - `Super+\` starts or advances current-monitor workspace history cycling. - `Super+/` reverses current-monitor workspace history cycling while the initiating `Super` key is held. - Releasing the initiating `Super` key commits the workspace history cycle. ### Directional Navigation Bindings Required behavior: - `Super+w/a/s/d` focuses windows directionally. - `Super+Shift+w/a/s/d` swaps or moves the focused window directionally. - `Super+Ctrl+w/a/s/d` moves the focused window to the monitor in that direction while preserving useful focus. - `Super+Ctrl+Shift+w/a/s/d` moves the focused window to an empty workspace on the monitor in that direction. - `Hyper+w/a/s/d` focuses monitors directionally. - `Hyper+Shift+w/a/s/d` swaps or moves windows between monitors directionally. - `Super+z` focuses the next monitor. - `Super+Shift+z` moves the focused window to the next monitor. ### Numbered Workspace Bindings Required behavior: - `Super+1..9` focuses workspace `1..9` on the current monitor. - `Super+Shift+1..9` sends the focused window to workspace `1..9` without following it. - `Super+Ctrl+1..9` sends the focused window to workspace `1..9` and follows it. ### Scratchpad Bindings Required behavior: - `Super+Alt+c` toggles the primary AI scratchpad. - `Super+Alt+Shift+c` toggles the backup AI scratchpad. - `Super+Alt+e` toggles the element scratchpad. - `Super+Alt+h` toggles the htop scratchpad. - `Super+Alt+k` toggles the slack scratchpad. - `Super+Alt+s` toggles the spotify scratchpad. - `Super+Alt+t` toggles the T3 Code scratchpad. - `Super+Alt+v` toggles the volume scratchpad. - `Super+Alt+x` toggles the x.com scratchpad. Important behavior: - `Super+Alt+grave` toggles the dropdown terminal scratchpad. - `Super+Alt+Return` enters the minimized-window picker or restores minimized windows, depending on environment support. - `Super+Alt` is reserved for app-specific raise/spawn, scratchpad, and scratchpad-adjacent bindings. ### Utility Bindings Required behavior: - `Hyper+v` opens clipboard history with a rofi-backed clipboard command such as `greenclip print` or `cliphist`. - `Hyper+p` opens the password picker with `rofi-pass`. - `Hyper+h` opens the screenshot tool with the compositor/session-appropriate screenshot command. - `Hyper+n` opens a Codex Desktop project picker and starts a new thread in the selected saved project root. - `Hyper+c` opens the Codex launcher with `rofi_tmcodex.sh`. - `Hyper+Shift+c` opens the Codex launcher with `tmcodex resume`. - `Hyper+k` opens the process killer with `rofi_kill_process.sh`. - `Hyper+Shift+k` opens the kill-all/process-tree killer with `rofi_kill_all.sh`. - `Hyper+r` opens the systemd/service menu with `rofi-systemd`. - `Hyper+slash` toggles the status bar with the status-bar-appropriate command. - `Hyper+backslash` toggles the monitor input with `mpg341cx_input toggle`. - `Hyper+i` opens the audio input selector with `rofi_select_input.hs`. - `Hyper+o` opens the audio output selector with `rofi_paswitch`. - `Hyper+y` opens the agentic skill picker with `rofi_agentic_skill`. - `Hyper+Shift+l` locks the session with the compositor/session-appropriate locker. Important behavior: - Wallpaper selection is available under `Hyper` via `rofi_wallpaper.sh`, but its exact key must avoid the required `Hyper+w/a/s/d` directional monitor bindings. - Expose-style overview remains available as a utility binding using the compositor-appropriate implementation. - Session-destructive operations use shifted or otherwise harder-to-hit variants. ## Migration Notes - `Super+Shift+e` is the target replacement for the older `Super+Shift+h` move-to-next-empty-workspace-and-follow binding.