#!/usr/bin/env bash # # Render the UI and screenshot it without touching your session. # # A Slint window needs a compositor: under bare Xvfb nothing maps, and on a locked or # remote machine there is no session to draw into. So this starts a nested headless # sway, runs the app inside it, drives it with synthetic keys and grabs a frame per # screen. It is how the shots in README.md were made, and how to check a layout change # on a machine with no display. # # nix-shell -E '(import ./shell.nix {}).overrideAttrs (o: { # nativeBuildInputs = o.nativeBuildInputs ++ (with (import {}); [ sway grim wtype ]); # })' --run 'tools/headless-shots.sh out/ http://127.0.0.1:8080' # set -euo pipefail OUTDIR="${1:?usage: headless-shots.sh [server-url]}" SERVER="${2:-http://127.0.0.1:8080}" BIN="${BIN:-./target/release/musicmouse-slint}" mkdir -p "$OUTDIR" export XDG_RUNTIME_DIR="$(mktemp -d)" unset WAYLAND_DISPLAY DISPLAY export WLR_BACKENDS=headless WLR_LIBINPUT_NO_DEVICES=1 WLR_RENDERER=pixman trap 'kill %1 2>/dev/null || true; rm -rf "$XDG_RUNTIME_DIR"' EXIT launcher="$XDG_RUNTIME_DIR/launch.sh" printf '#!/usr/bin/env bash\nexec %q --server %q >%q/app.log 2>&1\n' \ "$(realpath "$BIN")" "$SERVER" "$XDG_RUNTIME_DIR" > "$launcher" chmod +x "$launcher" printf 'output HEADLESS-1 mode 1920x1080\ndefault_border none\nexec %s\n' "$launcher" \ > "$XDG_RUNTIME_DIR/sway.cfg" sway -c "$XDG_RUNTIME_DIR/sway.cfg" >"$XDG_RUNTIME_DIR/sway.log" 2>&1 & for _ in $(seq 30); do [ -S "$XDG_RUNTIME_DIR/wayland-1" ] && break; sleep 1; done export WAYLAND_DISPLAY=wayland-1 sleep 16 # library fetch plus the first covers # Each step is ONE wtype invocation, and starts with a throwaway keypress. # # wtype creates a virtual keyboard, sends, and exits. The client needs a moment to # notice the seat gained a keyboard, so the first key or two of any invocation is # dropped - which makes a per-key loop lose every key it sends. Batching a step into # one invocation and opening it with "x" + BackSpace spends that warm-up on a keypress # that cancels itself out. WARM=(-s 260 "x" -k BackSpace) shot() { sleep 2.5; grim "$OUTDIR/$1.png"; echo " $1"; } shot 01-root wtype "${WARM[@]}" -k Down -k Return; shot 02-categories wtype "${WARM[@]}" -k Return; shot 03-grid wtype "${WARM[@]}" -k Escape -k Escape "maja"; shot 04-search wtype "${WARM[@]}" -k Escape -k question "brumm"; shot 05-tracksearch wtype "${WARM[@]}" -k Return; sleep 4; shot 06-play wtype "${WARM[@]}" -k Escape; shot 07-bar echo "wrote 7 frames to $OUTDIR"