scootbg overview
The lightest wallpaper daemon for Wayland, in place of swaybg,
hyprpaper, wpaperd and friends. It shows a color or an image on
each output, and one command changes it. Built for scoot and set up by
scoot’s own config, but not tied to it: scootbg speaks only standard
protocols, so it also runs on any compositor with
wlr-layer-shell-v1.
scootbg set '#1e1e2e' # every output, including ones plugged in laterscootbg set ~/Pictures/hills.jpg # an image, covering every outputscootbg set ~/Pictures/hills.jpg --output DP-2 --mode fitscootbg clear # back to the compositor's own backgroundscootbg query # each output and what it shows, one JSON lineThe [wallpaper] section
Section titled “The [wallpaper] section”In scoot, a [wallpaper] section runs all of this for you: scoot
starts scootbg itself and re-applies the section on every reload, with
no [autostart] entry and no session script. Leave
scootbg daemon out of [autostart] and your session script when you
use this section (apply-config starts the daemon; a second start is
harmless but flashes the wrong profile’s wallpaper for a moment).
[wallpaper]image = "~/Pictures/hills.jpg" # or: color = "#1e1e2e"mode = "fill" # fill | fit | stretch | center | tile
[wallpaper.output."DP-2"] # optional, one table per outputcolor = "#101014"A link works where a path does: image = "https://example.com/hills.jpg"
is downloaded once and cached by scootbg, so an example look can name
an image nobody commits. sha256 pins the download’s bytes.
| Field | Type | Reload | Meaning |
|---|---|---|---|
image |
string (path or URL) | live (re-applied) | A PNG, JPEG or WebP image. A path: ~ expands against HOME, a relative path resolves against the config file’s directory. A URL (http:///https://): downloaded once and cached — see Wallpaper from a link. |
color |
string ("#rrggbb") |
live (re-applied) | A solid color. image or color, never both; neither is nothing (the compositor’s own background_color). |
mode |
string | live | With an image only: fill (cover and crop), fit (letterbox with fill), stretch, center, tile. |
fill |
string ("#rrggbb") |
live | With an image only: the color around a fit or center image. |
filter |
string | live | With an image only: lanczos3, catmull-rom, bilinear or nearest. |
sha256 |
string (64 hex digits) | live (re-downloads) | With a URL image only: the download’s expected SHA-256. Anything else fails instead of showing. Refused beside a path. |
output."NAME" |
table | live | The same keys for one output, by connector name (as scootbg query lists them). Each output table stands alone: an output’s image does not take the top level’s mode. An empty table is nothing on that output. |
command |
string | live | The scootbg to run. Default "scootbg" on PATH; the Nix modules set it to the installed package’s store path. |
Whichever you changed last wins. Edit [wallpaper] (and start or
reload scoot): the config’s wallpaper shows. Run scootbg set after
that: your pick shows, and keeps showing across restarts and unrelated
reloads, until you next change [wallpaper] itself.
When it fails, the session carries on with its background_color:
scootbg not installed (a warning naming the command; the next reload
tries again), a failed run (exit status in the log), or a section with
a problem (unknown key, wrong type — the rest of the file still
applies, unlike other tables). Until scootbg’s first frame, scoot
shows its background_color.
What it costs
Section titled “What it costs”On a compositor with wp_single_pixel_buffer_manager_v1 and
wp_viewporter (scoot, sway, and most others) a color costs no shared
memory at all: one single-pixel buffer scaled to the output. Without
single-pixel buffers it is a 1×1 wl_shm buffer under the viewport, and
without a viewporter a full-size buffer. A static color asks for no frame
callbacks and wakes the daemon for nothing.
Once on screen a wallpaper costs no CPU (no wakeups in a minute, measured)
and one buffer per output at most: about 4.0 MB RSS with a color, 36.8 MB
with an image on a 4K output, and the same 36.8 MB with two 4K outputs
showing it. The measured budget is in
README.md,
and so is the comparison
with swaybg, awww, wbg and wpaperd on one machine. It is not yet the
lightest on every row: awww holds 1.0–1.6 MiB less idle memory above the
output buffers. scripts/scootbg-bench/bench.py re-runs the comparison.
The daemon and its socket
Section titled “The daemon and its socket”One daemon per display: its socket is
$XDG_RUNTIME_DIR/scootbg-NAME.sock, NAME being the last component of
$WAYLAND_DISPLAY. A second scootbg daemon refuses while one runs, and
a socket left by a dead one is replaced. It exits 0 on kill and 1 when
the compositor goes away, removing its socket either way. A signal
(SIGTERM, Ctrl-C) ends it on the spot and leaves the socket file; the other
commands then say no daemon is running (exit 1), and the next
scootbg daemon replaces the file. Every command exits 2 on a usage
error (an unknown command or argument, or a bad --profile name).