fix(desktop): reset the GPU renderer when a parked terminal comes back
What & why
A terminal pane that comes back from the parking container can paint stale glyphs over cells xterm's buffer has right. It stays mangled indefinitely, and clears the instant anything changes the pane's width — dragging the diff sidebar open, resizing the window.
Both surfaces already refit and refresh(0, rows - 1) on reattach (v1-terminal-cache.ts, terminal-runtime.ts), and the ResizeObserver they install fires an initial callback on observe(), so that path does run. It isn't enough: WebglRenderer._updateModel skips every cell whose cached model entry still matches the buffer cell (WebglRenderer.ts:571-576), so once that model has drifted from the pixels actually on screen, a refresh repaints nothing. handleResize is what recovers it, because it calls _clearModel() and forces a synchronous full redraw — that's why a resize cures it and a refresh doesn't.
clearTextureAtlas() is the same model invalidation without the dimension change: _charAtlas.clearTexture() + _clearModel(true) + _requestRedrawViewport(). So on reattach-from-parked, when the refit produced no dimension change, reset the renderer instead of refreshing. Forcing a cols change would also work and is what users do by hand, but it SIGWINCHes every TUI in the pane, reflows the whole scrollback, and trips the host's resize sync boundary (lastResizeSeq), which reanchors every other client attached to the session.
Also ports the atlas page-add reset that v2 has had since SUPER-1793 to the v1 path, which never got it.
Relates to #3321 and #3309, and to #3504 / #3351 — all closed in the July 2026 stale sweep (#5605), which grouped them as "repaint / ghosting on focus / workspace / tab switch — xterm viewport repaint plus DOM parking/reattach timing" and closed them for want of a harness rather than a diagnosis.
How I tested it
bun test in apps/desktop: 348 pass in src/renderer/lib/terminal/, 70 pass in the v1 Terminal/ tree, including three new tests for the primitive. bun run lint and bun run typecheck pass.
What led me here, on 1.29.0: three mangled panes, all long-lived background Claude sessions. superset terminals read returned clean, coherent screens for every one of them at the same 192x80 the pane was at — the host's own emulator, fed the same PTY bytes, disagreed with what was on screen. Opening the diff sidebar repaired one instantly, which rules out lost bytes: no program can redraw scrollback, so text that reappears on resize was in xterm's buffer all along. That puts the defect in the paint layer, and the addon source above explains why the existing refresh can't clear it.
No before/after screenshots, because I can't reproduce the corrupted state on demand — it took hours of idling to appear on its own, so I have not watched this patch clear it. The argument that it does is the addon source, not an observation. Worth a CDP check per apps/desktop/AGENTS.md before trusting it.
Scope worth flagging for review: unpark is the path this covers. A pane that mangles while it stays focused and attached is only addressed indirectly, by the atlas-growth reset — if unbounded atlas growth isn't that mechanism, that case needs its own trigger. Given the host demonstrably holds a correct screen, the stronger option there is to have the renderer compare itself against it on a quiet stream and reset on a persistent mismatch.
Checklist
- PR title follows conventional commits (
type(scope): subject) -
bun run lintandbun run typecheckpass (CI fails on lint warnings too) - "Allow edits from maintainers" is checked on fork PRs
Summary by cubic
Resets the WebGL renderer when a parked terminal pane comes back, so stale glyphs get repainted instead of lingering until a resize.
Bug Fixes
- Clears the renderer's glyph atlas and cached model on reattach when the refit didn't change dimensions; a plain
refresh()is skipped cell-by-cell once that model drifts from what's on screen. - Avoids forcing a resize, which would SIGWINCH every TUI, reflow the scrollback, and reanchor other clients through the host's resize sync.
- Ports the v2 atlas page-add reset to the v1 renderer path so truecolor-heavy TUIs can't grow the glyph atlas without bound.
Summary by CodeRabbit
-
Bug Fixes
- Fixed terminal displays that could show stale or missing glyphs after being restored, resized, or reused.
- Improved terminal refresh behavior when WebGL rendering is unavailable or terminal dimensions remain unchanged.
- Ensured empty terminals refresh safely without errors.
-
Tests
- Added coverage for renderer resets, fallback repainting, refresh ordering, and zero-row terminals.