#!/bin/bash
# Launches the screensaver fullscreen on every connected monitor (X11 / st).
set -u
export PATH="$HOME/.local/bin:$PATH"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WIN_CLASS="screensaver"
command -v tte >/dev/null || { echo "tte not found (pipx install terminaltexteffects)" >&2; exit 1; }
# Already running? Don't stack another instance.
if xdotool search --class "^${WIN_CLASS}\$" >/dev/null 2>&1; then
exit 0
fi
for mon in $(xrandr --listmonitors | awk 'NR>1 {print $3}'); do
# mon looks like 3440/798x1440/334+0+0
geom="${mon%%+*}" # 3440/798x1440/334
offsets="+${mon#*+}" # +0+0
w="${geom%%/*}"
h_part="${geom#*x}"
h="${h_part%%/*}"
x="$(echo "$offsets" | cut -d+ -f2)"
y="$(echo "$offsets" | cut -d+ -f3)"
# st has no runtime equivalent of kitty's window_padding_width/mouse_hide_wait
# overrides (those are compile-time-only in st), so they're just dropped here.
st -c "$WIN_CLASS" \
-f "JetBrainsMono Nerd Font:pixelsize=24:antialias=true:autohint=true" \
-A 1.0 \
-e "$SCRIPT_DIR/screensaver" &
kpid=$!
# Wait for the window owned by this st process to appear, then pin it
# to this monitor and fullscreen it.
newwin=""
for _ in $(seq 1 50); do
for win in $(xdotool search --class "^${WIN_CLASS}\$" 2>/dev/null); do
if [[ "$(xdotool getwindowpid "$win" 2>/dev/null)" == "$kpid" ]]; then
newwin="$win"
break 2
fi
done
sleep 0.1
done
if [[ -n "$newwin" ]]; then
# The window may not be fully mapped/reparented yet right after it
# appears in `xdotool search`, so retry placement to ride out the
# occasional BadWindow race with the window manager. `wmctrl`
# returning success only means the fullscreen request was sent, not
# that the WM actually acted on it (e.g. it's silently dropped if the
# window isn't mapped yet in the WM's eyes) -- read the geometry back
# and keep retrying until it actually matches the monitor, instead of
# giving up after a fixed few tries and leaving it windowed.
for attempt in $(seq 1 30); do
xdotool windowactivate --sync "$newwin" 2>/dev/null
xdotool windowmove "$newwin" "$x" "$y" 2>/dev/null
xdotool windowsize "$newwin" "$w" "$h" 2>/dev/null
wmctrl -ir "$newwin" -b add,fullscreen 2>/dev/null
geo="$(xdotool getwindowgeometry --shell "$newwin" 2>/dev/null)"
gx="$(grep -m1 '^X=' <<<"$geo" | cut -d= -f2)"
gy="$(grep -m1 '^Y=' <<<"$geo" | cut -d= -f2)"
gw="$(grep -m1 '^WIDTH=' <<<"$geo" | cut -d= -f2)"
gh="$(grep -m1 '^HEIGHT=' <<<"$geo" | cut -d= -f2)"
if [[ "$gx" == "$x" && "$gy" == "$y" && "$gw" == "$w" && "$gh" == "$h" ]]; then
break
fi
sleep 0.1
done
fi
done