From be5122048be6dfab9521ea391535373f6b59ec5b Mon Sep 17 00:00:00 2001 From: archipelago Date: Tue, 21 Jul 2026 12:46:15 -0400 Subject: [PATCH] fix(kiosk): correct --window-size to DIPs + panel-derived layout target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kiosk window was sized in physical pixels, but Chromium interprets --window-size in DIPs: with any device-scale > 1 the window painted scale-times larger than the panel, and with no window manager in the kiosk X session --kiosk/--start-fullscreen could not snap it back. On a 4K TV at scale 3 that meant an 11520x6480 window — 9x the panel area — which blew the compositor tile-memory budget ("tile memory limits exceeded, some content may not draw") and froze the screen on the last painted frame; smaller scales cropped content off the right/bottom. - Size the window in DIPs (panel / scale) so DIPs x scale = the panel. - Panels >=2560 wide now target a 1920-wide layout (4K -> scale 2.0, validated on the Framework's 72" 4K TV: spacious desktop layout at 2x sharpness); smaller panels keep the 1280 target (1080p TV -> 1.5). - Optional ARCHIPELAGO_KIOSK_MAX_WIDTH cap: drop to the best <=N-wide xrandr mode for weak hardware (TV upscales instead of us rasterizing). - Source /etc/archipelago/kiosk-display.conf so the upcoming Settings display-resolution picker can manage these knobs per node. Co-Authored-By: Claude Fable 5 --- .../configs/archipelago-kiosk-launcher.sh | 48 +++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/image-recipe/configs/archipelago-kiosk-launcher.sh b/image-recipe/configs/archipelago-kiosk-launcher.sh index 7815578e..9b1afcf5 100644 --- a/image-recipe/configs/archipelago-kiosk-launcher.sh +++ b/image-recipe/configs/archipelago-kiosk-launcher.sh @@ -22,6 +22,11 @@ if [ "$X_READY" != "true" ]; then exit 1 fi +# Settings-managed display overrides (system.kiosk-display.set writes this +# file, then restarts the kiosk): may set ARCHIPELAGO_KIOSK_SCALE, +# ARCHIPELAGO_KIOSK_TARGET_CSS_WIDTH or ARCHIPELAGO_KIOSK_MAX_WIDTH. +[ -f /etc/archipelago/kiosk-display.conf ] && . /etc/archipelago/kiosk-display.conf + KIOSK_SAFE_AREA_X_PX=${ARCHIPELAGO_KIOSK_SAFE_AREA_X_PX:-} KIOSK_SAFE_AREA_Y_PX=${ARCHIPELAGO_KIOSK_SAFE_AREA_Y_PX:-} @@ -54,6 +59,25 @@ configure_display() { ' /tmp/archipelago-kiosk-xrandr.txt) [ -n "$mode" ] || mode=1920x1080 + # Optional resolution cap for weak hardware: ARCHIPELAGO_KIOSK_MAX_WIDTH=1920 + # drops a 4K panel to its best <=1920-wide mode (the TV upscales) so the + # software rasterizer paints 1/4 the pixels. Off by default — native mode + # is sharp and fits the tile budget now that --window-size is in DIPs. + local max_w=${ARCHIPELAGO_KIOSK_MAX_WIDTH:-0} + if [ "$max_w" -gt 0 ] 2>/dev/null && [ "${mode%x*}" -gt "$max_w" ] 2>/dev/null; then + local capped + capped=$(awk -v out="$output" -v maxw="$max_w" ' + $1 == out { active = 1; next } + active && /^[[:space:]]+[0-9]+x[0-9]+/ { + split($1, wh, "x") + if (wh[1] + 0 <= maxw && wh[1] + 0 > best_w) { best_w = wh[1] + 0; best = $1 } + } + active && /^[^[:space:]]/ { active = 0 } + END { if (best) print best } + ' /tmp/archipelago-kiosk-xrandr.txt) + [ -n "$capped" ] && mode=$capped + fi + # Kiosk should use one native output. A spanning desktop makes Chromium land # on the laptop panel or stretch across both outputs. for internal in $(awk '/ connected/ && $1 ~ /^eDP|^LVDS/{print $1}' /tmp/archipelago-kiosk-xrandr.txt); do @@ -90,9 +114,17 @@ configure_display # panel becomes a 3840px-wide viewport and the UI renders tiny — and a # keyboard-less kiosk can't zoom. Derive Chromium's device-scale-factor from # the detected panel width so the *effective* CSS viewport lands near a -# comfortable across-the-room target, scaling the whole UI up on big screens: -# 1920x1080 -> 1.50 | 2560x1440 -> 2.00 | 3840x2160 -> 3.00 (clamped 1.0-3.0) -KIOSK_TARGET_CSS_WIDTH=${ARCHIPELAGO_KIOSK_TARGET_CSS_WIDTH:-1280} +# comfortable target. Panels >=2560 wide get a 1920-wide layout (4K -> scale +# 2.0 — user-validated on a 72" TV: spacious desktop layout, 2x sharp); +# smaller panels get a 1280-wide layout (1920 -> 1.50, laptops -> 1.0). +if [ -z "${ARCHIPELAGO_KIOSK_TARGET_CSS_WIDTH:-}" ]; then + if [ "$KIOSK_MODE_W" -ge 2560 ] 2>/dev/null; then + ARCHIPELAGO_KIOSK_TARGET_CSS_WIDTH=1920 + else + ARCHIPELAGO_KIOSK_TARGET_CSS_WIDTH=1280 + fi +fi +KIOSK_TARGET_CSS_WIDTH=$ARCHIPELAGO_KIOSK_TARGET_CSS_WIDTH if [ -n "${ARCHIPELAGO_KIOSK_SCALE:-}" ]; then KIOSK_SCALE=$ARCHIPELAGO_KIOSK_SCALE else @@ -100,6 +132,14 @@ else 'BEGIN{if(t<=0)t=1280; s=w/t; s=int(s*4+0.5)/4; if(s<1)s=1; if(s>3)s=3; printf "%.2f", s}') fi +# Chromium's --window-size is in DIPs (CSS px), not physical pixels: at scale S +# the window paints S x larger. This X session has no window manager, so +# --kiosk/--start-fullscreen cannot snap an oversized window back to the panel +# — it just hangs off the right/bottom edges (content cropped, background art +# offscreen). Size the window in DIPs so DIPs x scale = the panel exactly. +KIOSK_WIN_W=$(awk -v w="$KIOSK_MODE_W" -v s="$KIOSK_SCALE" 'BEGIN{printf "%d", w/s}') +KIOSK_WIN_H=$(awk -v h="$KIOSK_MODE_H" -v s="$KIOSK_SCALE" 'BEGIN{printf "%d", h/s}') + xhost +SI:localuser:archipelago 2>/dev/null || true xsetroot -solid black 2>/dev/null || true xset s off 2>/dev/null || true @@ -157,7 +197,7 @@ while true; do --disable-component-update \ $GPU_FLAGS \ --renderer-process-limit=2 \ - --window-size=${KIOSK_MODE_W},${KIOSK_MODE_H} \ + --window-size=${KIOSK_WIN_W},${KIOSK_WIN_H} \ --window-position=0,0 \ --start-fullscreen \ --force-device-scale-factor=${KIOSK_SCALE} \