aboutsummaryrefslogtreecommitdiffstats

wallp

A single-script wallpaper manager for a two-screen Wayland (sway / Hyprland) setup. Sets and restores wallpapers per screen, drives a 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 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:

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.

# ~/.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

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

# 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, 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.