aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers/specs/2026-06-11-wallp-merge-design.md
blob: 5f23772f5e69143aeef92df47b20d24f361b51ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
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=<file>       # set horizontal only, no GUI
wallp --set V=<file>       # set vertical only, no GUI
wallp --set H=<f> V=<f>    # set both, no GUI
wallp --restore            # restore last session from persistent state
wallp --theme <name>       # 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=<file> and/or V=<file>". 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 <name>` → 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 `<X>.pid`; if the PID is alive, `kill` it. The other
   output's swaybg is left untouched.
3. `swaybg -o <OUTPUT> -i <file> -m fill &`; save the new PID to `<X>.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 <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=<file>` 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.