3.3 KiB
Repository Guidelines
Purpose and scope
hypr-switcher provides macOS-style application switching and hiding on
Hyprland without compositor patches. Prefer stock Hyprland IPC operations over
changes to the Hyprland fork. A compositor change should only be considered
when the required operation cannot be expressed through the command or event
sockets.
Project structure
src/main.rs: daemon lifecycle, local command socket, switch sessions, GTK layer-shell HUD, and keyboard handling.src/ipc.rs: Hyprland command/event sockets and window operations.src/model.rs: client data, application grouping, address normalization, and focus history.src/desktop.rs: XDG desktop-file metadata and icon lookup.../hyprland.conf: source configuration integration. The live config may be deployed from another checkout; verify it before editing or reloading.
Add focused modules under src/ rather than allowing main.rs to absorb
unrelated parsing or model logic.
Behavioral invariants
- The process must remain a daemon. A one-shot switcher cannot retain a useful MRU history between invocations.
- Group applications exactly as
Client::app_keydoes: current class, then initial class, then title, then address. - Freeze normal MRU updates while a HUD session is active. Preview focus events must not mutate the ordering captured at the start of that session.
- Keep application and same-application window cycle lists stable for the duration of a cycle. Re-sorting after each preview causes two-window oscillation instead of traversal.
- A selected application raises all of its windows, with the MRU representative raised and focused last.
- The HUD owns an exclusive layer-shell keyboard grab. Release and hide it
before final focus, retaining the short delay in
Switcher::finish; removing that delay produces raised but unfocused windows. - Hidden applications live in
ipc::HIDDEN_WORKSPACE, are appended after visible applications, and are not unhidden merely by previewing them. Restore them only when the selection is committed. - Hidden state must remain discoverable from Hyprland client metadata after a daemon restart; do not make it depend solely on in-memory state.
Build and validation
Before handing off changes, run:
cargo fmt --check
cargo test
cargo clippy --workspace --all-targets -- -D warnings
cargo build --release
Install a tested build with:
cargo install --path . --root ~/.local --force
After installation, restart the existing daemon. For configuration changes,
validate and reload the actual active Hyprland config, then inspect live binds
and hyprctl configerrors.
For runtime testing, use a disposable window/class rather than moving or
hiding the user's real applications. Confirm layer presence through
hyprctl layers, focus through hyprctl activewindow, and hidden placement
through hyprctl clients.
Style and tests
Use Rust 2021 idioms and standard rustfmt. Keep IPC errors contextual and log
recoverable runtime failures without crashing the daemon. Add unit tests beside
pure parsing, grouping, and ordering logic. UI and compositor behavior require
proportional runtime checks in a live Hyprland session.
Preserve unrelated dirty changes in both configuration checkouts. Use
readlink -f ~/.config/hypr/hyprland.conf before assuming the workspace copy is
the active one.