#!/bin/bash
# Runs random TTE (terminal text effects) animations in a loop.
# Meant to be launched inside a fullscreen terminal by screensaver-launch.

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ART_FILE="${SCREENSAVER_ART:-$SCRIPT_DIR/screensaver.txt}"
# 120fps of full-canvas terminal effects pegged a CPU core and, on this
# machine, the fans -- most effects don't need anywhere near that to look
# smooth. Cuts CPU roughly in half on its own; combined with the larger
# font in screensaver-launch (fewer cells to animate per frame) it's closer
# to a 3-4x reduction.
FRAME_RATE="${SCREENSAVER_FPS:-30}"
WIN_CLASS="screensaver"

# DPMS blanking (xset dpms, 300s by default -- see ~/.xinitrc) turns the
# display off but doesn't stop this from rendering into its window, so
# without this tte just kept animating into a screen nobody could see,
# burning CPU/GPU for as long as the machine stayed idle.
#
# This has to pause tte in place rather than screensaverd killing the
# window from outside: creating *or* destroying an X window forces the
# display live again (confirmed live -- mapping or killing an unrelated
# window while DPMS-off flips "Monitor is Off" back to "On" instantly;
# writing new content into an already-mapped window does not), so killing
# the window the moment it blanks just wakes it right back up, and with
# screensaverd still seeing >IDLE_SECONDS of idle, relaunches the
# screensaver -- which wakes it again. The screen never actually stayed off.
monitor_off() {
  xset q 2>/dev/null | grep -q "Monitor is \(Off\|Standby\|Suspend\)"
}

screensaver_in_focus() {
  local id
  id=$(xdotool getactivewindow 2>/dev/null) || return 1
  xprop -id "$id" WM_CLASS 2>/dev/null | grep -q "\"$WIN_CLASS\""
}

exit_screensaver() {
  tput cnorm 2>/dev/null
  pkill -x tte 2>/dev/null
  exit 0
}

trap exit_screensaver SIGINT SIGTERM SIGHUP SIGQUIT

printf '\033]11;rgb:00/00/00\007' # black background
tput civis 2>/dev/null            # hide text cursor

tty=$(tty 2>/dev/null)

while true; do
  # Blanked: sit idle without touching the window at all (see monitor_off
  # above for why) until either DPMS wakes on its own or screensaverd kills
  # this whole window from outside because of real input.
  if monitor_off; then
    sleep 1
    continue
  fi

  tte -i "$ART_FILE" \
    --frame-rate "$FRAME_RATE" --canvas-width 0 --canvas-height 0 --reuse-canvas --anchor-canvas c --anchor-text c \
    --random-effect --no-eol --no-restore-cursor &

  while pgrep -t "${tty#/dev/}" -x tte >/dev/null; do
    if read -n1 -t 1 || ! screensaver_in_focus; then
      exit_screensaver
    fi
    if monitor_off; then
      pkill -x tte 2>/dev/null
      break
    fi
  done
done
