diff --git a/src/vs/workbench/electron-sandbox/window.ts b/src/vs/workbench/electron-sandbox/window.ts index 9a52c01defa..8239e05c46e 100644 --- a/src/vs/workbench/electron-sandbox/window.ts +++ b/src/vs/workbench/electron-sandbox/window.ts @@ -13,7 +13,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { EditorResourceAccessor, IUntitledTextResourceEditorInput, SideBySideEditor, pathsToEditors, IResourceDiffEditorInput, IUntypedEditorInput, IEditorPane, isResourceEditorInput, IResourceMergeEditorInput } from 'vs/workbench/common/editor'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { WindowMinimumSize, IOpenFileRequest, IWindowsConfiguration, getTitleBarStyle, IAddFoldersRequest, INativeRunActionInWindowRequest, INativeRunKeybindingInWindowRequest, INativeOpenFileRequest, IWindowSettings } from 'vs/platform/window/common/window'; +import { WindowMinimumSize, IOpenFileRequest, getTitleBarStyle, IAddFoldersRequest, INativeRunActionInWindowRequest, INativeRunKeybindingInWindowRequest, INativeOpenFileRequest } from 'vs/platform/window/common/window'; import { ITitleService } from 'vs/workbench/services/title/browser/titleService'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { ApplyZoomTarget, applyZoom } from 'vs/platform/window/electron-sandbox/window'; @@ -26,7 +26,7 @@ import { IMenuService, MenuId, IMenu, MenuItemAction, MenuRegistry } from 'vs/pl import { ICommandAction } from 'vs/platform/action/common/action'; import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { RunOnceScheduler } from 'vs/base/common/async'; -import { DisposableStore } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { LifecyclePhase, ILifecycleService, WillShutdownEvent, ShutdownReason, BeforeShutdownErrorEvent, BeforeShutdownEvent } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces'; import { IIntegrityService } from 'vs/workbench/services/integrity/common/integrity'; @@ -73,13 +73,10 @@ import { registerWindowDriver } from 'vs/workbench/services/driver/electron-sand import { mainWindow } from 'vs/base/browser/window'; import { BaseWindow } from 'vs/workbench/browser/window'; import { IHostService } from 'vs/workbench/services/host/browser/host'; +import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from 'vs/workbench/services/statusbar/browser/statusbar'; export class NativeWindow extends BaseWindow { - private touchBarMenu: IMenu | undefined; - private readonly touchBarDisposables = this._register(new DisposableStore()); - private lastInstalledTouchedBar: ICommandAction[][] | undefined; - private readonly customTitleContextMenuDisposable = this._register(new DisposableStore()); private readonly addFoldersScheduler = this._register(new RunOnceScheduler(() => this.doAddFolders(), 100)); @@ -330,29 +327,19 @@ export class NativeWindow extends BaseWindow { this.configurationService.updateValue(setting, false, ConfigurationTarget.USER_LOCAL); }); - // Zoom level changes + // Window Zoom this._register(this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration('window.zoomLevel')) { - this.updateWindowZoomLevel(); + this.onDidChangeConfiguredWindowZoomLevel(); } else if (e.affectsConfiguration('keyboard.touchbar.enabled') || e.affectsConfiguration('keyboard.touchbar.ignored')) { this.updateTouchbarMenu(); } })); - this._register(onDidChangeZoomLevel(targetWindowId => { - if (targetWindowId !== mainWindow.vscodeWindowId) { - return; // only update our own window - } + this._register(onDidChangeZoomLevel(targetWindowId => this.handleOnDidChangeZoomLevel(targetWindowId))); - const configuredWindowZoomLevel = this.configurationService.getValue('window')?.zoomLevel; - const currentWindowZoomLevel = getZoomLevel(mainWindow); - - let notifyZoomLevel: number | undefined = undefined; - if (configuredWindowZoomLevel !== currentWindowZoomLevel) { - notifyZoomLevel = currentWindowZoomLevel; - } - - ipcRenderer.invoke('vscode:notifyZoomLevel', notifyZoomLevel); + this._register(this.editorGroupService.onDidCreateAuxiliaryEditorPart(({ instantiationService, disposables, part }) => { + this.createResetWindowZoomStatusEntry(instantiationService, part.windowId, disposables); })); // Listen to visible editor changes (debounced in case a new editor opens immediately after) @@ -430,6 +417,8 @@ export class NativeWindow extends BaseWindow { this._register(this.lifecycleService.onWillShutdown(e => this.onWillShutdown(e))); } + //#region Window Lifecycle + private onBeforeShutdown({ veto, reason }: BeforeShutdownEvent): void { if (reason === ShutdownReason.CLOSE) { const confirmBeforeCloseSetting = this.configurationService.getValue<'always' | 'never' | 'keyboardOnly'>('window.confirmBeforeClose'); @@ -578,6 +567,8 @@ export class NativeWindow extends BaseWindow { } } + //#endregion + private updateDocumentEdited(documentEdited: true | undefined): void { let setDocumentEdited: boolean; if (typeof documentEdited === 'boolean') { @@ -638,23 +629,6 @@ export class NativeWindow extends BaseWindow { } } - private updateWindowZoomLevel(): void { - const windowConfig = this.configurationService.getValue(); - const windowZoomLevel = typeof windowConfig.window?.zoomLevel === 'number' ? windowConfig.window.zoomLevel : 0; - - let applyZoomLevel = false; - for (const { window } of getWindows()) { - if (getZoomLevel(window) !== windowZoomLevel) { - applyZoomLevel = true; - break; - } - } - - if (applyZoomLevel) { - applyZoom(windowZoomLevel, ApplyZoomTarget.ALL_WINDOWS); - } - } - private provideCustomTitleContextMenu(filePath: string | undefined): void { // Clear old menu @@ -708,6 +682,11 @@ export class NativeWindow extends BaseWindow { // Touchbar menu (if enabled) this.updateTouchbarMenu(); + // Zoom status + for (const { window, disposables } of getWindows()) { + this.createResetWindowZoomStatusEntry(this.instantiationService, window.vscodeWindowId, disposables); + } + // Smoke Test Driver if (this.environmentService.enableSmokeTestDriver) { this.setupDriver(); @@ -913,6 +892,12 @@ export class NativeWindow extends BaseWindow { }); } + //#region Touchbar + + private touchBarMenu: IMenu | undefined; + private readonly touchBarDisposables = this._register(new DisposableStore()); + private lastInstalledTouchedBar: ICommandAction[][] | undefined; + private updateTouchbarMenu(): void { if (!isMacintosh) { return; // macOS only @@ -981,6 +966,8 @@ export class NativeWindow extends BaseWindow { } } + //#endregion + private onAddFoldersRequest(request: IAddFoldersRequest): void { // Buffer all pending requests @@ -1064,4 +1051,101 @@ export class NativeWindow extends BaseWindow { return this.editorService.openEditors(editors, undefined, { validateTrust: true }); } + + //#region Window Zoom + + private readonly mapWindowIdToResetZoomStatusEntry = new Map(); + + private configuredWindowZoomLevel = this.resolveConfiguredWindowZoomLevel(); + + private resolveConfiguredWindowZoomLevel(): number { + const windowZoomLevel = this.configurationService.getValue('window.zoomLevel'); + + return typeof windowZoomLevel === 'number' ? windowZoomLevel : 0; + } + + private handleOnDidChangeZoomLevel(targetWindowId: number): void { + + // Zoom status entry + this.updateResetWindowZoomStatusEntry(targetWindowId); + + // Notify main process about a custom zoom level + if (targetWindowId === mainWindow.vscodeWindowId) { + const currentWindowZoomLevel = getZoomLevel(mainWindow); + + let notifyZoomLevel: number | undefined = undefined; + if (this.configuredWindowZoomLevel !== currentWindowZoomLevel) { + notifyZoomLevel = currentWindowZoomLevel; + } + + ipcRenderer.invoke('vscode:notifyZoomLevel', notifyZoomLevel); + } + } + + private createResetWindowZoomStatusEntry(instantiationService: IInstantiationService, targetWindowId: number, disposables: DisposableStore): void { + this.mapWindowIdToResetZoomStatusEntry.set(targetWindowId, disposables.add(instantiationService.createInstance(ResetZoomStatusEntry))); + disposables.add(toDisposable(() => this.mapWindowIdToResetZoomStatusEntry.delete(targetWindowId))); + + this.updateResetWindowZoomStatusEntry(targetWindowId); + } + + private updateResetWindowZoomStatusEntry(targetWindowId: number): void { + const targetWindow = getWindowById(targetWindowId); + const entry = this.mapWindowIdToResetZoomStatusEntry.get(targetWindowId); + if (entry && targetWindow) { + entry.updateResetZoomEntry(getZoomLevel(targetWindow.window) !== this.configuredWindowZoomLevel); + } + } + + private onDidChangeConfiguredWindowZoomLevel(): void { + this.configuredWindowZoomLevel = this.resolveConfiguredWindowZoomLevel(); + + let applyZoomLevel = false; + for (const { window } of getWindows()) { + if (getZoomLevel(window) !== this.configuredWindowZoomLevel) { + applyZoomLevel = true; + break; + } + } + + if (applyZoomLevel) { + applyZoom(this.configuredWindowZoomLevel, ApplyZoomTarget.ALL_WINDOWS); + } + } + + //#endregion + + override dispose(): void { + super.dispose(); + + for (const [, entry] of this.mapWindowIdToResetZoomStatusEntry) { + entry.dispose(); + } + } +} + +class ResetZoomStatusEntry extends Disposable { + + private readonly resetZoomStatusEntry = this._register(new MutableDisposable()); + + constructor(@IStatusbarService private readonly statusbarService: IStatusbarService) { + super(); + } + + updateResetZoomEntry(visible: boolean): void { + if (visible) { + if (!this.resetZoomStatusEntry.value) { + const text = localize('resetZoom', "Reset Zoom"); + this.resetZoomStatusEntry.value = this.statusbarService.addEntry({ + name: localize('status.resetWindowZoom', "Reset Window Zoom"), + text, + ariaLabel: text, + command: 'workbench.action.zoomReset', + kind: 'prominent' + }, 'status.resetWindowZoom', StatusbarAlignment.RIGHT, 102); + } + } else { + this.resetZoomStatusEntry.clear(); + } + } } diff --git a/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts b/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts index a9ae966b65b..b7e1b0ef394 100644 --- a/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts +++ b/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts @@ -11,7 +11,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { DisposableStore } from 'vs/base/common/lifecycle'; import { INativeHostService } from 'vs/platform/native/common/native'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { CodeWindow, mainWindow } from 'vs/base/browser/window'; +import { CodeWindow } from 'vs/base/browser/window'; import { mark } from 'vs/base/common/performance'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { NativeWindow } from 'vs/workbench/electron-sandbox/window'; @@ -22,6 +22,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { IHostService } from 'vs/workbench/services/host/browser/host'; import { applyZoom } from 'vs/platform/window/electron-sandbox/window'; import { getZoomLevel } from 'vs/base/browser/browser'; +import { getActiveWindow } from 'vs/base/browser/dom'; type NativeCodeWindow = CodeWindow & { readonly vscode: ISandboxGlobals; @@ -89,7 +90,7 @@ export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService if (typeof options?.zoomLevel === 'number') { windowZoomLevel = options.zoomLevel; } else { - windowZoomLevel = getZoomLevel(mainWindow); + windowZoomLevel = getZoomLevel(getActiveWindow()); } applyZoom(windowZoomLevel, auxiliaryWindow);