Skip to content

fix: terminal canvas misalignment on zoom level change#309165

Open
ammaarrahmed wants to merge 1 commit intomicrosoft:mainfrom
ammaarrahmed:fix/terminal-zoom-layout-recalculation
Open

fix: terminal canvas misalignment on zoom level change#309165
ammaarrahmed wants to merge 1 commit intomicrosoft:mainfrom
ammaarrahmed:fix/terminal-zoom-layout-recalculation

Conversation

@ammaarrahmed
Copy link
Copy Markdown

@ammaarrahmed ammaarrahmed commented Apr 11, 2026

Summary

When the user changes the editor zoom level (Ctrl++/Ctrl+-), the integrated terminal canvas fails to repaint and align correctly. The prompt text gets clipped, disappears, or renders with excess blank space. Inline suggestion ghost text also misaligns.

Root Cause

The terminal's dimension calculations (getXtermScaledDimensions, _measureFont) use window.devicePixelRatio for canvas rendering and font measurements, but no listener existed to trigger a layout recalculation when the pixel ratio changed due to zoom. Switching tabs worked around the issue because setVisible(true) calls _resize(), which recalculates dimensions with the now-current DPR.

Fix

Two event listeners are added in the TerminalInstance constructor:

  • PixelRatio.onDidChange — fires when devicePixelRatio changes (e.g. browser zoom, display scale)
  • onDidChangeZoomLevel — fires from Electron's zoom API (e.g. Ctrl++/Ctrl+-)

Both trigger a shared handler that defers (50 ms for DOM settling) a full layout recalculation:

  1. Marks font metrics as stale (_layoutSettingsChanged = true)
  2. Clears the WebGL/canvas texture atlas (forceRedraw())
  3. Runs the full layout() path to recalculate cols/rows

Precedent

This matches the established pattern used by other VS Code components that already subscribe to PixelRatio.onDidChange:

  • Editor (editorDom.ts)
  • Color picker widget
  • Debug toolbar
  • Breadcrumbs widget
  • Notebook cells

Demo

Screencast.from.2026-04-11.10-28-43.webm

Testing Checklist

  • Ctrl++ / Ctrl+- — terminal repaints correctly, no clipping or blank space
  • Tab switching after zoom — still works as before
  • Split terminals — both panes recalculate correctly
  • Type-check passes (tsgo)
  • Layering check passes (valid-layers-check)
  • ESLint passes
  • Hygiene passes

How to Test

  1. Open an integrated terminal
  2. Type some text so the prompt is visible
  3. Press Ctrl++ or Ctrl+- to zoom in/out
  4. Observe the terminal canvas repaints cleanly without clipping, blank space, or misaligned ghost text

Fixes #309160

Copilot AI review requested due to automatic review settings April 11, 2026 09:30
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes integrated terminal canvas/text misalignment after zoom changes by triggering a terminal relayout when zoom/DPR changes, ensuring font measurements and xterm rendering are recalculated promptly.

Changes:

  • Subscribe to PixelRatio.onDidChange to react to devicePixelRatio changes and trigger a relayout.
  • Subscribe to onDidChangeZoomLevel to react to Electron zoom level changes and trigger the same relayout path.
  • Force an xterm redraw and mark layout settings as stale before recalculating layout/resize.

Comment thread src/vs/workbench/contrib/terminal/browser/terminalInstance.ts Outdated
@ammaarrahmed
Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

When the user changes the editor zoom level (Ctrl++/Ctrl+-), the
integrated terminal canvas failed to repaint and align correctly.
The prompt text would get clipped, disappear, or render with excess
blank space. Inline suggestion ghost text also misaligned.

Root cause: the terminal's dimension calculations use
window.devicePixelRatio for canvas rendering and font measurements,
but no listener existed to trigger a layout recalculation when the
pixel ratio changed due to zoom.

This adds two event listeners in the TerminalInstance constructor:
- PixelRatio.onDidChange: fires when devicePixelRatio changes
- onDidChangeZoomLevel: fires from Electron's zoom API

Both trigger a deferred (50ms) full layout recalculation that:
1. Marks font metrics as stale (_layoutSettingsChanged = true)
2. Clears the WebGL/canvas texture atlas (forceRedraw)
3. Runs the full layout() path to recalculate cols/rows

This matches the established pattern used by the editor, color picker,
debug toolbar, breadcrumbs, and notebook components, all of which
already subscribe to PixelRatio.onDidChange.

Fixes microsoft#309160

Signed-off-by: Ammaar Ahmed <ammaarlatif53@gmail.com>
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.

Terminal: Missing devicePixelRatio listener causes misalignment on zoom

3 participants