Skip to content

fix: terminal sized incorrectly on first load until window resize - #1561

Open
jolly-exe wants to merge 2 commits into
tsl0922:mainfrom
jolly-exe:main
Open

jolly-exe wants to merge 2 commits into
tsl0922:mainfrom
jolly-exe:main

Conversation

@jolly-exe

@jolly-exe jolly-exe commented Jul 25, 2026 •

Copy link
Copy Markdown

Problem

When you first open a ttyd session the terminal doesn’t fill its container, leaving empty space along the right and bottom edges. The only way it corrects itself is if you resize the browser window.

Root cause

Xterm.open() calls fitAddon.fit() immediately after terminal.open(), while the default DOM renderer is still active. Shortly after that the SET_PREFERENCES message switches the renderer to webgl. Webgl measures cell sizes a little differently than the DOM renderer, but nothing triggers another fit after the switch, so the terminal keeps the stale dimensions until a real window resize happens.

Fix

applyPreferences() now calls fitAddon.fit() once after every preference has been applied, including the renderer type. This replaces the earlier font-only refit that never caught the renderer change.

While fixing that I also cleaned up a pre-existing build break. Preact’s RefCallback type now allows an optional cleanup return, so the bare assignment in terminal/index.tsx no longer type-checks. I wrapped the callback so it returns void and regenerated src/html.h from the updated frontend.

Verification

I built the production bundle together with the ttyd binary and served it against a mock of the websocket handshake in headless Chromium at 1000x700. Before the change the terminal loaded at cols=125 and a same-viewport resize event pushed it to cols=135. After the change it loads at cols=135 right away and the same resize does nothing. Both tsc --noEmit and npm run build pass cleanly.

jolly added 2 commits August 18, 2026 16:26
The initial fitAddon.fit() runs while xterm's dom renderer is active.
The default rendererType preference (webgl) then loads asynchronously
and measures cell size slightly differently, but nothing re-fits after
the swap, so cols/rows stay pinned to the stale dom-renderer size. The
terminal ends up smaller than its container until a window resize
forces a fresh fit under the correct renderer.

Fit once after all preferences (including renderer) are applied,
replacing the narrower font-only refit.
The RefCallback type now allows returning an optional cleanup function
(void | (() => void)), so the bare assignment expression no longer
type-checks and blocks the production build. Wrap it to return void.

Also regenerates src/html.h from the current frontend (includes the
terminal resize fix).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant