Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/services/auxiliaryWindow/electron-browser/auxiliaryWindowService.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { localize } from '../../../../nls.js';
7
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
8
import { IWorkbenchLayoutService } from '../../layout/browser/layoutService.js';
9
import { AuxiliaryWindow, AuxiliaryWindowMode, BrowserAuxiliaryWindowService, IAuxiliaryWindowOpenOptions, IAuxiliaryWindowService } from '../browser/auxiliaryWindowService.js';
10
import { ISandboxGlobals } from '../../../../base/parts/sandbox/electron-browser/globals.js';
11
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
12
import { DisposableStore } from '../../../../base/common/lifecycle.js';
13
import { INativeHostService } from '../../../../platform/native/common/native.js';
14
import { IDialogService } from '../../../../platform/dialogs/common/dialogs.js';
15
import { CodeWindow } from '../../../../base/browser/window.js';
16
import { mark } from '../../../../base/common/performance.js';
17
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
18
import { ShutdownReason } from '../../lifecycle/common/lifecycle.js';
19
import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry.js';
20
import { Barrier } from '../../../../base/common/async.js';
21
import { IHostService } from '../../host/browser/host.js';
22
import { applyZoom } from '../../../../platform/window/electron-browser/window.js';
23
import { getZoomLevel, isFullscreen, setFullscreen } from '../../../../base/browser/browser.js';
24
import { getActiveWindow } from '../../../../base/browser/dom.js';
25
import { IWorkbenchEnvironmentService } from '../../environment/common/environmentService.js';
26
import { isMacintosh } from '../../../../base/common/platform.js';
27
28
type NativeCodeWindow = CodeWindow & {
29
readonly vscode: ISandboxGlobals;
30
};
31
32
export class NativeAuxiliaryWindow extends AuxiliaryWindow {
33
34
private skipUnloadConfirmation = false;
35
36
private maximized = false;
37
private alwaysOnTop = false;
38
39
constructor(
40
window: CodeWindow,
41
container: HTMLElement,
42
stylesHaveLoaded: Barrier,
43
@IConfigurationService configurationService: IConfigurationService,
44
@INativeHostService private readonly nativeHostService: INativeHostService,
45
@IInstantiationService private readonly instantiationService: IInstantiationService,
46
@IHostService hostService: IHostService,
47
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
48
@IDialogService private readonly dialogService: IDialogService
49
) {
50
super(window, container, stylesHaveLoaded, configurationService, hostService, environmentService);
51
52
if (!isMacintosh) {
53
// For now, limit this to platforms that have clear maximised
54
// transitions (Windows, Linux) via window buttons.
55
this.handleMaximizedState();
56
}
57
58
this.handleFullScreenState();
59
this.handleAlwaysOnTopState();
60
}
61
62
private handleMaximizedState(): void {
63
(async () => {
64
this.maximized = await this.nativeHostService.isMaximized({ targetWindowId: this.window.vscodeWindowId });
65
})();
66
67
this._register(this.nativeHostService.onDidMaximizeWindow(windowId => {
68
if (windowId === this.window.vscodeWindowId) {
69
this.maximized = true;
70
}
71
}));
72
73
this._register(this.nativeHostService.onDidUnmaximizeWindow(windowId => {
74
if (windowId === this.window.vscodeWindowId) {
75
this.maximized = false;
76
}
77
}));
78
}
79
80
private handleAlwaysOnTopState(): void {
81
(async () => {
82
this.alwaysOnTop = await this.nativeHostService.isWindowAlwaysOnTop({ targetWindowId: this.window.vscodeWindowId });
83
})();
84
85
this._register(this.nativeHostService.onDidChangeWindowAlwaysOnTop(({ windowId, alwaysOnTop }) => {
86
if (windowId === this.window.vscodeWindowId) {
87
this.alwaysOnTop = alwaysOnTop;
88
}
89
}));
90
}
91
92
private async handleFullScreenState(): Promise<void> {
93
const fullscreen = await this.nativeHostService.isFullScreen({ targetWindowId: this.window.vscodeWindowId });
94
if (fullscreen) {
95
setFullscreen(true, this.window);
96
}
97
}
98
99
protected override async handleVetoBeforeClose(e: BeforeUnloadEvent, veto: string): Promise<void> {
100
this.preventUnload(e);
101
102
await this.dialogService.error(veto, localize('backupErrorDetails', "Try saving or reverting the editors with unsaved changes first and then try again."));
103
}
104
105
protected override async confirmBeforeClose(e: BeforeUnloadEvent): Promise<void> {
106
if (this.skipUnloadConfirmation) {
107
return;
108
}
109
110
this.preventUnload(e);
111
112
const confirmed = await this.instantiationService.invokeFunction(accessor => NativeAuxiliaryWindow.confirmOnShutdown(accessor, ShutdownReason.CLOSE));
113
if (confirmed) {
114
this.skipUnloadConfirmation = true;
115
this.nativeHostService.closeWindow({ targetWindowId: this.window.vscodeWindowId });
116
}
117
}
118
119
protected override preventUnload(e: BeforeUnloadEvent): void {
120
e.preventDefault();
121
e.returnValue = true;
122
}
123
124
override createState(): IAuxiliaryWindowOpenOptions {
125
const state = super.createState();
126
const fullscreen = isFullscreen(this.window);
127
return {
128
...state,
129
bounds: state.bounds,
130
mode: this.maximized ? AuxiliaryWindowMode.Maximized : fullscreen ? AuxiliaryWindowMode.Fullscreen : AuxiliaryWindowMode.Normal,
131
alwaysOnTop: this.alwaysOnTop
132
};
133
}
134
}
135
136
export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService {
137
138
constructor(
139
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
140
@IConfigurationService configurationService: IConfigurationService,
141
@INativeHostService private readonly nativeHostService: INativeHostService,
142
@IDialogService dialogService: IDialogService,
143
@IInstantiationService private readonly instantiationService: IInstantiationService,
144
@ITelemetryService telemetryService: ITelemetryService,
145
@IHostService hostService: IHostService,
146
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService
147
) {
148
super(layoutService, dialogService, configurationService, telemetryService, hostService, environmentService);
149
}
150
151
protected override async resolveWindowId(auxiliaryWindow: NativeCodeWindow): Promise<number> {
152
mark('code/auxiliaryWindow/willResolveWindowId');
153
const windowId = await auxiliaryWindow.vscode.ipcRenderer.invoke('vscode:registerAuxiliaryWindow', this.nativeHostService.windowId);
154
mark('code/auxiliaryWindow/didResolveWindowId');
155
156
return windowId;
157
}
158
159
protected override createContainer(auxiliaryWindow: NativeCodeWindow, disposables: DisposableStore, options?: IAuxiliaryWindowOpenOptions) {
160
161
// Zoom level (either explicitly provided or inherited from main window)
162
let windowZoomLevel: number;
163
if (typeof options?.zoomLevel === 'number') {
164
windowZoomLevel = options.zoomLevel;
165
} else {
166
windowZoomLevel = getZoomLevel(getActiveWindow());
167
}
168
169
applyZoom(windowZoomLevel, auxiliaryWindow);
170
171
return super.createContainer(auxiliaryWindow, disposables);
172
}
173
174
protected override createAuxiliaryWindow(targetWindow: CodeWindow, container: HTMLElement, stylesHaveLoaded: Barrier): AuxiliaryWindow {
175
return new NativeAuxiliaryWindow(targetWindow, container, stylesHaveLoaded, this.configurationService, this.nativeHostService, this.instantiationService, this.hostService, this.environmentService, this.dialogService);
176
}
177
}
178
179
registerSingleton(IAuxiliaryWindowService, NativeAuxiliaryWindowService, InstantiationType.Delayed);
180
181