breadpaper/EVENTS.md
Breadway 1efc721990
All checks were successful
check / check (push) Successful in 2m28s
dev release / build (push) Successful in 49s
Add GTK wallpaper library
Scan ~/Pictures/Wallpapers and /usr/share/backgrounds/bos (configurable)
and open a bread-theme GTK picker via `breadpaper library` (alias browse).
Clicking a thumbnail runs the existing set path. listen honors
bread.command.paper.library by spawning that picker.
2026-08-16 00:26:50 +08:00

4.1 KiB

breadpaper — bread event integration

breadpaper is a wallpaper setter: it works exactly the same with or without breadd running. When breadd is present, a successful breadpaper set (or the bare-path shorthand) publishes bread.paper.changed into the shared bread automation fabric, and breadpaper listen honors bread.command.paper.set and bread.command.paper.library. See the parent bread repo's Documentation.md — specifically its "Namespaces" and "Integrating a bread* app" sections — for the general convention this follows.

App id: paper. Transport: bread-utils's bread_client module (feature bread-client) — the CLI links it directly. One-shot set/get use BreadClient::connect("paper") + emit only. The long-running listen subcommand holds a subscribe open.

breadpaper listen is fail-silent if breadd is down: subscribe reconnects with backoff and simply delivers nothing until the daemon comes back. The one-shot set/get/library path does not require listen. Modules that want to change the wallpaper without a listener can still shell out:

bread.exec("breadpaper set /path/to/image.png")

A workflow that publishes the command instead should wait for the confirmation, not assume the emit finished the set:

bread.emit("bread.command.paper.set", { path = "/path/to/image.png" })
bread.wait("bread.paper.set.done", { timeout = 10000 })

Events published (bread.paper.*)

Event Data When
bread.paper.changed { "path": "<wallpaper>" } After a successful set (awww + wal + bread-theme reload), including when listen honors bread.command.paper.set. path is the canonical absolute path that was applied. Not emitted on get, and not emitted if any of the three steps fail.
bread.paper.set.done { "path": "<wallpaper>" } bread.command.paper.set was received and set() succeeded. path is the canonical absolute path that was applied. Not emitted by the one-shot CLI set — that path only publishes changed.
bread.paper.set.failed { "error": "<message>", "path"?: "<requested>" } bread.command.paper.set was received but set() failed, or data.path was missing/not a string. path is the requested (not canonical) path when one was supplied.
bread.paper.library.done {} bread.command.paper.library was received and a breadpaper library process was started. Not emitted by the one-shot CLI library / browse.
bread.paper.library.failed { "error": "<message>" } bread.command.paper.library was received but the library process could not be spawned.

Commands honored (bread.command.paper.*)

Honored only while breadpaper listen is running. A bread-emit bread.command.paper.set with no listener is a silent no-op — that is the documented bread convention, not a breadpaper bug.

Verb Data Effect
set { "path": "..." } Calls the existing set() (awww + wal + bread-theme reload). Emits bread.paper.set.done / .failed. A successful set also emits bread.paper.changed.
library {} Spawns breadpaper library (GTK picker). Emits bread.paper.library.done once the process is started, or bread.paper.library.failed if the spawn fails. Clicking a thumbnail in that window is a normal set and publishes bread.paper.changed.

Not implemented: slideshow / random / next

breadpaper library / browse is the in-app picker. Do not invent bread.command.paper.next / .random / .cycle (or matching events) ahead of a real slideshow feature. Unrecognized verbs are ignored.

Fail-safe behavior

  • If breadd isn't installed or isn't running, emit is a silent no-op (BreadClient::emit never blocks or errors the caller) — breadpaper still sets the wallpaper, generates the palette, and reloads themes.
  • breadpaper listen does not exit if breadd is down. The command subscription reconnects automatically (BreadClient::subscribe's background thread has its own backoff loop); no restart of listen is needed once breadd returns.