feat: replace WebView2+xterm.js with native Microsoft.Terminal.Wpf#8
Conversation
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>
|
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>
Integrate with VS's Unified Settings API to expose terminal font family and size configuration under Settings > Copilot CLI IDE Bridge. - Add IExternalSettingsProvider implementation (TerminalSettingsProvider) that dynamically enumerates installed monospace fonts via GDI+ - Add registration.json with external settings callback pattern - Add TerminalSettings helper to read font preferences from store - Wire font settings into TerminalToolWindowControl.SetTheme() - Proffer TerminalSettingsProvider service from the package The font family dropdown uses allowsFreeformInput so users can also type arbitrary font names. GetEnumChoicesAsync uses Task.Yield() as VS requires truly async completion for external enum providers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
VS 18 Canary moved Microsoft.Terminal.Wpf.dll from CommonExtensions\Microsoft\Terminal\ to CommonExtensions\Microsoft\Terminal\Terminal.Wpf\. Update the csproj HintPath to probe both locations at build time and the AssemblyResolve handler to check both paths at runtime. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
7b5f169 to
2cf43d4
Compare
When RestartSession is called (solution open), the native TerminalControl still has old buffer state and doesn't re-fire Resize since its own size hasn't changed. This causes garbled rendering until a manual resize. Fix: On SessionRestarted, send VT RIS (Reset to Initial State) to clear the control's buffer, then re-sync ConPTY dimensions with the control's last known size. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
TerminalControl doesn't re-fire Resize when only the underlying process changes (WPF size unchanged). Read Rows/Columns from the control's already-computed character grid and forward to the session service. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove verbose per-resize, per-settings-call, and routine lifecycle logging. Keep only error logs and important session start/stop/restart messages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Pulled the branch, built clean, all 284 tests pass. This is a huge improvement over the WebView2 approach. Some observations from reading through the code: What's great:
Minor observations:
I'm going to do hands-on testing in VS 2026 Enterprise and will report back with results. |
|
Tested the native-terminal branch in VS 2026 Enterprise. Everything works: terminal renders, typing is responsive, process restart on Enter works, resize works. Looks identical to the WebView2 version from a user perspective, which is the point. Nice work! One minor UX thing I noticed (pre-existing, not from this PR): clicking Tools > Copilot CLI Window doesn't auto-focus the terminal. I'll open a separate issue for that after this merges. |
- TerminalThemer: rename DarkTheme/LightTheme to _darkTheme/_lightTheme - TerminalThemer: use collection expressions for ColorTable arrays - TerminalSettingsProvider: use collection expression for empty array - TerminalToolWindowControl: use object initializer for TerminalControl Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- copilot-instructions.md: Add Unified Settings subsystem section, document TerminalSettings/TerminalSettingsProvider/registration.json, fix solution close lifecycle (RestartSession not StopSession) - CHANGELOG.md: Add missing [Unreleased] entries (font settings, Terminal.Wpf path resolution, ConPTY dimension sync) - README.md: Fix menu text to match .vsct (Launch/Show verbs) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
VS maps Escape to 'deactivate tool window', causing focus to jump to the editor when pressing Escape in the terminal. Fix by intercepting WM_KEYDOWN(VK_ESCAPE) in PreProcessMessage and forwarding the Kitty keyboard protocol escape sequence to ConPTY, matching VS's own TerminalWindowBase.EscKeyCode pattern exactly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add comment on Resize() thread safety assumption (lock in TerminalProcess) - Log warning when Microsoft.Terminal.Wpf.dll not found in either path Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Focus the TerminalControl after frame.Show() by yielding to a background thread first, then switching back to the UI thread. This lets VS finish its frame activation sequence before we set focus on the native terminal HWND. Without the yield, VS steals focus back during its own activation handling. Pattern taken from VS's own TerminalWindowBase.OnActiveFrameChanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
We should be good now, I addressed observations |
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:
SetTheme()How it works
Microsoft.Terminal.Wpf.dllships with every Visual Studio installation atCommonExtensions\Microsoft\Terminal\. Our extension references it at build time and resolves it at runtime via anAssemblyResolvehandler that locates the DLL from the VS install directory.The new
TerminalToolWindowControlimplementsITerminalConnection— a 4-member interface:WriteInput(string data)— user keystroke → ConPTYTerminalOutputevent — ConPTY output → native rendererResize(uint rows, uint columns)— dimensions changedClose()— cleanupThe ConPTY layer (
TerminalProcess,TerminalSessionService) is completely unchanged — same I/O pipeline, just a different consumer.Changes
New files
TerminalThemer.cs(79 lines) — VS theme →TerminalThemewith dark/light ANSI palettes (COLORREF/BGR format), auto-switches onVSColorTheme.ThemeChangedTerminalToolWindowControl.cs— rewritten asITerminalConnectionimplementation (183 lines, down from 209)Removed files
Resources/Terminal/terminal.html— WebView2 host pageResources/Terminal/terminal-app.js— xterm.js bridge, resize, I/OResources/Terminal/lib/xterm.js— xterm.js coreResources/Terminal/lib/xterm.css— xterm.js stylesResources/Terminal/lib/addon-fit.js— FitAddonResources/Terminal/lib/addon-webgl.js— WebglAddonModified files
CopilotCliIde.csproj— removed WebView2 NuGet + Terminal resources, added Terminal.Wpf assembly referenceCopilotCliIdePackage.cs— added staticAssemblyResolvehandler forMicrosoft.Terminal.WpfDirectory.Packages.props— removedMicrosoft.Web.WebView2package versionTerminalToolWindow.cs— simplified (removed WebView2-specificPreProcessMessage)TerminalSessionService.cs— removed stale commentpackage-lock.json— cleaned ghost xterm referencesDocumentation updated
.github/copilot-instructions.md— architecture now references Microsoft.Terminal.WpfREADME.md— terminal stack updatedCHANGELOG.md— migration documented under [Unreleased]Unchanged (ConPTY layer)
TerminalProcess.cs— ConPTY process managementTerminalSessionService.cs— session lifecycleConPty.cs— P/Invoke bindingsStats
Net removal of 322 lines — simpler codebase with better rendering.
Testing
ToolWindowBackgroundColorKeyNotes
Microsoft.Terminal.Wpf.dllis 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.AssemblyResolvehandler in the package's static constructor findsdevenv.exe's directory viaProcess.GetCurrentProcess().MainModule.FileName, then looks for the DLL atCommonExtensions\Microsoft\Terminal\.ITerminalConnection.Resizemay be called from a non-UI thread by the native control. The session start (which needsGetWorkspaceFolder()on the UI thread) is marshaled viaDispatcher.BeginInvoke.