#!/usr/bin/env bash # Raw full-root PNG grab of the headless display. # # This is deliberately the *uncropped* root window, because # `tools/re-capture/bin/screenshot` is a wrapper that calls this one as its raw # grabber and then crops to the game surface — xenia's window is a GTK window # whose menu bar pushes the 1280x720 game image down ~25 px, and every pixel # oracle in the toolkit was measured against the bare game image. That wrapper # directory is first on PATH, so scripts calling `screenshot` get the cropped # game surface and this stays the honest raw grab underneath it. # # screenshot [out.png] default: $HOME/shots/shot-NNNN.png set -u OUT="${1:-}" if [ -z "$OUT" ]; then dir="${HOME:-/tmp}/shots"; mkdir -p "$dir" n_file="$dir/.counter" n=$(( $(cat "$n_file" 2>/dev/null || echo 0) + 1 )); echo "$n" > "$n_file" OUT="$dir/shot-$(printf '%04d' "$n").png" fi mkdir -p "$(dirname "$OUT")" if ! xdpyinfo >/dev/null 2>&1; then echo "screenshot: no display on ${DISPLAY:-}" >&2 exit 1 fi # ImageMagick first. `import` talks X11 directly and captures a window that is # mid-redraw without tearing the way a video grabber can. if command -v import >/dev/null 2>&1 && import -silent -window root "$OUT" 2>/dev/null; then echo "$OUT"; exit 0 fi # Fallback: ffmpeg's x11grab. Needs an explicit size, so read it off the server # rather than assuming the geometry. if command -v ffmpeg >/dev/null 2>&1; then size=$(xdpyinfo | awk '/dimensions:/{print $2; exit}') if ffmpeg -loglevel error -y -f x11grab -draw_mouse 0 \ -video_size "$size" -i "$DISPLAY" -frames:v 1 "$OUT" 2>/dev/null; then echo "$OUT"; exit 0 fi fi # Last resort: xwd, which is always present with x11-utils. if command -v xwd >/dev/null 2>&1 && command -v convert >/dev/null 2>&1; then xwd -root -silent | convert xwd:- "$OUT" && { echo "$OUT"; exit 0; } fi echo "screenshot: no working capture backend" >&2 exit 1