Files

3.4 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.
  • flake.nix: standalone Nix package, app, checks, and development shell.
  • ../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_key does: 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
nix flake check

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.