438 lines
17 KiB
Markdown
438 lines
17 KiB
Markdown
# 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.
|
|
|
|
## 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
|
|
remains required behavior, but it should not require an extra `Hyper`
|
|
modifier beyond `Shift`.
|
|
- `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.
|
|
- Directional focus in tabbed/fullscreen mode should cycle predictably through
|
|
windows even though their screen geometry overlaps.
|
|
|
|
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.
|
|
|
|
## 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 transmission.
|
|
- A named scratchpad exists for volume.
|
|
- Scratchpads appear near-fullscreen and centered by default.
|
|
- Toggling a scratchpad deactivates fullscreen/tabbed state first.
|
|
- 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. This is the target replacement for the older `Super+Shift+h`
|
|
binding.
|
|
- `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.
|
|
- `Hyper+w/a/s/d` focuses monitors directionally.
|
|
- `Hyper+Shift+w/a/s/d` swaps or moves windows between monitors directionally.
|
|
- Moving the focused window to an empty workspace on the monitor in a direction
|
|
remains required behavior, but it should not require a `Hyper+Ctrl` binding.
|
|
- `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 codex 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 transmission scratchpad.
|
|
- `Super+Alt+v` toggles the volume 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+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.
|