fix(plymouth): #137 splash follows the canvas; #145 keyboard hint on the LUKS prompt
All checks were successful
Check / eval (push) Successful in 3m59s

The logo was off-centre on the external when booting/shutting down docked.
Both earlier diagnoses in this repo were WRONG, and that is the part worth
keeping: Window.GetWidth() returns max_width (not head 0), and per-head
sprites would have DUPLICATED the logo — the script plugin already builds
one max_width x max_height canvas, centres every display inside it
(script-lib-sprite.c:536) and draws sprites at (sprite.x - display.x), so a
canvas-centred sprite is centred on every head. The arithmetic was right.

The bug was TIME: every position was a top-level statement evaluated once
at parse time. A head arriving/leaving mid-splash resizes the canvas, the
plugin re-centres the displays, and frozen sprites end up off by
(new_max - old_max)/2 on every head. One monitor never resizes the canvas —
hence "only when docked". Fix: one layout(), re-run from the existing
refresh callback on canvas change.

The trap that cost two attempts (now a comment): in plymouth script a bare
assignment inside a function writes the GLOBAL if that name already exists
globally. So `canvas_width = Window.GetWidth()` updated global.canvas_width
BEFORE the guard compared against it — always false, body never ran, splash
rendered as a bare background, NO error logged. Isolated with a 20-line
probe. Hence cw/ch.

#145 rides along: a VT loads one keymap and knows nothing of per-device
layouts, so the passphrase box types with the console layout — worth saying
before three wrong tries on a disk you cannot read (same gap as #114, one
step earlier). Fedora's mechanism does not port: ply_keymap_icon is a C
widget in the two-step plugin (the script plugin has no keyboard API), fed
from XKBLAYOUT in /etc/vconsole.conf, which NixOS never writes (plymouth's
trace says `XKBLAYOUT: (null)`). So @LAYOUT@ is baked from
services.xserver.xkb.layout like the palette — the FIRST of a comma list,
since that is what the VT loads. Icon is plymouth's own keyboard.png (the
same glyph Fedora shows), copied at build time so no GPL bytes enter the
repo, recoloured to subtext.

chmod +w after that copy: store files are 444 and recolor rewrites in
place. Without it magick fails, the phase aborts, and EVERY LATER SED
SILENTLY DOES NOT RUN — the theme shipped with @BG_R@ literals and I only
caught it by reading the build log.

Verified by render (tools/plymouth-preview.sh, real built theme): both
heads centred, password dialog showing padlock + entry + keyboard icon and
"us". V3 queued — only a real docked boot can resize a canvas.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 13:14:05 +01:00
parent 121b91f69c
commit ff0f9d6359
6 changed files with 247 additions and 166 deletions

View File

@@ -449,6 +449,49 @@ Design/decision records and a running log of shipped work (items marked
(#131). Those windows therefore carry float/center rules and deliberately no
`size` rule. Measured after: calendar 1536×936 = exactly 60%×65%, doctor
1408×1008 = 55%×70%, both centred in the Waybar work area.
- ✓ **Splash: positions follow the canvas, + a keyboard hint on the LUKS prompt
(#137/#145, 2026-07-16):** Bernardo's logo was off-centre on the external when
booting/shutting down docked. **The first two diagnoses were both wrong**, and
the record matters more than the fix: it is *not* that `Window.GetWidth()`
returns head 0 (it returns `max_width`), and *not* that per-head sprites were
needed (they would have duplicated the logo). The script plugin builds one
canvas of `max_width × max_height`, **centres every display inside it**
(`display->x = (max_width - width)/2`, `script-lib-sprite.c:536`) and draws
each sprite at `sprite.x - display.x` — so a canvas-centred sprite is centred
on **every** head and the theme's arithmetic was right all along. The bug was
**time**: every position was a top-level statement evaluated once at parse
time, so a head arriving or leaving mid-splash resized the canvas, the plugin
re-centred the displays, and the frozen sprites ended up off by
`(new_max - old_max)/2` on every head. One monitor never resizes the canvas —
hence "only when docked". Fix: one `layout()`, re-run from the existing
refresh callback on canvas change.
**The trap that cost two attempts, now a comment in the script:** in plymouth
script a bare assignment inside a function writes the **global** if that name
already exists globally (`global.foo` and `foo` are one variable). So
`canvas_width = Window.GetWidth()` updated `global.canvas_width` *before* the
guard compared against it — always false, body never ran, whole splash a bare
background, **no error logged**. Proven with a 20-line probe:
`[after assign: global.canvas_width=800][guard SKIPPED]` vs a distinctly named
local firing correctly. Hence `cw`/`ch`.
**#145** rides along: a VT loads exactly one keymap and knows nothing of
per-device layouts, so the passphrase box types with the console layout —
worth stating before three wrong tries on a disk nobody can read yet (the same
gap as #114, one step earlier in the boot). Fedora's own mechanism does not
port: its label is `ply_keymap_icon`, a **C widget** in the two-step plugin
(the script plugin has no keyboard API), fed from `XKBLAYOUT` in
`/etc/vconsole.conf` — which **NixOS never writes** (this box has only
`KEYMAP=<store path>`; plymouth's trace literally says `XKBLAYOUT: (null)`).
So `@LAYOUT@` is baked from `services.xserver.xkb.layout` exactly like the
palette already is — **first** of a comma list, because that is what the VT
loads and the raw string would lie in the multi-layout case the label exists
for. The icon is plymouth's own `keyboard.png` (literally Federa's glyph),
copied at build time so no GPL bytes enter this repo, recoloured to subtext.
`chmod +w` after that copy: store files are 444 and `recolor` rewrites in
place — without it magick fails, the phase aborts, **every later sed silently
does not run**, and the theme ships with `@BG_R@` in it.
V2 by render, both heads + the password dialog, via the new
`tools/plymouth-preview.sh`. V3 (a real docked boot/shutdown) is queued: the
fake heads exist from the start, so the rig cannot resize a canvas.
- ✓ **Dock mode survives a rebuild (#142, 2026-07-16):** Bernardo: every rebuild
while docked re-lit the laptop panel and threw a workspace onto it, and he
re-picked Dock mode by hand. It was not forgetfulness — **a rebuild performed