Stop motion wallpaper when the Omarchy theme changes

mpvpaper kept running over the new theme's static wallpaper because
nothing was watching the omarchy-theme symlink. Add a small sibling
script that polls ~/.config/omarchy/current/background and, when the
target changes, runs `motion-wallpaper-toggle stop` — which tears down
mpvpaper and respawns swaybg with the new symlink target so the new
theme's bg becomes visible.

- motion-wallpaper-theme-watcher: polls readlink every 2s, exits silently
  on non-Omarchy systems where the symlink doesn't exist.
- toggle: spawn alongside the auto-pause watcher; kill alongside it.
- wallpaper.sh: install the new binary.
This commit is contained in:
28allday 2026-04-25 09:04:08 +01:00
parent 9e201769c9
commit 779ff3d495
3 changed files with 103 additions and 22 deletions

60
motion-wallpaper-theme-watcher Executable file
View file

@ -0,0 +1,60 @@
#!/usr/bin/env bash
# ==============================================================================
# Motion Wallpaper — theme-change watcher.
#
# Polls the Omarchy background symlink (~/.config/omarchy/current/background).
# When the user switches themes (or cycles backgrounds), Omarchy points the
# symlink at a new image. mpvpaper would otherwise keep running on top of the
# new theme's static wallpaper, so we tear it down via the toggle script —
# which also respawns swaybg with the *new* symlink target.
#
# Runs as a sibling to mpvpaper. Spawned and killed by motion-wallpaper-toggle.
# ==============================================================================
set -euo pipefail
BG_LINK="$HOME/.config/omarchy/current/background"
LOG_FILE="${XDG_CACHE_HOME:-$HOME/.cache}/motion-wallpaper.log"
POLL_SECONDS=2
log() {
printf '[%s] theme-watcher: %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >> "$LOG_FILE"
}
# Non-Omarchy systems won't have the symlink. Exit silently — auto-pause still
# works without us; we only matter on Omarchy where theme-set rotates the bg.
if [ ! -L "$BG_LINK" ] && [ ! -e "$BG_LINK" ]; then
log "no Omarchy background symlink at $BG_LINK — exiting"
exit 0
fi
initial="$(readlink -f "$BG_LINK" 2>/dev/null || true)"
if [ -z "$initial" ]; then
log "could not resolve $BG_LINK — exiting"
exit 0
fi
log "watching $BG_LINK (initial=$initial)"
# Locate the toggle binary in PATH first, then fall back to our own dir — same
# trick the auto-pause watcher uses, since launcher-spawned PATH is minimal.
TOGGLE="$(command -v motion-wallpaper-toggle 2>/dev/null || true)"
if [ -z "$TOGGLE" ]; then
self_dir="$(dirname "$(readlink -f "$0")")"
if [ -x "$self_dir/motion-wallpaper-toggle" ]; then
TOGGLE="$self_dir/motion-wallpaper-toggle"
fi
fi
if [ -z "$TOGGLE" ]; then
log "motion-wallpaper-toggle not found — exiting"
exit 0
fi
while sleep "$POLL_SECONDS"; do
current="$(readlink -f "$BG_LINK" 2>/dev/null || true)"
[ -z "$current" ] && continue
if [ "$current" != "$initial" ]; then
log "background changed ($initial → $current) — stopping motion wallpaper"
"$TOGGLE" stop >/dev/null 2>&1 || true
exit 0
fi
done

View file

@ -322,29 +322,47 @@ kill_static_wallpapers() {
} }
kill_watcher() { kill_watcher() {
pkill -f motion-wallpaper-watcher 2>/dev/null || true pkill -f motion-wallpaper-watcher 2>/dev/null || true
pkill -f motion-wallpaper-theme-watcher 2>/dev/null || true
}
# Locate a sibling script — first in PATH, then in this script's dir. Used
# for both watchers because launcher-spawned PATH is minimal.
locate_sibling() {
local name="$1" path
path="$(command -v "$name" 2>/dev/null || true)"
if [ -z "$path" ]; then
local self_dir
self_dir="$(dirname "$(readlink -f "$0")")"
if [ -x "$self_dir/$name" ]; then
path="$self_dir/$name"
fi
fi
printf '%s' "$path"
} }
start_watcher() { start_watcher() {
local watcher local watcher theme_watcher
# PATH in launcher-spawned terminals is unreliable (minimal systemd env etc), watcher="$(locate_sibling motion-wallpaper-watcher)"
# so fall back to the script's own directory where the installer puts both. theme_watcher="$(locate_sibling motion-wallpaper-theme-watcher)"
watcher="$(command -v motion-wallpaper-watcher 2>/dev/null || true)"
if [ -z "$watcher" ]; then
local self_dir
self_dir="$(dirname "$(readlink -f "$0")")"
if [ -x "$self_dir/motion-wallpaper-watcher" ]; then
watcher="$self_dir/motion-wallpaper-watcher"
fi
fi
if [ -z "$watcher" ]; then
log "watcher binary not found — auto-pause disabled"
return 0
fi
kill_watcher kill_watcher
setsid "$watcher" < /dev/null >> "$LOG_FILE" 2>&1 &
disown 2>/dev/null || true if [ -n "$watcher" ]; then
log "watcher spawned via $watcher" setsid "$watcher" < /dev/null >> "$LOG_FILE" 2>&1 &
disown 2>/dev/null || true
log "auto-pause watcher spawned via $watcher"
else
log "auto-pause watcher binary not found — auto-pause disabled"
fi
if [ -n "$theme_watcher" ]; then
setsid "$theme_watcher" < /dev/null >> "$LOG_FILE" 2>&1 &
disown 2>/dev/null || true
log "theme watcher spawned via $theme_watcher"
else
log "theme watcher binary not found — theme-change auto-stop disabled"
fi
} }
restore_static_wallpaper() { restore_static_wallpaper() {

View file

@ -5,6 +5,7 @@
# Installs: # Installs:
# ~/.local/bin/motion-wallpaper-toggle runtime TUI # ~/.local/bin/motion-wallpaper-toggle runtime TUI
# ~/.local/bin/motion-wallpaper-watcher auto-pause watcher # ~/.local/bin/motion-wallpaper-watcher auto-pause watcher
# ~/.local/bin/motion-wallpaper-theme-watcher theme-change watcher
# ~/.local/share/applications/motion-wallpaper-toggle.desktop app entry # ~/.local/share/applications/motion-wallpaper-toggle.desktop app entry
# ~/.local/share/icons/hicolor/scalable/apps/motion-wallpaper.svg icon # ~/.local/share/icons/hicolor/scalable/apps/motion-wallpaper.svg icon
# ~/.config/systemd/user/motion-wallpaper.service optional autostart unit # ~/.config/systemd/user/motion-wallpaper.service optional autostart unit
@ -29,10 +30,11 @@ fi
TOGGLE_SRC="$SCRIPT_DIR/motion-wallpaper-toggle" TOGGLE_SRC="$SCRIPT_DIR/motion-wallpaper-toggle"
WATCHER_SRC="$SCRIPT_DIR/motion-wallpaper-watcher" WATCHER_SRC="$SCRIPT_DIR/motion-wallpaper-watcher"
THEME_WATCHER_SRC="$SCRIPT_DIR/motion-wallpaper-theme-watcher"
UNIT_SRC="$SCRIPT_DIR/motion-wallpaper.service" UNIT_SRC="$SCRIPT_DIR/motion-wallpaper.service"
ICON_SRC="$SCRIPT_DIR/icons/motion-wallpaper.svg" ICON_SRC="$SCRIPT_DIR/icons/motion-wallpaper.svg"
for f in "$TOGGLE_SRC" "$WATCHER_SRC" "$UNIT_SRC" "$ICON_SRC"; do for f in "$TOGGLE_SRC" "$WATCHER_SRC" "$THEME_WATCHER_SRC" "$UNIT_SRC" "$ICON_SRC"; do
if [ ! -f "$f" ]; then if [ ! -f "$f" ]; then
echo "Missing installer asset: $f" >&2 echo "Missing installer asset: $f" >&2
exit 1 exit 1
@ -99,8 +101,9 @@ fi
# ----- install files ----------------------------------------------------------- # ----- install files -----------------------------------------------------------
install -D -m 755 "$TOGGLE_SRC" "$HOME/.local/bin/motion-wallpaper-toggle" install -D -m 755 "$TOGGLE_SRC" "$HOME/.local/bin/motion-wallpaper-toggle"
install -D -m 755 "$WATCHER_SRC" "$HOME/.local/bin/motion-wallpaper-watcher" install -D -m 755 "$WATCHER_SRC" "$HOME/.local/bin/motion-wallpaper-watcher"
install -D -m 755 "$THEME_WATCHER_SRC" "$HOME/.local/bin/motion-wallpaper-theme-watcher"
# Install custom SVG icon into the hicolor theme — Walker and other XDG-aware # Install custom SVG icon into the hicolor theme — Walker and other XDG-aware
# launchers will find it by name (Icon=motion-wallpaper) without needing a # launchers will find it by name (Icon=motion-wallpaper) without needing a