From e6d57f1b6968ae4a1066ee4f1797582152f4ad08 Mon Sep 17 00:00:00 2001 From: danix Date: Thu, 11 Jun 2026 09:16:02 +0200 Subject: docs: wallp merge design spec Co-Authored-By: Claude Opus 4.8 --- .../specs/2026-06-11-wallp-merge-design.md | 184 +++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 docs/superpowers/specs/2026-06-11-wallp-merge-design.md (limited to 'docs/superpowers') diff --git a/docs/superpowers/specs/2026-06-11-wallp-merge-design.md b/docs/superpowers/specs/2026-06-11-wallp-merge-design.md new file mode 100644 index 0000000..5f23772 --- /dev/null +++ b/docs/superpowers/specs/2026-06-11-wallp-merge-design.md @@ -0,0 +1,184 @@ +# wallp — Unified Wallpaper Manager — Design + +Date: 2026-06-11 + +## Overview + +Single bash script `wallp` replacing two scripts: + +- `multiwal.sh` — interactive wallpaper setter (qarma picker, two screens). +- `qar-lastwall.sh` — restores last-session wallpapers at session start. + +Command-line flags pick the action. qarma is used **only** for GUI (file picker, +selection menu, dialogs, help). `swaybg` actually sets wallpapers and needs no +qarma. Per-output PID tracking allows updating a single screen without blanking +the other (the old `pkill swaybg` killed both). A config file holds defaults; +flags override where applicable. + +Two-screen setup: + +- Horizontal screen — logical `H`, physical output from conf `OUTPUT_H` (e.g. `DP-1`). +- Vertical screen — logical `V`, physical output from conf `OUTPUT_V` (e.g. `DP-3`). + +## CLI + +``` +wallp # help screen +wallp --help / -h # help screen +wallp --set # qarma picker: menu H/V/Both -> file picker(s) +wallp --set H= # set horizontal only, no GUI +wallp --set V= # set vertical only, no GUI +wallp --set H= V= # set both, no GUI +wallp --restore # restore last session from persistent state +wallp --theme # override conf theme (combine with --set/--restore) +``` + +Rules: + +- Bare invocation or `--help`/`-h` → help screen. Shown in a qarma window when + `$WAYLAND_DISPLAY` is set, otherwise printed to stdout. +- `--set` with no `H=`/`V=` args: + - `$WAYLAND_DISPLAY` set → qarma selection flow. + - no display → error: "no display: pass H= and/or V=". Exit non-zero. +- `--set` with `H=`/`V=` args → set those outputs directly, no GUI (works + headless; swaybg does not need qarma). +- `--restore` → no display required (intended for session-start autostart). +- `--theme ` → overrides conf `THEME` for this invocation. +- Unknown flag → error message + help, exit non-zero. + +Logical `H=`/`V=` keys map to physical `OUTPUT_H`/`OUTPUT_V` from conf, so output +renames only touch the conf, not command lines or muscle memory. + +## Config — `~/.config/wallp/wallp.conf` + +Format: simple `key=value`, one per line. Parsed manually (no shell sourcing — +avoids code execution from the conf). Blank lines and lines starting with `#` +ignored. Leading `~` in path values expanded to `$HOME`. + +Keys: + +``` +THEME=sexy-splurge +OUTPUT_H=DP-1 +OUTPUT_V=DP-3 +DEFAULT_H=/home/danix/Pictures/wallpapers/SFW/wallhaven-4yd27g_2560x1080.png +DEFAULT_V=/home/danix/Pictures/wallpapers/SFW/wallhaven-gwzqjl_2560x1080.png +``` + +Behavior: + +- **Conf file missing** → write a commented template to the conf path, tell the + user (stdout + notify-send if available) to fill it in and re-run, then + **exit 0 without touching any wallpaper**. Applies to every action. +- **Conf present, required path/output key missing or empty** → hard error + naming the missing key, exit non-zero, no wallpaper change. Required keys: + `OUTPUT_H`, `OUTPUT_V`, `DEFAULT_H`, `DEFAULT_V`. +- **THEME** is the one exception: if absent, built-in fallback `sexy-splurge` + is used. `--theme` flag also overrides it. + +An example conf is shipped in the repo (`wallp.conf.example`). + +## State Files + +Runtime pointers (volatile, in `~/.cache`, reset on reboot): + +- `~/.cache/wal/wal` — H wallpaper path. Read by pywal and apps. +- `~/.cache/wal/wal2` — V wallpaper path. +- `~/.cache/wal/wpaper` — symlink to current H image (maintained by wallp). + +Persistent pointers (survive reboot, in `~/.config`): + +- `~/.config/wal/wal` — H wallpaper path. +- `~/.config/wal/wal2` — V wallpaper path. + +PID tracking (runtime only, meaningless after reboot): + +- `~/.cache/wallp/H.pid` — swaybg PID for horizontal output. +- `~/.cache/wallp/V.pid` — swaybg PID for vertical output. + +wallp writes **all** pointer files directly (cache + config) on set and restore. +This moves persistence out of `wal.sh` and into wallp. `wal.sh` is reduced to its +theme-app glue only (dunst symlink+restart, kitty symlink); it loses the +wal/wal2/wpaper copy logic. `wal.sh` remains the wal `-o` hook for future use. + +## Set Flow + +For each chosen output (H and/or V): + +1. Resolve the file path (from qarma picker or `H=`/`V=` arg). Validate it + exists; if not, error and skip that output (do not blank it). +2. Selective kill: read `.pid`; if the PID is alive, `kill` it. The other + output's swaybg is left untouched. +3. `swaybg -o -i -m fill &`; save the new PID to `.pid`. +4. Write the pointer to cache (`wal`/`wal2`) and config (`wal`/`wal2`). + +After all chosen outputs are done: + +5. Update `~/.cache/wal/wpaper` symlink → current H image. +6. Run `wal --backend colorz -nq --theme -o ~/bin/wal.sh`. +7. `notify-send` color-theme update. + +qarma selection flow (`--set`, display present, no args): + +- qarma list/menu: choose `H` / `V` / `Both` (no initial yes/no confirmation). +- File picker per chosen output: `qarma --file-selection --preview-images 500 + --width 1300 --height 600` with a per-output title. +- Picker cancelled → skip that output (no error). + +## Restore Flow (`--restore`) + +For each output H/V: + +1. If the persistent pointer (`~/.config/wal/wal` for H, `wal2` for V) exists → + read the path, selective-kill that output's old PID, `swaybg`, save PID, and + sync the pointer to `~/.cache/wal/`. +2. If no persistent pointer for that output → use `DEFAULT_H`/`DEFAULT_V` from + conf, write both pointers (cache + config), swaybg, save PID. + +After both outputs: + +3. Update `wpaper` symlink → H image. +4. Run wal theme + notify (same as set steps 6-7). + +No display required. Replaces `qar-lastwall.sh`. Intended for session-start +autostart. + +## Error Handling + +- Missing/invalid file for an output → error, skip that output, do not blank it. +- qarma cancel → skip output, no error. +- Dead or missing PID file → start fresh swaybg, no kill attempt. +- GUI needed but no display → clear error, exit non-zero. +- Required binary missing (`swaybg`, `wal`, `qarma` when GUI needed, + `notify-send` optional) → checked at start; error and exit if a required one + is absent. `notify-send` treated as optional (skip notification if absent). +- Conf missing → generate template, instruct user, exit 0, no change. +- Required conf key missing → hard error, exit non-zero, no change. + +## Testing + +The script is side-effecting (swaybg, wal, filesystem). Strategy: + +- Factor pure logic into functions: conf parsing, arg parsing, `~` expansion, + logical→physical output mapping, file-existence validation. +- Test with bats (or a stub harness): place fake `swaybg`, `wal`, `qarma`, + `notify-send` as executable stubs on `PATH` in a temp dir; point `HOME` at a + temp dir. +- Assertions: + - Conf-missing path generates the template and changes no wallpaper. + - Missing required key hard-errors. + - `--set V=` writes V pointers (cache + config) and leaves `H.pid` + untouched (partial update does not blank H). + - Selective kill targets only the changed output's PID. + - Restore falls back to `DEFAULT_*` when no persistent pointer exists. + - `~` in conf paths expands to `$HOME`. +- Manual smoke test on the real two-screen setup. + +## Migration Notes + +- `wal.sh` lines 16-27 (wal/wal2/wpaper copy + symlink) move into wallp; remove + them from `wal.sh`, keep dunst + kitty glue. +- Old `qar-lastwall.sh` read `~/.config/wal/*`; old `multiwal.sh` wrote + `~/.cache/wal/*` — this mismatch bug is resolved: wallp writes both. +- Old default-wallpaper paths had a literal quoted `~` (swaybg would not expand) + — fixed via `~`→`$HOME` expansion on conf load. -- cgit v1.2.3