fix(panel): draw a terminal in its web font only once the font has loaded
Merged
DA
5d ago+122+122+012345678901234567890123456789-2-2-0123456789
This came out of the 390px phone check for the Terminal tab on the web (#4357, #4360). It is independent of both.
The bug
- A page fetches a web font only once something draws in it, and xterm measures its cells as it opens.
- The web profile's monospace face is the JetBrains Mono web font (
--luke-font-monoin@luke/ui'sprofiles.css). A terminal opened before that font landed measured its cells in the stand-in face, and fit its columns to them. - The next resize measured the cells again in the face that had landed, but kept the columns. On a phone, the next resize is the keyboard coming up.
- So the screen drew about 17% past its box, and every long line was cut off at the right edge. At 390px it was 62 columns of 7 px in a 371 px screen; with the fix it is 53.
- The desktop never hits this: its monospace faces are the system's, loaded already.
The fix
terminal-surface.ts:
- Face still loading (
document.fonts.checkfalse): the terminal opens in the system'smonospaceand switches to its own face oncedocument.fonts.loadlands. The switch is a change of xterm's font option, so xterm measures the cells again, and the screen is fitted to them. - Face already loaded: drawn in at once, and nothing is fetched.
- Face that fails to load: the terminal keeps the stand-in.
Tests
terminal/index.test.ts, through the bundle's own door (terminal.mount), reads the face the DOM renderer's rules draw the rows in:
- A face still loading is stood in for by
monospace, and the full stack is drawn in once the load lands. - A face already loaded is drawn in at once, and nothing is fetched.
Checked by hand
I drew the real Terminal tab full screen at 390×844 (3× scale, DOM renderer), typed ls, and shrank the stage to 390×508 for the keyboard:
- Before:
.xterm-screenwas 434 px wide in a 390 px tab, and lines were cut off at the right edge. - After: 371 px, lines wrap inside the screen, and the prompt stays above the keyboard.
Made with Luke