Path: blob/main/src/vs/workbench/services/auxiliaryWindow/electron-browser/auxiliaryWindowService.ts
5262 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { localize } from '../../../../nls.js';6import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';7import { IWorkbenchLayoutService } from '../../layout/browser/layoutService.js';8import { AuxiliaryWindow, AuxiliaryWindowMode, BrowserAuxiliaryWindowService, IAuxiliaryWindowOpenOptions, IAuxiliaryWindowService } from '../browser/auxiliaryWindowService.js';9import { ISandboxGlobals } from '../../../../base/parts/sandbox/electron-browser/globals.js';10import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';11import { DisposableStore } from '../../../../base/common/lifecycle.js';12import { INativeHostService } from '../../../../platform/native/common/native.js';13import { IDialogService } from '../../../../platform/dialogs/common/dialogs.js';14import { CodeWindow } from '../../../../base/browser/window.js';15import { mark } from '../../../../base/common/performance.js';16import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';17import { ShutdownReason } from '../../lifecycle/common/lifecycle.js';18import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry.js';19import { Barrier } from '../../../../base/common/async.js';20import { IHostService } from '../../host/browser/host.js';21import { applyZoom } from '../../../../platform/window/electron-browser/window.js';22import { getZoomLevel, isFullscreen, setFullscreen } from '../../../../base/browser/browser.js';23import { getActiveWindow } from '../../../../base/browser/dom.js';24import { IWorkbenchEnvironmentService } from '../../environment/common/environmentService.js';25import { isMacintosh } from '../../../../base/common/platform.js';26import { assert } from '../../../../base/common/assert.js';27import { IContextMenuService } from '../../../../platform/contextview/browser/contextView.js';2829type NativeCodeWindow = CodeWindow & {30readonly vscode: ISandboxGlobals;31};3233export class NativeAuxiliaryWindow extends AuxiliaryWindow {3435private skipUnloadConfirmation = false;3637private maximized = false;38private alwaysOnTop = false;3940constructor(41window: CodeWindow,42container: HTMLElement,43stylesHaveLoaded: Barrier,44@IConfigurationService configurationService: IConfigurationService,45@INativeHostService private readonly nativeHostService: INativeHostService,46@IInstantiationService private readonly instantiationService: IInstantiationService,47@IHostService hostService: IHostService,48@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,49@IDialogService private readonly dialogService: IDialogService,50@IContextMenuService contextMenuService: IContextMenuService,51@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService52) {53super(window, container, stylesHaveLoaded, configurationService, hostService, environmentService, contextMenuService, layoutService);5455if (!isMacintosh) {56// For now, limit this to platforms that have clear maximised57// transitions (Windows, Linux) via window buttons.58this.handleMaximizedState();59}6061this.handleFullScreenState();62this.handleAlwaysOnTopState();63}6465private handleMaximizedState(): void {66(async () => {67this.maximized = await this.nativeHostService.isMaximized({ targetWindowId: this.window.vscodeWindowId });68})();6970this._register(this.nativeHostService.onDidMaximizeWindow(windowId => {71if (windowId === this.window.vscodeWindowId) {72this.maximized = true;73}74}));7576this._register(this.nativeHostService.onDidUnmaximizeWindow(windowId => {77if (windowId === this.window.vscodeWindowId) {78this.maximized = false;79}80}));81}8283private handleAlwaysOnTopState(): void {84(async () => {85this.alwaysOnTop = await this.nativeHostService.isWindowAlwaysOnTop({ targetWindowId: this.window.vscodeWindowId });86})();8788this._register(this.nativeHostService.onDidChangeWindowAlwaysOnTop(({ windowId, alwaysOnTop }) => {89if (windowId === this.window.vscodeWindowId) {90this.alwaysOnTop = alwaysOnTop;91}92}));93}9495private async handleFullScreenState(): Promise<void> {96const fullscreen = await this.nativeHostService.isFullScreen({ targetWindowId: this.window.vscodeWindowId });97if (fullscreen) {98setFullscreen(true, this.window);99}100}101102protected override async handleVetoBeforeClose(e: BeforeUnloadEvent, veto: string): Promise<void> {103this.preventUnload(e);104105await this.dialogService.error(veto, localize('backupErrorDetails', "Try saving or reverting the editors with unsaved changes first and then try again."));106}107108protected override async confirmBeforeClose(e: BeforeUnloadEvent): Promise<void> {109if (this.skipUnloadConfirmation) {110return;111}112113this.preventUnload(e);114115const confirmed = await this.instantiationService.invokeFunction(accessor => NativeAuxiliaryWindow.confirmOnShutdown(accessor, ShutdownReason.CLOSE));116if (confirmed) {117this.skipUnloadConfirmation = true;118this.nativeHostService.closeWindow({ targetWindowId: this.window.vscodeWindowId });119}120}121122protected override preventUnload(e: BeforeUnloadEvent): void {123e.preventDefault();124e.returnValue = true;125}126127override createState(): IAuxiliaryWindowOpenOptions {128const state = super.createState();129const fullscreen = isFullscreen(this.window);130return {131...state,132bounds: state.bounds,133mode: this.maximized ? AuxiliaryWindowMode.Maximized : fullscreen ? AuxiliaryWindowMode.Fullscreen : AuxiliaryWindowMode.Normal,134alwaysOnTop: this.alwaysOnTop135};136}137}138139export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService {140141constructor(142@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,143@IConfigurationService configurationService: IConfigurationService,144@INativeHostService private readonly nativeHostService: INativeHostService,145@IDialogService dialogService: IDialogService,146@IInstantiationService private readonly instantiationService: IInstantiationService,147@ITelemetryService telemetryService: ITelemetryService,148@IHostService hostService: IHostService,149@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,150@IContextMenuService contextMenuService: IContextMenuService,151) {152super(layoutService, dialogService, configurationService, telemetryService, hostService, environmentService, contextMenuService);153}154155protected override async resolveWindowId(auxiliaryWindow: NativeCodeWindow): Promise<number> {156mark('code/auxiliaryWindow/willResolveWindowId');157const windowId = await auxiliaryWindow.vscode.ipcRenderer.invoke('vscode:registerAuxiliaryWindow', this.nativeHostService.windowId);158mark('code/auxiliaryWindow/didResolveWindowId');159assert(typeof windowId === 'number');160161return windowId;162}163164protected override createContainer(auxiliaryWindow: NativeCodeWindow, disposables: DisposableStore, options?: IAuxiliaryWindowOpenOptions) {165166// Zoom level (either explicitly provided or inherited from main window)167let windowZoomLevel: number;168if (typeof options?.zoomLevel === 'number') {169windowZoomLevel = options.zoomLevel;170} else {171windowZoomLevel = getZoomLevel(getActiveWindow());172}173174applyZoom(windowZoomLevel, auxiliaryWindow);175176return super.createContainer(auxiliaryWindow, disposables);177}178179protected override createAuxiliaryWindow(targetWindow: CodeWindow, container: HTMLElement, stylesHaveLoaded: Barrier): AuxiliaryWindow {180return new NativeAuxiliaryWindow(targetWindow, container, stylesHaveLoaded, this.configurationService, this.nativeHostService, this.instantiationService, this.hostService, this.environmentService, this.dialogService, this.contextMenuService, this.layoutService);181}182}183184registerSingleton(IAuxiliaryWindowService, NativeAuxiliaryWindowService, InstantiationType.Delayed);185186187