aboutsummaryrefslogtreecommitdiffstats

wallp

A single-script wallpaper manager for a two-screen Wayland (sway / Hyprland) setup. Sets and restores wallpapers per screen, refreshes the desktop accent colour to match, 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 dialog, or pass file paths as arguments for scripted/headless use.
  • Session restore — re-applies the last wallpapers at login, falling back to configured defaults on first run.
  • Unified desktop theme — after every change wallp hands the new wallpaper to udt-accent, which owns the whole palette (rofi, Hyprland, Firefox, quickshell, Sublime). wallp itself no longer runs pywal or stores a theme.
  • 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
udt-accent optional refreshes the desktop accent colour
qarma only for GUI --set screen-choice menu + file picker
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. udt-accent is looked up at run time: if it is absent, or it fails, the wallpaper is still set and only the accent refresh is skipped.

Install

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

ln -s "$PWD/wallp" ~/bin/wallp

A symlink keeps the installed command in step with the checkout, so edits take effect at once. A plain cp wallp ~/bin/wallp && chmod +x ~/bin/wallp works too, but then every repo edit needs a re-copy.

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.

# ~/.config/wallp/wallp.conf

# 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 all required. A missing or empty one is a hard error (named in the message).

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)

Examples

# 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

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
~/.cache/wallp/H.pid PID of the horizontal swaybg
~/.cache/wallp/V.pid PID of the vertical swaybg
~/.cache/udt/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 ~/.cache/udt/wpaper symlink and run udt-accent ~/.cache/udt/wpaper to re-derive the desktop accent colour.

Restoring: for each screen, use the saved path if present, otherwise the configured default; apply it; then refresh the accent the same way.

The wpaper symlink is the hand-off point to the rest of the theme: other tools (rofi, udt-accent) read it rather than wallp's own state.

Integration with sway / Hyprland

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

# 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:

bats tests/wallp.bats

The suite stubs swaybg, udt-accent, 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.