Skip to content

feat: replace WebView2+xterm.js with native Microsoft.Terminal.Wpf#8

Open
sailro wants to merge 2 commits intomainfrom
native-terminal
Open

feat: replace WebView2+xterm.js with native Microsoft.Terminal.Wpf#8
sailro wants to merge 2 commits intomainfrom
native-terminal

Conversation

@sailro
Copy link
Copy Markdown
Owner

@sailro sailro commented Apr 12, 2026

Replace WebView2+xterm.js with native Microsoft.Terminal.Wpf

Summary

Replace the Chromium-based terminal renderer (WebView2 + xterm.js) with VS's built-in native terminal control (Microsoft.Terminal.Wpf) — the same DirectWrite rendering engine used by Windows Terminal and VS's own integrated terminal.

Motivation

The embedded terminal (added in PR #7) used WebView2 to host xterm.js. While functional, this carried significant overhead:

WebView2 + xterm.js (before) Microsoft.Terminal.Wpf (after)
Renderer Chromium Canvas/WebGL Native Win32 DirectWrite
VT parsing JavaScript (xterm.js) Native C++ (Windows Terminal engine)
Memory ~80MB (Chromium process) ~5MB (in-process WPF control)
Startup Slow (Chromium init + page load) Instant (WPF control)
Dependencies WebView2 runtime + 6 JS files None (ships with VS)
Focus Complex WPF↔Chromium recovery hack Native WPF focus model
Theme Hardcoded dark theme in JS VS theme integration via SetTheme()
Box-drawing Needed WebGL addon workaround Perfect natively

How it works

Microsoft.Terminal.Wpf.dll ships with every Visual Studio installation at CommonExtensions\Microsoft\Terminal\. Our extension references it at build time and resolves it at runtime via an AssemblyResolve handler that locates the DLL from the VS install directory.

The new TerminalToolWindowControl implements ITerminalConnection — a 4-member interface:

  • WriteInput(string data) — user keystroke → ConPTY
  • TerminalOutput event — ConPTY output → native renderer
  • Resize(uint rows, uint columns) — dimensions changed
  • Close() — cleanup

The ConPTY layer (TerminalProcess, TerminalSessionService) is completely unchanged — same I/O pipeline, just a different consumer.

Changes

New files

  • TerminalThemer.cs (79 lines) — VS theme → TerminalTheme with dark/light ANSI palettes (COLORREF/BGR format), auto-switches on VSColorTheme.ThemeChanged
  • TerminalToolWindowControl.cs — rewritten as ITerminalConnection implementation (183 lines, down from 209)

Removed files

  • Resources/Terminal/terminal.html — WebView2 host page
  • Resources/Terminal/terminal-app.js — xterm.js bridge, resize, I/O
  • Resources/Terminal/lib/xterm.js — xterm.js core
  • Resources/Terminal/lib/xterm.css — xterm.js styles
  • Resources/Terminal/lib/addon-fit.js — FitAddon
  • Resources/Terminal/lib/addon-webgl.js — WebglAddon

Modified files

  • CopilotCliIde.csproj — removed WebView2 NuGet + Terminal resources, added Terminal.Wpf assembly reference
  • CopilotCliIdePackage.cs — added static AssemblyResolve handler for Microsoft.Terminal.Wpf
  • Directory.Packages.props — removed Microsoft.Web.WebView2 package version
  • TerminalToolWindow.cs — simplified (removed WebView2-specific PreProcessMessage)
  • TerminalSessionService.cs — removed stale comment
  • package-lock.json — cleaned ghost xterm references

Documentation updated

  • .github/copilot-instructions.md — architecture now references Microsoft.Terminal.Wpf
  • README.md — terminal stack updated
  • CHANGELOG.md — migration documented under [Unreleased]

Unchanged (ConPTY layer)

  • TerminalProcess.cs — ConPTY process management
  • TerminalSessionService.cs — session lifecycle
  • ConPty.cs — P/Invoke bindings
  • All MCP server files — terminal is client-side only

Stats

16 files changed, 317 insertions(+), 639 deletions(-)

Net removal of 322 lines — simpler codebase with better rendering.

Testing

  • Build clean (0 errors, 0 warnings)
  • 284 server tests pass
  • Roslyn dead code analysis clean (1 pre-existing unused constant)
  • Manual testing: Copilot CLI renders with full ANSI colors, box-drawing characters, status bar, interactive prompt
  • Theme integration: dark background from VS ToolWindowBackgroundColorKey
  • Session restart (Enter after process exit) works
  • Resize handling (dock panel drag) works
  • VS 2022 compatibility (built/tested on VS 2026 Insiders only)
  • Light theme testing

Notes

  • Microsoft.Terminal.Wpf.dll is not bundled in the VSIX — it resolves from the VS install directory at runtime. This avoids redistribution concerns and ensures version compatibility with the host VS.
  • The AssemblyResolve handler in the package's static constructor finds devenv.exe's directory via Process.GetCurrentProcess().MainModule.FileName, then looks for the DLL at CommonExtensions\Microsoft\Terminal\.
  • ITerminalConnection.Resize may be called from a non-UI thread by the native control. The session start (which needs GetWorkspaceFolder() on the UI thread) is marshaled via Dispatcher.BeginInvoke.
image image

Use VS's built-in terminal rendering control (same as Windows Terminal).
Eliminates Chromium dependency, ~80MB memory reduction, instant startup,
native DirectWrite rendering, VS theme integration.

- Implement ITerminalConnection in TerminalToolWindowControl
- Add TerminalThemer for VS dark/light theme colors
- Remove WebView2, xterm.js, addon-fit, addon-webgl
- Reference VS-deployed Microsoft.Terminal.Wpf.dll (Private=false)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@sailro
Copy link
Copy Markdown
Owner Author

sailro commented Apr 12, 2026

Hey @bommerts, thank you again for the initial prototype. I tried to move to the native terminal support that we have in VS, and it worked. I need more testing of course, but it could be great.

- Replace WebView2+xterm.js terminal with VS's built-in Microsoft.Terminal.Wpf
- Use VsInstallRoot HintPath for CI-compatible assembly resolution
- Add AppDomain.AssemblyResolve handler for runtime DLL loading
- Add TerminalThemer for VS dark/light theme integration
- Remove WebView2 NuGet, xterm.js resources, and related code
- Update docs, changelog, and squad files for new terminal stack

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.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.

1 participant