From a25f20052973cd92bd51c9325a8f88cd47861f4c Mon Sep 17 00:00:00 2001 From: maziggy Date: Sun, 12 Apr 2026 11:09:59 +0200 Subject: [PATCH] . --- spoolbuddy/daemon/display_control.py | 45 +++++++++++---------------- spoolbuddy/install/spoolbuddy-idle.sh | 9 ++++++ 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/spoolbuddy/daemon/display_control.py b/spoolbuddy/daemon/display_control.py index 4968b7600..6d67eba5a 100644 --- a/spoolbuddy/daemon/display_control.py +++ b/spoolbuddy/daemon/display_control.py @@ -106,37 +106,30 @@ class DisplayControl: self._blanked = True logger.debug("Screen idle timeout reached (swayidle manages blanking)") + _WAYLAND_ENV_FILE = Path("/tmp/spoolbuddy-wayland-env") + def _discover_wayland_env(self) -> dict[str, str] | None: """Discover WAYLAND_DISPLAY and XDG_RUNTIME_DIR for the kiosk session. The daemon runs as a systemd service outside the Wayland session, so - these variables aren't inherited. First try our own runtime dir, then - scan all /run/user/*/ dirs — on a kiosk there's exactly one Wayland - session and the daemon may run under a system uid that logind doesn't - create a runtime dir for. + these variables aren't inherited. The kiosk idle watchdog + (spoolbuddy-idle.sh) writes them to /tmp/spoolbuddy-wayland-env on + startup — read that file. """ - candidates: list[Path] = [] - # Prefer our own runtime dir if set - own_xdg = os.environ.get("XDG_RUNTIME_DIR", "") - if own_xdg: - candidates.append(Path(own_xdg)) - candidates.append(Path(f"/run/user/{os.getuid()}")) - # Fall back to scanning all user runtime dirs - run_user = Path("/run/user") - if run_user.is_dir(): - for uid_dir in sorted(run_user.iterdir()): - if uid_dir.is_dir() and uid_dir not in candidates: - candidates.append(uid_dir) - - for runtime in candidates: - if not runtime.is_dir(): - continue - try: - for entry in sorted(runtime.iterdir()): - if entry.name.startswith("wayland-") and not entry.name.endswith(".lock"): - return {"WAYLAND_DISPLAY": entry.name, "XDG_RUNTIME_DIR": str(runtime)} - except PermissionError: - continue + if not self._WAYLAND_ENV_FILE.exists(): + return None + try: + env: dict[str, str] = {} + for line in self._WAYLAND_ENV_FILE.read_text().strip().splitlines(): + if "=" in line: + key, value = line.split("=", 1) + env[key] = value + wayland_display = env.get("WAYLAND_DISPLAY", "") + xdg_runtime_dir = env.get("XDG_RUNTIME_DIR", "") + if wayland_display and xdg_runtime_dir: + return {"WAYLAND_DISPLAY": wayland_display, "XDG_RUNTIME_DIR": xdg_runtime_dir} + except Exception as e: + logger.warning("Failed to read %s: %s", self._WAYLAND_ENV_FILE, e) return None def _wlopm(self, on: bool) -> None: diff --git a/spoolbuddy/install/spoolbuddy-idle.sh b/spoolbuddy/install/spoolbuddy-idle.sh index b2eceb648..b661de3da 100755 --- a/spoolbuddy/install/spoolbuddy-idle.sh +++ b/spoolbuddy/install/spoolbuddy-idle.sh @@ -85,6 +85,15 @@ if [ -n "$BACKEND_URL" ] && [ -n "$API_KEY" ] && [ -n "$DEVICE_ID" ]; then fi fi +# Write Wayland env to a known file so the SpoolBuddy daemon (which runs as a +# systemd service outside the compositor) can discover the socket and call wlopm +# to wake the display on NFC/scale events. +WAYLAND_ENV_FILE="/tmp/spoolbuddy-wayland-env" +printf 'WAYLAND_DISPLAY=%s\nXDG_RUNTIME_DIR=%s\n' \ + "${WAYLAND_DISPLAY:-}" "${XDG_RUNTIME_DIR:-}" > "$WAYLAND_ENV_FILE" +chmod 644 "$WAYLAND_ENV_FILE" +echo "wrote Wayland env to $WAYLAND_ENV_FILE" + if [ "$TIMEOUT" -le 0 ]; then # Blanking explicitly disabled — don't launch swayidle at all. echo "timeout<=0, sleeping forever"