Cross-check HIS against hyprctl instances (dir can linger)

The previous check trusted $XDG_RUNTIME_DIR/hypr/$HIS/ existing, but the
directory and its socket files can remain on disk after the session dies.
On a real run the stale signature still had a dir, so the guard passed
and hyprctl silently failed again.

ensure_hyprland_env now queries `hyprctl instances` — the source of truth
for live sessions — and rewrites HIS if ours isn't in the list. Watcher
mirrors the same logic.

Also: drop the outdated "zenity" mention from the installer header.
This commit is contained in:
28allday 2026-04-23 22:52:51 +01:00
parent 154bcc85d4
commit 9e201769c9
3 changed files with 39 additions and 33 deletions

View file

@ -182,29 +182,34 @@ show_header() {
# ===== selection ==============================================================
ensure_hyprland_env() {
# The TUI can be launched from contexts whose env doesn't carry a valid
# HYPRLAND_INSTANCE_SIGNATURE. Two failure modes:
# 1) HIS unset (fresh login shell from a non-graphical context)
# 2) HIS set but STALE — points to a previous Hyprland session whose
# socket no longer exists (seen when Walker's env carries the
# signature from an earlier login). The second case is silent but
# equally broken: hyprctl dumps a plain-text error on stdout.
# `hyprctl instances` always reports the *live* signatures, so recover
# from that. Leave HIS unchanged if we can't find a live instance.
# The TUI can be launched from contexts whose HYPRLAND_INSTANCE_SIGNATURE
# isn't usable. Three failure modes, all silent:
# 1) HIS unset (fresh login shell, cron, ssh).
# 2) HIS set but points to a dead session — the `hypr/<sig>/` directory
# and its socket files can linger on disk after the Hyprland process
# exits, so a dir-exists check is not enough.
# 3) Walker's env retained an old HIS across a Hyprland restart.
# `hyprctl instances` is the source of truth: it only reports live
# instances. Always cross-check against it and rewrite HIS if ours isn't
# in the list.
local his="${HYPRLAND_INSTANCE_SIGNATURE:-}"
if [ -n "$his" ] && [ -d "$RUNTIME_DIR/hypr/$his" ]; then
local live
live="$(hyprctl instances 2>/dev/null | awk '/^instance /{sub(/:$/,"",$2); print $2}')"
if [ -z "$live" ]; then
# No live Hyprland — nothing we can do, let the caller surface an error.
return 0
fi
if [ -n "$his" ] && printf '%s\n' "$live" | grep -qxF "$his"; then
return 0
fi
local sig
sig="$(hyprctl instances 2>/dev/null | awk '/^instance /{sub(/:$/,"",$2); print $2; exit}')"
if [ -n "$sig" ] && [ "$sig" != "$his" ]; then
sig="$(printf '%s\n' "$live" | head -n 1)"
export HYPRLAND_INSTANCE_SIGNATURE="$sig"
if [ -n "$his" ]; then
log "replaced stale HYPRLAND_INSTANCE_SIGNATURE ($his → $sig)"
else
log "recovered HYPRLAND_INSTANCE_SIGNATURE=$sig from hyprctl instances"
fi
fi
}
get_monitors() {

View file

@ -21,17 +21,17 @@ log() {
}
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
# Cross-check against `hyprctl instances` — the socket dir alone can linger
# on disk after a session dies, so a dir-exists check isn't reliable.
live="$(hyprctl instances 2>/dev/null | awk '/^instance /{sub(/:$/,"",$2); print $2}')"
if [ -z "$live" ]; then
log "no live Hyprland instance reported by hyprctl — exiting"
exit 0
fi
if [ -z "$his" ] || ! printf '%s\n' "$live" | grep -qxF "$his"; then
sig="$(printf '%s\n' "$live" | head -n 1)"
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"

View file

@ -3,14 +3,15 @@
# Motion Wallpaper Installer for Omarchy / Hyprland
#
# Installs:
# ~/.local/bin/motion-wallpaper-toggle runtime script
# ~/.local/bin/motion-wallpaper-toggle runtime TUI
# ~/.local/bin/motion-wallpaper-watcher auto-pause watcher
# ~/.local/share/applications/motion-wallpaper-toggle.desktop app entry
# ~/.local/share/icons/hicolor/scalable/apps/motion-wallpaper.svg icon
# ~/.config/systemd/user/motion-wallpaper.service optional autostart unit
#
# Dependencies:
# mpv, jq, zenity (pacman)
# mpv, jq, gum, socat, libnotify (pacman)
# mpvpaper (AUR, via yay or paru)
# libnotify (pacman) — optional, for notify-send
# ==============================================================================
set -euo pipefail