aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
blob: d66216fad852fb153332297a3d182675cd59f200 (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
185
186
187
188
189
190
191
192
193
194
195
# wallp

A single-script wallpaper manager for a two-screen Wayland (sway / Hyprland)
setup. Sets and restores wallpapers per screen, drives a [pywal](https://github.com/dylanaraps/pywal)
color theme, and remembers what you had across reboots.

It replaces two older scripts — an interactive setter and a session restorer —
with one flag-driven program.

## Features

- **Two independent screens** — a horizontal (`H`) and a vertical (`V`) output,
  mapped to physical connectors in config.
- **Partial updates** — change one screen without disturbing the other. Each
  screen's `swaybg` process is tracked by PID and only the changed one is
  restarted (no full-screen blank flash).
- **GUI or CLI** — pick wallpapers through a [qarma](https://github.com/luebking/qarma)
  dialog, or pass file paths as arguments for scripted/headless use.
- **Session restore** — re-applies the last wallpapers (and last theme) at login,
  falling back to configured defaults on first run.
- **Theme persistence** — the last theme sticks until you change it; `--restore`
  brings it back, not the config default.
- **Self-bootstrapping config** — first run writes a template config and tells
  you to fill it in, without touching your wallpapers.

## Requirements

| Tool          | Required            | Purpose                              |
|---------------|---------------------|--------------------------------------|
| `bash`        | yes (≥ 4.4)         | the script itself                    |
| `swaybg`      | yes                 | paints the wallpaper on each output  |
| `wal` (pywal) | yes                 | generates/applies the color theme    |
| `qarma`       | only for GUI `--set`| screen-choice menu + file picker     |
| `notify-send` | optional            | desktop notification on theme change |
| `bats`        | dev only            | running the test suite               |

`wallp` checks for the required binaries at startup and exits with a clear
message if one is missing.

## Install

`wallp` is a standalone script — put it somewhere on your `PATH`:

```bash
cp wallp ~/bin/wallp
chmod +x ~/bin/wallp
```

> **Note:** this is a plain copy. If you later edit the script in the repo,
> re-copy it to `~/bin` for the change to take effect.

## Configuration

Config lives at `~/.config/wallp/wallp.conf`. On the very first run, if it
doesn't exist, `wallp` writes a template there and exits **without changing any
wallpaper** — edit it, then run again.

```ini
# ~/.config/wallp/wallp.conf

# Optional. Defaults to sexy-splurge if omitted.
THEME=sexy-splurge

# Physical output names. Find yours with:
#   swaymsg -t get_outputs      (sway)
#   hyprctl monitors            (Hyprland)
#   wlr-randr
OUTPUT_H=DP-1
OUTPUT_V=DP-3

# Used by --restore when there is no saved wallpaper yet.
# A leading ~ is expanded to your home directory.
DEFAULT_H=~/Pictures/wallpapers/SFW/horizontal.png
DEFAULT_V=~/Pictures/wallpapers/SFW/vertical.png
```

Format notes:

- Plain `key=value`, one per line. Blank lines and `#` comments are ignored.
- The file is **not** sourced as shell — it's parsed manually, so it can't run
  code.
- `OUTPUT_H`, `OUTPUT_V`, `DEFAULT_H`, `DEFAULT_V` are required. A missing or
  empty one is a hard error (named in the message). `THEME` is optional.

## Usage

```
wallp                      Show help
wallp --help | -h          Show help
wallp --set                Interactive selection (qarma): pick H / V / Both
wallp --set H=<file>       Set the horizontal screen only
wallp --set V=<file>       Set the vertical screen only
wallp --set H=<f> V=<f>    Set both screens
wallp --restore            Restore last session (defaults if none saved)
wallp --theme <name>       Override the theme (combine with --set or --restore)
```

### Examples

```bash
# Interactive: a menu asks which screen, then a file picker opens.
wallp --set

# Change only the vertical monitor; the horizontal one is untouched.
wallp --set V=~/Pictures/wallpapers/portrait.png

# Set both at once.
wallp --set H=~/pics/wide.jpg V=~/pics/tall.jpg

# Restore on login (defaults on first ever run).
wallp --restore

# Set a wallpaper and switch theme in one go; the theme persists afterwards.
wallp --set H=~/pics/wide.jpg --theme gruvbox
```

### Theme precedence

When resolving which theme to apply, `wallp` uses, in order:

1. `--theme <name>` on the command line,
2. the last persisted theme (`~/.config/wallp/theme`),
3. `THEME` from the config,
4. the built-in default `sexy-splurge`.

The resolved theme is always saved, so it carries across `--restore`.

### GUI vs CLI

`qarma` is used **only** to draw windows — the screen-choice menu, the file
picker, dialogs, and the help screen when a display is present. The actual
wallpaper is always set by `swaybg`, so the `H=`/`V=` argument forms work fine
without any display (e.g. from a startup script). `--restore` never needs a
display.

If you run `wallp --set` with no arguments and no Wayland display is available,
it errors and asks you to pass `H=`/`V=` instead.

## How it works

State is owned entirely by `wallp`:

| Path                          | Role                                            |
|-------------------------------|-------------------------------------------------|
| `~/.config/wallp/wallp.conf`  | configuration                                   |
| `~/.config/wallp/wall_h`      | persisted horizontal wallpaper path             |
| `~/.config/wallp/wall_v`      | persisted vertical wallpaper path               |
| `~/.config/wallp/theme`       | persisted theme name                            |
| `~/.cache/wallp/H.pid`        | PID of the horizontal `swaybg`                  |
| `~/.cache/wallp/V.pid`        | PID of the vertical `swaybg`                     |
| `~/.cache/wal/wpaper`         | symlink to the current horizontal image         |

Setting a screen: validate the file, kill **only** that screen's old `swaybg`,
launch a new one (`swaybg -o <output> -i <file> -m fill`), record the new PID,
and save the path. Then update the `wpaper` symlink and apply the theme via
`wal --backend colorz -nq --theme <name> -o ~/bin/wal.sh`.

Restoring: for each screen, use the saved path if present, otherwise the
configured default; apply it; then re-apply the resolved (persisted) theme.

The `~/.cache/wal/wpaper` symlink is kept because other tools (e.g. rofi themes)
read it.

## Integration with sway / Hyprland

Bind the interactive setter to a key and run a restore at startup. For Hyprland:

```ini
# autostart
exec-once = wallp --restore

# keybind
bind = $mainMod, Return, exec, wallp --set
```

(For sway, use `exec` / `bindsym` equivalents.)

## Development

The whole program is the single `wallp` file; functions are small and isolated
so they can be unit-tested. Tests use [bats](https://github.com/bats-core/bats-core):

```bash
bats tests/wallp.bats
```

The suite stubs `swaybg`, `wal`, `qarma`, and `notify-send` on `PATH` and runs
against a temporary `$HOME`, so it touches nothing real. Contributions should
follow TDD — add a failing test first.

Design notes and the implementation plan live under `docs/superpowers/`.

## License

Personal tooling; use as you like.