Office
Mobile terminal rotation: resize without corruption
Phone terminals break on rotation when session cols/rows are stale. Correctness requires measuring the viewport, sending Resize(cols, rows), and applying it server-side.
Published: 2026-01-02 · Last updated: 2026-01-04
Direct answer
Rotation breaks phone terminals because the session never receives the resize and still thinks it has the old cols/rows. The fix is not CSS. The fix is a resize contract: the client measures the terminal viewport, computes columns and rows, sends Resize(cols, rows) to the server, and the server applies it to the session. This must happen on orientation change, viewport resize, and any UI change that affects the terminal’s available space.
Mechanism (what “correct resize” means)
1) Terminals render into a grid
Terminal emulators render text into a grid of character cells:
- cols: how many characters fit across
- rows: how many lines fit vertically
Programs running inside the session (shell, editors, pagers) rely on those values for:
- line wrapping
- cursor movement
- full-screen redraw logic
If the browser changes size but the session does not, the session will emit escape codes based on the wrong geometry. The result looks like corruption.
2) The browser knows the viewport; the server controls the session
The client is the only component that can accurately measure the rendered terminal area (after headers, keyboards, safe areas, etc.).
The server is the only component that can resize the session.
So resize must be a message:
Resize(cols, rows)
3) Debounce and idempotency matter
On mobile, resize events can fire in bursts:
- rotation triggers multiple layout passes
- address bar shows/hides
- soft keyboard changes viewport height
A durable approach:
- debounce resize sends (e.g., 50–150ms)
- send only when
(cols, rows)actually changed - server applies the latest resize; older ones can be ignored
4) Resizing is a correctness feature, not a polish feature
If you do not treat resize as correctness, users will blame “the terminal” when the real bug is stale session geometry.
Common failure modes
Failure mode: “We resize the DOM, but not the session”
Symptom: text wraps incorrectly; full-screen apps become unusable.
Root cause: CSS makes the terminal container bigger, but the server never receives cols/rows.
Fix: client computes cols/rows and sends Resize; server applies to the session.
Failure mode: “We send resize, but it lags”
Symptom: rotation causes a period of corruption before it corrects.
Root cause: resize is debounced too aggressively, or not triggered on the right events.
Fix: trigger on orientation + resize + terminal fit events; use a small debounce.
Failure mode: “Keyboard causes hidden terminal area”
Symptom: typing opens the keyboard and the terminal becomes partially unusable.
Root cause: viewport measurement ignores the keyboard’s impact.
Fix: measure the actual visible container after the keyboard opens; send Resize again.
How to verify
-
Curses app test
- Run a full-screen terminal UI.
- Rotate repeatedly.
- Expected: redraw is clean; no persistent corruption.
-
Address bar and keyboard
- Scroll to hide/show address bar; focus an input to open keyboard.
- Expected: terminal refits and stays correct.
-
Resize flooding
- Simulate rapid resizes.
- Expected: server remains stable; terminal remains responsive.
Link up (pillar)
Read next (sibling)
Scope boundary
This note focuses on terminal correctness under viewport changes. It does not prescribe a UI framework or terminal emulator library.