From 62a39dadb752d9da06486a7593f6349fbd89f6b3 Mon Sep 17 00:00:00 2001 From: Deng Liu Date: Sun, 8 Nov 2026 10:22:51 -0800 Subject: [PATCH] feat(zoom): route Increase/Decrease Font Size across editors, terminals and WebViews (#2172) Increase, Decrease and Reset Font Size only reached the active CodeMirror editor, so they did nothing with focus in a terminal or plugin WebView. They now apply to the focused surface through a shared workbench service: an editor tab, a terminal tab (which refits), or a plugin WebView. Wheel zoom stays pointer-based. Co-authored-by: dengliu <5108773+dengliu@users.noreply.github.com> --- src/editor/core/actions.ts | 33 ++++++++-- .../plugins/__tests__/webViews.test.tsx | 25 ++++++++ src/features/plugins/views/WebView.tsx | 7 ++- src/features/plugins/views/frame-bridge.js | 10 ++- src/features/terminal/copyKeys.test.ts | 33 ++++++++++ src/features/terminal/session.test.ts | 49 ++++++++++++++- src/features/terminal/session.ts | 24 ++++++- src/features/viewers/markdown/zoom.test.tsx | 62 +++++++++++++++++++ src/workbench/contributions.ts | 25 ++++++++ 9 files changed, 259 insertions(+), 9 deletions(-) diff --git a/src/editor/core/actions.ts b/src/editor/core/actions.ts index abc9389e1..fb82ead1b 100644 --- a/src/editor/core/actions.ts +++ b/src/editor/core/actions.ts @@ -6,6 +6,7 @@ import { foldEffect, syntaxTree, toggleFold } from "@codemirror/language"; import { acceptCompletion, completionStatus } from "@codemirror/autocomplete"; import { executeAction, registerActions, type Action } from "@/platform/actions"; import { getContext } from "@/platform/context"; +import { resetSurfaceFontZoom, stepFocusedSurfaceFontZoom } from "@/workbench/contributions"; import { editorController, useGotoLine, useTabs } from "./controller"; import { addCaretsToLineEnds, @@ -109,6 +110,27 @@ function withView(run: (view: EditorView, slot: EditorSlot) => unknown) { }; } +/** Routes keyboard font zoom to focus, then the active editor slot. */ +function stepSurfaceFontSize(delta: 1 | -1): void { + const activeEl = typeof document !== "undefined" ? (document.activeElement as HTMLElement | null) : null; + if (activeEl) { + if (stepFocusedSurfaceFontZoom(delta)) return; + const cmEl = activeEl.closest?.(".cm-editor") as HTMLElement | null; + if (cmEl) { + const cmView = EditorView.findFromDOM(cmEl); + if (cmView) { + stepFontZoom(cmView, delta); + return; + } + } + } + + const slot = activeSlot(); + if (!slot?.view) return; + stepFontZoom(slot.view, delta); + if (!slot.view.hasFocus && !getContext().popupOpen) slot.view.focus(); +} + // --- extend / shrink selection --------------------------------------------------- /** One stack per selection range (by index): ⌥↑ / ⌥↓ work on every caret. */ @@ -872,6 +894,9 @@ export function registerEditorActions(): () => void { run: () => { for (const ed of useEditorRegistry.getState().editors) if (ed.view.state.field(fontZoom, false)) ed.view.dispatch({ effects: setFontZoom.of(0) }); + if (typeof document !== "undefined") { + resetSurfaceFontZoom(); + } }, }, { @@ -879,16 +904,16 @@ export function registerEditorActions(): () => void { title: "Increase Font Size", category: "View", keywords: ["zoom", "font size"], - when: EDITOR_WHEN, - run: withView((view) => stepFontZoom(view, 1)), + when: "projectOpen", + run: () => stepSurfaceFontSize(1), }, { id: "editor.decreaseFontSize", title: "Decrease Font Size", category: "View", keywords: ["zoom", "font size"], - when: EDITOR_WHEN, - run: withView((view) => stepFontZoom(view, -1)), + when: "projectOpen", + run: () => stepSurfaceFontSize(-1), }, { id: "file.toggleReadOnly", diff --git a/src/features/plugins/__tests__/webViews.test.tsx b/src/features/plugins/__tests__/webViews.test.tsx index 84338837c..2674128da 100644 --- a/src/features/plugins/__tests__/webViews.test.tsx +++ b/src/features/plugins/__tests__/webViews.test.tsx @@ -102,6 +102,31 @@ describe("web view helpers", () => { }); describe("frame bridge", () => { + it("accepts bounded zoom only from its parent with the bridge tag", () => { + const script = /