Skip to content

fix(desktop): restore terminal buffer after Unicode 11 activation#3581

Merged
Kitenite merged 2 commits into
mainfrom
fix/terminal-cjk-garbled-unicode11-order
Apr 20, 2026
Merged

fix(desktop): restore terminal buffer after Unicode 11 activation#3581
Kitenite merged 2 commits into
mainfrom
fix/terminal-cjk-garbled-unicode11-order

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Apr 20, 2026

Summary

Fixes #3572 — garbled CJK/Latin rendering with many Claude Code tabs open.

  • Load xterm addons (and activate unicode.activeVersion = "11") before replaying the persisted terminal buffer. Previously restoreBuffer ran first, so xterm parsed CJK / emoji / ZWJ sequences using Unicode 6 cell widths and baked the wrong widths into the restored buffer — producing the garbled glyphs on repaint that the issue reporters and @johann-taberlet both observed (resizing the window forces a reflow, which is why that "fixes" it temporarily).
  • This mirrors VS Code's pattern: _updateUnicodeVersion() is called during terminal construction (xtermTerminal.ts:302), before any write or attachToElement.
  • Bumps @xterm/* to the versions VS Code currently ships (xterm/unicode11/etc. 6.1.0-beta.197, webgl 0.20.0-beta.196). We were 2 beta versions behind across the board.

What I considered and didn't do

The bot investigation noted onContextLoss in terminal-addons.ts doesn't flip the shared suggestedRendererType to "dom", so subsequent terminals keep retrying WebGL after a cascading context-loss. I tried adding that fallback, but VS Code deliberately doesn't do it either (xtermTerminal.ts:853-856 — only a WebGL load failure flips the flag, not context loss) because a transient GPU hiccup shouldn't disable WebGL app-wide. Leaving our behavior aligned with VS Code.

If CJK corruption returns after this lands under heavy multi-tab usage, the next thing to investigate is the WebGL context cap / cascading context-loss path — but that's a separate issue and a more invasive change.

Test plan

  • Open desktop app, create 7–8 Claude Code tabs, paste Chinese content, switch between tabs, reload workspace — verify no garbled glyphs in persisted terminal buffers
  • Confirm terminals still render non-CJK content correctly
  • Verify WebGL renderer still activates (no regression from addon load-order change)

Summary by cubic

Fixes garbled CJK/emoji rendering in restored terminals by activating Unicode 11 before replaying the buffer. Aligns terminal init with VS Code to prevent wrong cell widths after reloads and tab switches.

  • Bug Fixes

    • Load addons (activates unicode.activeVersion = "11") before restoreBuffer(...) so CJK/emoji/ZWJ sequences use Unicode 11 widths.
    • Tightened the inline comment to document the required ordering and avoid regressions.
  • Dependencies

    • Bump @xterm/xterm and addons to 6.1.0-beta.197 and @xterm/addon-webgl to 0.20.0-beta.196 to match VS Code.

Written for commit ea65a58. Summary will update on new commits.

Summary by CodeRabbit

  • Chores

    • Updated terminal emulator dependencies to newer beta versions.
  • Bug Fixes

    • Ensured terminal buffer restoration happens after terminal addons finish initializing, improving restored content consistency.

The persisted xterm buffer was being replayed before the Unicode11Addon
was loaded, so CJK, emoji, and ZWJ sequences got parsed with Unicode 6
cell widths. The wrong widths baked into the buffer, producing garbled
glyphs on repaint — especially visible with many Claude Code tabs open
and Chinese content (#3572).

Mirrors VS Code's pattern: load Unicode11Addon during terminal
construction, before the first write. Also bumps @xterm/* to the
versions VS Code ships (xterm 6.1.0-beta.197, webgl 0.20.0-beta.196).
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c84b0a34-a2dc-4f61-be04-42d46dc1789b

📥 Commits

Reviewing files that changed from the base of the PR and between afcf90e and ea65a58.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/lib/terminal/terminal-runtime.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/src/renderer/lib/terminal/terminal-runtime.ts

📝 Walkthrough

Walkthrough

Deferred terminal buffer restoration until xterm addons finish loading; updated several @xterm/* package versions in the desktop app package.json.

Changes

Cohort / File(s) Summary
xterm dependency updates
apps/desktop/package.json
Bumped @xterm/addon-clipboard, @xterm/addon-fit, @xterm/addon-image, @xterm/addon-ligatures, @xterm/addon-progress, @xterm/addon-search, @xterm/addon-serialize, @xterm/addon-unicode11, @xterm/headless, @xterm/xterm from beta.195beta.197; @xterm/addon-webgl from beta.194beta.196.
Terminal runtime initialization reordering
apps/desktop/src/renderer/lib/terminal/terminal-runtime.ts
Moved restoreBuffer(terminalId, terminal) to occur after loadAddons(terminal) completes; loadAddons result (e.g., searchAddon, progressAddon, dispose) is captured and included in the returned TerminalRuntime prior to buffer replay.

Sequence Diagram(s)

sequenceDiagram
    participant App as Desktop App
    participant Terminal as Terminal Instance
    participant AddonLoader as Addon Loader
    participant BufferStore as Buffer Restore
    App->>Terminal: createRuntime(wrapper, terminalId)
    Terminal->>Terminal: terminal.open(wrapper)
    Terminal->>AddonLoader: loadAddons(terminal)
    AddonLoader-->>Terminal: addonsResult (search, progress, dispose, ...)
    Terminal->>BufferStore: restoreBuffer(terminalId, terminal)
    BufferStore-->>Terminal: replay buffer
    Terminal-->>App: return TerminalRuntime (includes addons and dispose)
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

Poem

🐰
When addons wake and then restore,
Buffers hop in, neat and sure.
No more garble, lines in tune,
Terminal hums beneath the moon.
Beta leaps, the rabbit cheers—clear rune!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly describes the main change: ensuring terminal buffer restoration occurs after Unicode 11 activation, directly addressing the fix for garbled CJK rendering.
Description check ✅ Passed Description is comprehensive with clear summary, related issue link, change rationale, considerations, and test plan covering all required template sections effectively.
Linked Issues check ✅ Passed Changes fully address issue #3572 objectives: addon loading reordered to activate Unicode 11 before buffer replay, xterm packages bumped to match VS Code versions, and WebGL context-loss behavior kept aligned with VS Code.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing CJK/Unicode rendering: dependency version bumps in package.json and buffer restoration ordering in terminal-runtime.ts align with the linked issue requirements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/terminal-cjk-garbled-unicode11-order

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 20, 2026

Greptile Summary

This PR fixes garbled CJK/emoji rendering when restoring persisted terminal buffers in the desktop app. The root cause was that restoreBuffer was called before loadAddons, meaning xterm parsed multi-byte sequences using Unicode 6 cell widths and baked those incorrect widths into the restored buffer. The fix reorders the two calls so the Unicode 11 addon is activated synchronously before any buffer data is written. The PR also bumps all @xterm/* packages by 2 beta versions to align with VS Code's current pinned versions.

Key changes:

  • In createRuntime(), loadAddons(terminal) is now called before restoreBuffer(terminalId, terminal), ensuring terminal.unicode.activeVersion = \"11\" is set before xterm processes the replayed buffer data.
  • All @xterm/* addons bumped from beta.195beta.197 (and addon-webgl from beta.194beta.196).
  • The PR correctly notes that VS Code's own _updateUnicodeVersion() is called during terminal construction before any write or attachToElement, and this change mirrors that pattern.

Confidence Score: 5/5

Safe to merge — the fix is minimal, correct, and well-justified by VS Code's own initialization pattern.

The one-line reorder is the right fix: terminal.unicode.activeVersion = "11" is set synchronously inside loadAddons before it returns, so by the time restoreBuffer calls terminal.write(), the Unicode 11 width tables are already registered. The async write queue in xterm ensures the data is parsed with the correct widths when it's actually processed. Package bumps are minor and consistent. No logic errors, no security concerns.

No files require special attention.

Important Files Changed

Filename Overview
apps/desktop/src/renderer/lib/terminal/terminal-runtime.ts Core fix: moves loadAddons before restoreBuffer in createRuntime() so Unicode 11 cell widths are active before the buffer is replayed; logic is correct and minimal.
apps/desktop/package.json Bumps all @xterm/* packages 2 beta versions (195→197, webgl 194→196) to match VS Code's current pinned versions; straightforward dependency update.
bun.lock Auto-generated lockfile updated to reflect the xterm version bumps in package.json; no manual review needed.

Sequence Diagram

sequenceDiagram
    participant CR as createRuntime()
    participant XT as XTerm instance
    participant LA as loadAddons()
    participant U11 as Unicode11Addon
    participant RB as restoreBuffer()
    participant LS as localStorage

    CR->>XT: new XTerm() + open(wrapper)
    Note over CR,XT: Before fix: restoreBuffer ran here (Unicode 6 widths active)
    CR->>LA: loadAddons(terminal)
    LA->>XT: loadAddon(Unicode11Addon)
    LA->>XT: unicode.activeVersion = "11"
    Note over XT: Unicode 11 width tables now active
    LA-->>CR: searchAddon, progressAddon, dispose
    CR->>RB: restoreBuffer(terminalId, terminal)
    RB->>LS: getItem(terminal-buffer:id)
    LS-->>RB: serialized VT data
    RB->>XT: terminal.write(data)
    Note over XT: Parses CJK/emoji/ZWJ with correct Unicode 11 widths
Loading

Reviews (1): Last reviewed commit: "fix(desktop): restore terminal buffer af..." | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 20, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch
  • ✅ Electric Fly.io app

Thank you for your contribution! 🎉

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.

[bug] Intermittent garbled text rendering with multiple Claude Code tabs and Chinese content

1 participant