From 81de5087eafd53582d30bb7d48725ac84a71bc07 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 8 Aug 2026 03:13:00 -0700 Subject: [PATCH] Wait for the live VT to settle before drawing the first screen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tty1 boots as an 80-column console and only widens once the kernel framebuffer/KMS takes over, which lands late — especially in VMs. The configurator's logo is wider than 80 columns, so the very first draw measured against that transient narrow console: the logo wrapped ("smushed") and, with left padding clamped to zero, hugged the left edge. Every later screen re-measures once the console has grown, which is why only the opening keyboard screen looked wrong. Hold the first draw until the width settles at or above the logo width, capped so a console that never widens still proceeds. Terminal emulators (dry runs) are already at final size and are skipped. Co-Authored-By: Claude --- configs/airootfs/root/configurator | 31 ++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/configs/airootfs/root/configurator b/configs/airootfs/root/configurator index 606fe2b..1ab29f0 100644 --- a/configs/airootfs/root/configurator +++ b/configs/airootfs/root/configurator @@ -38,6 +38,33 @@ measure_terminal() { } measure_terminal +# The live VT resizes late during boot: tty1 starts as the 80-column boot +# console and only grows once the kernel framebuffer/KMS takes over (noticeably +# late in VMs). The logo is wider than 80 columns, so a first draw against that +# transient narrow console wraps the logo ("smushed") and can't center it +# (padding clamps to 0, so it hugs the left). Every later screen re-measures and +# looks right, so this only bites the very first screen. Hold that first draw +# until the width settles at (or above) the logo width. Terminal emulators (dry +# runs) are already at final size, so skip them; a real VT that never widens +# (e.g. nomodeset) still proceeds after the cap rather than hanging. +wait_for_stable_terminal() { + [[ $(tty 2>/dev/null) == /dev/tty* ]] || return 0 + + local width last="" stable=0 waited=0 + while (( waited < 5000 )); do + width=$(stty size 2>/dev/null = LOGO_WIDTH )); then + (( ++stable >= 3 )) && break + else + stable=0 + fi + last=$width + sleep 0.2 + (( waited += 200 )) + done +} + clear_logo() { measure_terminal printf "\033[H\033[2J" @@ -944,6 +971,10 @@ select_installation() { defer_provisioning=false install_target="full_disk" +# Let the live VT reach its settled width before the first screen so the logo +# isn't measured against the transient 80-column boot console. +wait_for_stable_terminal + keyboard_form true if $defer_provisioning; then