#!/bin/bash
# Idle watcher: launches the screensaver after IDLE_SECONDS of inactivity
# and kills it the moment real activity resumes.
set -u

# sxwm's `exec` runs commands via execvp with whatever PATH the X session
# started with, which may not include a pipx-installed `tte`. Make sure it's
# found regardless.
export PATH="$HOME/.local/bin:$PATH"

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
IDLE_SECONDS="${SCREENSAVER_IDLE_SECONDS:-150}"
WIN_CLASS="screensaver"
PAUSE_FILE="${XDG_RUNTIME_DIR:-/tmp}/screensaver-paused"

is_running() {
  xdotool search --class "^${WIN_CLASS}\$" >/dev/null 2>&1
}

# Set by screensaver-toggle. Checked fresh every loop iteration (not just
# at launch time) so toggling pause while the screensaver is already
# showing kills it immediately, same as real input would.
is_paused() {
  [[ -e "$PAUSE_FILE" ]]
}

# xssstate only tracks keyboard/mouse input, so a video playing quietly
# (no input for the whole runtime) still counts as "idle" and would get
# covered by the screensaver. playerctl (already a dependency for the
# media keybindings) reports MPRIS playback state for players that
# support it (mpv, VLC, Firefox/Chromium, ...), so use that as an extra
# "really idle" check.
media_playing() {
  command -v playerctl >/dev/null 2>&1 || return 1
  [ "$(playerctl status 2>/dev/null)" = "Playing" ]
}

stop_screensaver() {
  pkill -f "$SCRIPT_DIR/screensaver\$" 2>/dev/null
  pkill -x tte 2>/dev/null
  for win in $(xdotool search --class "^${WIN_CLASS}\$" 2>/dev/null); do
    xdotool windowkill "$win" 2>/dev/null
  done
}

while true; do
  idle_ms=$(xssstate -i)
  idle_s=$((idle_ms / 1000))

  if (( idle_s >= IDLE_SECONDS )) && ! is_running && ! media_playing && ! is_paused; then
    "$SCRIPT_DIR/screensaver-launch"
  elif is_running && { (( idle_s < 1 )) || media_playing || is_paused; }; then
    stop_screensaver
  fi

  sleep 1
done
