From 05f9ddd3af672647d7cb384b19bda163b881a8ae Mon Sep 17 00:00:00 2001 From: Tyler Date: Mon, 25 May 2026 09:41:39 -0700 Subject: [PATCH] test: headless input harness with mouse click/drag support shot_input.sh launches the app under Xvfb and drives it with xdotool, then screenshots for pixel-diff verification. Adds click/drag/rdrag pseudo-actions that insert the frame gap raylib's button edge-detection needs (a bare xdotool "click 1" is too fast and no-ops). Documents the settled-capture timing (12s) and the 1280x800 viewport/sidebar bounds. Co-Authored-By: Claude Opus 4.7 --- shot_input.sh | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100755 shot_input.sh diff --git a/shot_input.sh b/shot_input.sh new file mode 100755 index 0000000..8808ec2 --- /dev/null +++ b/shot_input.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# Usage: shot_input.sh [action ...] +# Launches rspektrum under Xvfb, runs input actions, captures the screen, cleans up. +# +# Actions (each runs in order): +# "sleep N" sleep N seconds locally (let the app settle / animate). +# Capture at "sleep 12" for a SETTLED render: the background +# high-res STFT fill runs over the first several seconds, so +# earlier grabs are nondeterministic run-to-run. +# "click X Y" left-click at (X,Y): move, press, hold ~0.2s, release. +# "drag X1 Y1 X2 Y2" left-drag from (X1,Y1) to (X2,Y2). +# "rdrag X1 Y1 X2 Y2" same but with Alt held (the app's pan gesture). +# "key NAME" xdotool keysym, e.g. "key F1", "key p", "key Home". +# anything else passed verbatim to xdotool (mousemove, mousedown, ...). +# +# IMPORTANT timing note: a left button's press and release MUST land in different +# 60 Hz frames or raylib's IsMouseButtonPressed edge-detect (current && !previous) +# never fires. The click/drag helpers below insert that gap; a bare "click 1" via +# xdotool is too fast and silently no-ops. Keys reach GLFW fine under Xvfb; so do +# synthetic mouse buttons (the pointer just has to be over a live target). +# +# Layout cheat-sheet at the default 1280x800 window (UI scale = 1.0): +# spectrogram viewport ~ x:[385,1242] y:[50,468] (drags/selections go here) +# sidebar ~ x:[0,320] (buttons; click centers) +# a selection box needs a >5 px drag or it reverts to "no selection". +set -u +OUT="${1:-/tmp/rspek_shot.png}"; shift || true +REPO=/home/tyler/ham/Audio-Experiments/rspektrum +DISP=:99 +WAV="${RSPEK_WAV:-/tmp/mlink_bulk_drop.wav}" + +pkill -f "Xvfb $DISP" 2>/dev/null +sleep 1 +Xvfb $DISP -screen 0 1280x800x24 >/tmp/xvfb.log 2>&1 & +XVFB=$! +sleep 1 + +cd "$REPO" || exit 1 +DISPLAY=$DISP ./bin/Debug/rspektrum "$WAV" >/tmp/rspek.log 2>&1 & +APP=$! +sleep 5 # initial load + +# Make sure the app window is focused so key events land on it. +WID=$(DISPLAY=$DISP xdotool search --name "Spectrogram" | head -1) +[ -n "$WID" ] && DISPLAY=$DISP xdotool windowactivate "$WID" 2>/dev/null +sleep 0.3 + +xd() { DISPLAY=$DISP xdotool "$@" 2>>/tmp/xdotool.log; } + +for act in "$@"; do + # shellcheck disable=SC2086 + set -- $act + case "$1" in + sleep) sleep "$2" ;; + click) + xd mousemove "$2" "$3"; sleep 0.1 + xd mousedown 1; sleep 0.2 # hold across >=1 frame + xd mouseup 1; sleep 0.15 + ;; + drag) + xd mousemove "$2" "$3"; sleep 0.1 + xd mousedown 1; sleep 0.1 + xd mousemove "$4" "$5"; sleep 0.2 + xd mouseup 1; sleep 0.15 + ;; + rdrag) + xd keydown alt; sleep 0.05 + xd mousemove "$2" "$3"; sleep 0.1 + xd mousedown 1; sleep 0.1 + xd mousemove "$4" "$5"; sleep 0.2 + xd mouseup 1; sleep 0.1 + xd keyup alt; sleep 0.15 + ;; + *) xd "$@"; sleep 0.15 ;; + esac +done +sleep 0.3 + +DISPLAY=$DISP import -window root "$OUT" 2>/tmp/import.log +RC=$? +kill $APP 2>/dev/null +kill $XVFB 2>/dev/null +wait 2>/dev/null +echo "capture rc=$RC -> $OUT" +ls -la "$OUT" 2>/dev/null