Walker's env can carry a stale HIS across Hyprland restarts — the variable points at a signature whose socket dir no longer exists, so hyprctl dumps a plain-text "not running" error to stdout and the TUI silently bails. Validate HIS against `$XDG_RUNTIME_DIR/hypr/$HIS/` and fall through to the `hyprctl instances` recovery path when the directory is missing, not only when HIS is unset. Same detection added to the watcher.
88 lines
3 KiB
Bash
88 lines
3 KiB
Bash
#!/usr/bin/env bash
|
|
# ==============================================================================
|
|
# Motion Wallpaper — auto-pause watcher.
|
|
#
|
|
# Subscribes to Hyprland's event socket (socket2) and toggles mpv pause/resume
|
|
# via the IPC socket that mpvpaper was started with. Replaces mpvpaper's own
|
|
# --auto-pause / -p flag, which is unreliable on recent Hyprland releases.
|
|
#
|
|
# This script runs as a background sibling to mpvpaper. The main toggle script
|
|
# starts it and kills it.
|
|
# ==============================================================================
|
|
|
|
set -euo pipefail
|
|
|
|
RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
|
|
MPV_IPC="$RUNTIME_DIR/motion-wallpaper-mpv.sock"
|
|
LOG_FILE="${XDG_CACHE_HOME:-$HOME/.cache}/motion-wallpaper.log"
|
|
|
|
log() {
|
|
printf '[%s] watcher: %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >> "$LOG_FILE"
|
|
}
|
|
|
|
his="${HYPRLAND_INSTANCE_SIGNATURE:-}"
|
|
if [ -z "$his" ] || [ ! -d "$RUNTIME_DIR/hypr/$his" ]; then
|
|
# HIS is missing or stale (points to a dead session). Recover from the
|
|
# live signature reported by `hyprctl instances`.
|
|
sig="$(hyprctl instances 2>/dev/null | awk '/^instance /{sub(/:$/,"",$2); print $2; exit}')"
|
|
if [ -n "$sig" ]; then
|
|
export HYPRLAND_INSTANCE_SIGNATURE="$sig"
|
|
log "using HYPRLAND_INSTANCE_SIGNATURE=$sig (was: ${his:-unset})"
|
|
else
|
|
log "HYPRLAND_INSTANCE_SIGNATURE not usable and no live instance found — exiting"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
HYPR_SOCK="$RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock"
|
|
if [ ! -S "$HYPR_SOCK" ]; then
|
|
log "hyprland event socket not found ($HYPR_SOCK) — exiting"
|
|
exit 0
|
|
fi
|
|
|
|
if ! command -v socat >/dev/null 2>&1; then
|
|
log "socat not installed — exiting"
|
|
exit 0
|
|
fi
|
|
|
|
send_mpv() {
|
|
# Best-effort — silently no-op if mpv's IPC socket isn't up yet.
|
|
[ -S "$MPV_IPC" ] || return 0
|
|
printf '%s\n' "$1" | socat - "UNIX-CONNECT:$MPV_IPC" >/dev/null 2>&1 || true
|
|
}
|
|
|
|
pause_mpv() { send_mpv '{ "command": ["set_property", "pause", true] }'; }
|
|
resume_mpv() { send_mpv '{ "command": ["set_property", "pause", false] }'; }
|
|
|
|
log "watching $HYPR_SOCK"
|
|
|
|
# Kill socat child on exit so it doesn't spam "Broken pipe" to the log when
|
|
# the watcher is killed by the main toggle script.
|
|
cleanup() {
|
|
# `[ ] && kill` short-circuits to non-zero when SOCAT_PID is unset, which
|
|
# under `set -e` would abort the trap before `exit 0` — wrap safely.
|
|
if [ -n "${SOCAT_PID:-}" ]; then
|
|
kill "$SOCAT_PID" 2>/dev/null || true
|
|
fi
|
|
exit 0
|
|
}
|
|
trap cleanup EXIT INT TERM
|
|
|
|
# Hyprland socket2 emits newline-separated "EVENT>>DATA" lines. We only care
|
|
# about the fullscreen state. `fullscreen>>1` = entered, `fullscreen>>0` = left.
|
|
# socat stderr is dropped so EPIPE on shutdown doesn't bloat the log.
|
|
coproc SOCAT { socat -u "UNIX-CONNECT:$HYPR_SOCK" - 2>/dev/null; }
|
|
# Bash auto-exports SOCAT_PID from `coproc SOCAT`; used in cleanup trap.
|
|
|
|
while IFS= read -r line <&"${SOCAT[0]}"; do
|
|
case "$line" in
|
|
fullscreen\>\>1)
|
|
log "fullscreen entered — pause"
|
|
pause_mpv
|
|
;;
|
|
fullscreen\>\>0)
|
|
log "fullscreen left — resume"
|
|
resume_mpv
|
|
;;
|
|
esac
|
|
done
|