Skip to content

fix(desktop): force WebGL repaint on load and fall back to DOM after context loss#3477

Open
hyrness wants to merge 1 commit intosuperset-sh:mainfrom
hyrness:fix/terminal-cjk-garbling
Open

fix(desktop): force WebGL repaint on load and fall back to DOM after context loss#3477
hyrness wants to merge 1 commit intosuperset-sh:mainfrom
hyrness:fix/terminal-cjk-garbling

Conversation

@hyrness
Copy link
Copy Markdown

@hyrness hyrness commented Apr 15, 2026

Description

Fixes intermittent garbling of CJK (and occasionally Latin) characters in the terminal that resolves when the text is selected with the mouse.

After #3252 (54e8a1c8), terminal attachment calls ensureSession via tRPC before connecting the WebSocket. This creates a timing window where the terminal can receive data — including wide/CJK characters — before the WebGL renderer has initialized (WebGL is deferred to requestAnimationFrame). During that window, cells are rendered by the DOM renderer. When WebGL takes over, it does not automatically repaint those pre-rendered cells, leaving wide characters in an inconsistent state in the texture atlas. Selecting the text forces a repaint which corrects the display.

Two fixes in terminal-addons.ts and helpers.ts:

  1. Force a full repaint after WebGL loads — call terminal.refresh(0, terminal.rows - 1) immediately after terminal.loadAddon(webglAddon) so all buffered cells are re-rendered through the WebGL renderer.
  2. Mark renderer as DOM after context loss — set suggestedRendererType = "dom" in the onContextLoss handler so subsequent terminals skip WebGL after a GPU context loss.

Related Issues

Fixes #3406

Type of Change

  • Bug fix

Testing

Run the desktop app and output CJK characters in the terminal (e.g. echo "こんにちは 你好"). Verify no garbling occurs on initial render and after switching workspaces/tabs.

Screenshots (if applicable)

Additional Notes

The garbling was intermittent and depended on timing between WebSocket data delivery and WebGL initialization, making it more likely to occur on slower machines or under load.


Summary by cubic

Fixes intermittent CJK and wide-character garbling in the desktop terminal by forcing a full repaint when WebGL initializes and falling back to the DOM renderer after GPU context loss. Ensures correct rendering on first load and after context issues.

  • Bug Fixes
    • After loading the WebGL addon, call terminal.refresh(0, terminal.rows - 1) to repaint all buffered cells through WebGL.
    • On WebGL context loss, dispose the addon and set suggestedRendererType = "dom" so subsequent terminals skip WebGL.

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

Summary by CodeRabbit

  • Bug Fixes
    • Improved terminal rendering reliability by properly handling WebGL context loss with graceful fallback and display refresh.
    • Fixed rendering issues with wide and CJK characters to ensure complete and accurate display in the terminal.

…context loss

After the ensureSession change (superset-sh#3252), terminals can receive data
(including wide/CJK characters) via the WebSocket before the WebGL
renderer initializes (deferred to rAF). When WebGL takes over, the
pre-rendered cells are not correctly re-rendered, causing intermittent
garbling that fixes on mouse selection.

Two fixes:
1. Call terminal.refresh() after loading the WebGL addon to force a
   full repaint of all buffered cells with the WebGL renderer.
2. Set suggestedRendererType = "dom" in the onContextLoss handler so
   that subsequent terminals in the same session skip WebGL after a
   GPU context loss.

Fixes superset-sh#3406
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 15, 2026

📝 Walkthrough

Walkthrough

This change fixes garbled wide and CJK character rendering in the terminal by ensuring the WebGL renderer repaints all content after addon initialization and by properly falling back to DOM rendering when WebGL context loss occurs.

Changes

Cohort / File(s) Summary
WebGL Terminal Rendering and Repaint Logic
apps/desktop/src/renderer/lib/terminal/terminal-addons.ts, apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts
Added explicit suggestedRendererType = "dom" assignment on WebGL context loss and forced full terminal repaint via terminal.refresh(0, terminal.rows - 1) after WebGL addon loading to ensure proper rendering of wide and CJK characters.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 Wide chars were lost in the WebGL glow,
So we refresh and repaint the show,
CJK characters dance so fine,
Now rendered perfect, line by line! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the main changes: forcing WebGL repaint on load and falling back to DOM after context loss, which directly address the intermittent character garbling issue.
Description check ✅ Passed The description is comprehensive, following the template with clear sections covering the bug context, specific fixes, related issues, type of change, and testing instructions.
Linked Issues check ✅ Passed The PR directly addresses issue #3406 by implementing two fixes: forcing WebGL repaint on load and falling back to DOM after context loss, which resolve the intermittent CJK character garbling reported.
Out of Scope Changes check ✅ Passed All changes are focused on fixing the WebGL rendering and fallback logic in terminal initialization and context loss handling, remaining within the scope of issue #3406.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 15, 2026

Greptile Summary

This PR applies two targeted fixes to the WebGL terminal renderer to eliminate intermittent CJK (and occasionally Latin) character garbling on initial load. The root cause is a timing window between WebSocket data delivery and WebGL's deferred requestAnimationFrame initialization, during which cells are rendered by the DOM renderer and never repainted when WebGL takes over.

  • Fix 1 — Force repaint after WebGL loads: Calls terminal.refresh(0, terminal.rows - 1) immediately after terminal.loadAddon(webglAddon) so all buffered cells (including wide/CJK characters already rendered by the DOM renderer) are fully re-rasterized through the WebGL path.
  • Fix 2 — Mark renderer as DOM on context loss: Sets suggestedRendererType = \"dom\" inside the onContextLoss handler so subsequent terminal instances skip WebGL entirely after a GPU context loss, avoiding the same issue on resource-constrained machines.
  • Both fixes are applied consistently to the v2 path (terminal-addons.ts) and the v1 terminal-cache path (helpers.ts).

Confidence Score: 5/5

Safe to merge — minimal, targeted changes with no risk of regressions.

Both fixes are logically sound and well-understood. refresh(0, rows-1) after loadAddon is the canonical way to force a full repaint in xterm.js, and setting suggestedRendererType = dom on context loss matches the established VS Code pattern already used in the catch block. The same two-line delta is applied symmetrically to both code paths (v1 and v2 terminal helpers), and no existing behaviour is altered in the non-error path beyond one extra synchronous repaint call per terminal open. No new state, no async complexity, no API surface changes.

No files require special attention.

Important Files Changed

Filename Overview
apps/desktop/src/renderer/lib/terminal/terminal-addons.ts Adds suggestedRendererType = dom on WebGL context loss and a forced full repaint after WebGL addon loads to fix CJK rendering garbling.
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts Mirrors the same two fixes from terminal-addons.ts for the v1 terminal cache path: DOM fallback on context loss and post-load refresh for CJK repaint.

Reviews (1): Last reviewed commit: "fix(desktop): force WebGL repaint on loa..." | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/desktop/src/renderer/lib/terminal/terminal-addons.ts (1)

46-65: Optional DRY cleanup: extract shared WebGL init/fallback block.

This rAF WebGL setup/fallback logic now exists in both apps/desktop/src/renderer/lib/terminal/terminal-addons.ts and apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts. A small shared helper would reduce drift risk.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/lib/terminal/terminal-addons.ts` around lines 46 -
65, Extract the duplicated WebGL init/fallback logic into a shared helper
function (e.g., initWebglRenderer) and replace the duplicated blocks in
terminal-addons.ts and Terminal/helpers.ts with calls to that helper; the helper
should accept the terminal instance and mutable state refs (webglAddon,
suggestedRendererType, disposed) or return updated values, perform the
requestAnimationFrame setup, create WebglAddon, register onContextLoss to
dispose and set suggestedRendererType = "dom" and call terminal.refresh(0,
terminal.rows - 1), call terminal.loadAddon(webglAddon), and catch errors to set
webglAddon = null and suggestedRendererType = "dom" so both sites reuse the same
robust init/fallback behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/desktop/src/renderer/lib/terminal/terminal-addons.ts`:
- Around line 46-65: Extract the duplicated WebGL init/fallback logic into a
shared helper function (e.g., initWebglRenderer) and replace the duplicated
blocks in terminal-addons.ts and Terminal/helpers.ts with calls to that helper;
the helper should accept the terminal instance and mutable state refs
(webglAddon, suggestedRendererType, disposed) or return updated values, perform
the requestAnimationFrame setup, create WebglAddon, register onContextLoss to
dispose and set suggestedRendererType = "dom" and call terminal.refresh(0,
terminal.rows - 1), call terminal.loadAddon(webglAddon), and catch errors to set
webglAddon = null and suggestedRendererType = "dom" so both sites reuse the same
robust init/fallback behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 031225a3-ccab-4a8c-998a-9500b1aa2cc4

📥 Commits

Reviewing files that changed from the base of the PR and between 1e23353 and c9ee064.

📒 Files selected for processing (2)
  • apps/desktop/src/renderer/lib/terminal/terminal-addons.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts

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 2 files

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] Sometimes the displayed Chinese characters are garbled.

1 participant