mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-01 01:25:38 -05:00
Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998 (#7880)
* Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998 * fix pipelines * fix strict-null-checks * add missing files
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
import * as path from 'vs/base/common/path';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import * as nls from 'vs/nls';
|
||||
import { Event as CommonEvent, Emitter } from 'vs/base/common/event';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display, TouchBarSegmentedControl, NativeImage, BrowserWindowConstructorOptions, SegmentedControlSegment } from 'electron';
|
||||
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
|
||||
@@ -13,7 +14,7 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IWindowSettings, MenuBarVisibility, IWindowConfiguration, ReadyState, getTitleBarStyle } from 'vs/platform/windows/common/windows';
|
||||
import { IWindowSettings, MenuBarVisibility, IWindowConfiguration, ReadyState, getTitleBarStyle, getMenuBarVisibility } from 'vs/platform/windows/common/windows';
|
||||
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
|
||||
import { ICodeWindow, IWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows';
|
||||
@@ -27,6 +28,9 @@ import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainServ
|
||||
import { endsWith } from 'vs/base/common/strings';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs';
|
||||
import { mnemonicButtonLabel } from 'vs/base/common/labels';
|
||||
|
||||
const RUN_TEXTMATE_IN_WORKER = false;
|
||||
|
||||
@@ -48,26 +52,37 @@ interface ITouchBarSegment extends SegmentedControlSegment {
|
||||
id: string;
|
||||
}
|
||||
|
||||
const enum WindowError {
|
||||
UNRESPONSIVE = 1,
|
||||
CRASHED = 2
|
||||
}
|
||||
|
||||
export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
|
||||
private static readonly MIN_WIDTH = 200;
|
||||
private static readonly MIN_HEIGHT = 120;
|
||||
private static readonly MIN_WIDTH = 600;
|
||||
private static readonly MIN_HEIGHT = 600;
|
||||
|
||||
private static readonly MAX_URL_LENGTH = 2 * 1024 * 1024; // https://cs.chromium.org/chromium/src/url/url_constants.cc?l=32
|
||||
|
||||
private hiddenTitleBarStyle: boolean;
|
||||
private showTimeoutHandle: NodeJS.Timeout;
|
||||
private _id: number;
|
||||
private _win: BrowserWindow;
|
||||
private readonly _onClose = this._register(new Emitter<void>());
|
||||
readonly onClose: CommonEvent<void> = this._onClose.event;
|
||||
|
||||
private readonly _onDestroy = this._register(new Emitter<void>());
|
||||
readonly onDestroy: CommonEvent<void> = this._onDestroy.event;
|
||||
|
||||
private readonly _onLoad = this._register(new Emitter<void>());
|
||||
readonly onLoad: CommonEvent<void> = this._onLoad.event;
|
||||
|
||||
private hiddenTitleBarStyle: boolean | undefined;
|
||||
private showTimeoutHandle: NodeJS.Timeout | undefined;
|
||||
private _lastFocusTime: number;
|
||||
private _readyState: ReadyState;
|
||||
private windowState: IWindowState;
|
||||
private currentMenuBarVisibility: MenuBarVisibility;
|
||||
private representedFilename: string;
|
||||
private currentMenuBarVisibility: MenuBarVisibility | undefined;
|
||||
private representedFilename: string | undefined;
|
||||
|
||||
private readonly whenReadyCallbacks: { (window: ICodeWindow): void }[];
|
||||
|
||||
private currentConfig: IWindowConfiguration;
|
||||
private pendingLoadConfig?: IWindowConfiguration;
|
||||
|
||||
private marketplaceHeadersPromise: Promise<object>;
|
||||
@@ -83,6 +98,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
@IThemeMainService private readonly themeMainService: IThemeMainService,
|
||||
@IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService,
|
||||
@IBackupMainService private readonly backupMainService: IBackupMainService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@IDialogMainService private readonly dialogMainService: IDialogMainService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -91,8 +108,111 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
this._readyState = ReadyState.NONE;
|
||||
this.whenReadyCallbacks = [];
|
||||
|
||||
// create browser window
|
||||
this.createBrowserWindow(config);
|
||||
//#region create browser window
|
||||
{
|
||||
// Load window state
|
||||
const [state, hasMultipleDisplays] = this.restoreWindowState(config.state);
|
||||
this.windowState = state;
|
||||
|
||||
// in case we are maximized or fullscreen, only show later after the call to maximize/fullscreen (see below)
|
||||
const isFullscreenOrMaximized = (this.windowState.mode === WindowMode.Maximized || this.windowState.mode === WindowMode.Fullscreen);
|
||||
|
||||
const options: BrowserWindowConstructorOptions = {
|
||||
width: this.windowState.width,
|
||||
height: this.windowState.height,
|
||||
x: this.windowState.x,
|
||||
y: this.windowState.y,
|
||||
backgroundColor: this.themeMainService.getBackgroundColor(),
|
||||
minWidth: CodeWindow.MIN_WIDTH,
|
||||
minHeight: CodeWindow.MIN_HEIGHT,
|
||||
show: !isFullscreenOrMaximized,
|
||||
title: product.nameLong,
|
||||
webPreferences: {
|
||||
// By default if Code is in the background, intervals and timeouts get throttled, so we
|
||||
// want to enforce that Code stays in the foreground. This triggers a disable_hidden_
|
||||
// flag that Electron provides via patch:
|
||||
// https://github.com/electron/libchromiumcontent/blob/master/patches/common/chromium/disable_hidden.patch
|
||||
backgroundThrottling: false,
|
||||
nodeIntegration: true,
|
||||
nodeIntegrationInWorker: RUN_TEXTMATE_IN_WORKER,
|
||||
webviewTag: true
|
||||
}
|
||||
};
|
||||
|
||||
if (isLinux) {
|
||||
options.icon = path.join(this.environmentService.appRoot, 'resources/linux/code.png'); // Windows and Mac are better off using the embedded icon(s)
|
||||
}
|
||||
|
||||
const windowConfig = this.configurationService.getValue<IWindowSettings>('window');
|
||||
|
||||
if (isMacintosh && !this.useNativeFullScreen()) {
|
||||
options.fullscreenable = false; // enables simple fullscreen mode
|
||||
}
|
||||
|
||||
if (isMacintosh) {
|
||||
options.acceptFirstMouse = true; // enabled by default
|
||||
|
||||
if (windowConfig?.clickThroughInactive === false) {
|
||||
options.acceptFirstMouse = false;
|
||||
}
|
||||
}
|
||||
|
||||
const useNativeTabs = isMacintosh && windowConfig?.nativeTabs === true;
|
||||
if (useNativeTabs) {
|
||||
options.tabbingIdentifier = product.nameShort; // this opts in to sierra tabs
|
||||
}
|
||||
|
||||
const useCustomTitleStyle = getTitleBarStyle(this.configurationService, this.environmentService, !!config.extensionDevelopmentPath) === 'custom';
|
||||
if (useCustomTitleStyle) {
|
||||
options.titleBarStyle = 'hidden';
|
||||
this.hiddenTitleBarStyle = true;
|
||||
if (!isMacintosh) {
|
||||
options.frame = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the browser window.
|
||||
this._win = new BrowserWindow(options);
|
||||
this._id = this._win.id;
|
||||
|
||||
if (isMacintosh && useCustomTitleStyle) {
|
||||
this._win.setSheetOffset(22); // offset dialogs by the height of the custom title bar if we have any
|
||||
}
|
||||
|
||||
// TODO@Ben (Electron 4 regression): when running on multiple displays where the target display
|
||||
// to open the window has a larger resolution than the primary display, the window will not size
|
||||
// correctly unless we set the bounds again (https://github.com/microsoft/vscode/issues/74872)
|
||||
//
|
||||
// However, when running with native tabs with multiple windows we cannot use this workaround
|
||||
// because there is a potential that the new window will be added as native tab instead of being
|
||||
// a window on its own. In that case calling setBounds() would cause https://github.com/microsoft/vscode/issues/75830
|
||||
if (isMacintosh && hasMultipleDisplays && (!useNativeTabs || BrowserWindow.getAllWindows().length === 1)) {
|
||||
if ([this.windowState.width, this.windowState.height, this.windowState.x, this.windowState.y].every(value => typeof value === 'number')) {
|
||||
const ensuredWindowState = this.windowState as Required<IWindowState>;
|
||||
this._win.setBounds({
|
||||
width: ensuredWindowState.width,
|
||||
height: ensuredWindowState.height,
|
||||
x: ensuredWindowState.x,
|
||||
y: ensuredWindowState.y
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (isFullscreenOrMaximized) {
|
||||
this._win.maximize();
|
||||
|
||||
if (this.windowState.mode === WindowMode.Fullscreen) {
|
||||
this.setFullScreen(true);
|
||||
}
|
||||
|
||||
if (!this._win.isVisible()) {
|
||||
this._win.show(); // to reduce flicker from the default window size to maximize, we only show after maximize
|
||||
}
|
||||
}
|
||||
|
||||
this._lastFocusTime = Date.now(); // since we show directly, we need to set the last focus time too
|
||||
}
|
||||
//#endregion
|
||||
|
||||
// respect configured menu bar visibility
|
||||
this.onConfigurationUpdated();
|
||||
@@ -101,139 +221,26 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
this.createTouchBar();
|
||||
|
||||
// Request handling
|
||||
this.handleMarketplaceRequests();
|
||||
this.marketplaceHeadersPromise = resolveMarketplaceHeaders(product.version, this.environmentService, this.fileService);
|
||||
|
||||
// Eventing
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private createBrowserWindow(config: IWindowCreationOptions): void {
|
||||
private currentConfig: IWindowConfiguration | undefined;
|
||||
get config(): IWindowConfiguration | undefined { return this.currentConfig; }
|
||||
|
||||
// Load window state
|
||||
const [state, hasMultipleDisplays] = this.restoreWindowState(config.state);
|
||||
this.windowState = state;
|
||||
private _id: number;
|
||||
get id(): number { return this._id; }
|
||||
|
||||
// in case we are maximized or fullscreen, only show later after the call to maximize/fullscreen (see below)
|
||||
const isFullscreenOrMaximized = (this.windowState.mode === WindowMode.Maximized || this.windowState.mode === WindowMode.Fullscreen);
|
||||
private _win: BrowserWindow;
|
||||
get win(): BrowserWindow { return this._win; }
|
||||
|
||||
const options: BrowserWindowConstructorOptions = {
|
||||
width: this.windowState.width,
|
||||
height: this.windowState.height,
|
||||
x: this.windowState.x,
|
||||
y: this.windowState.y,
|
||||
backgroundColor: this.themeMainService.getBackgroundColor(),
|
||||
minWidth: CodeWindow.MIN_WIDTH,
|
||||
minHeight: CodeWindow.MIN_HEIGHT,
|
||||
show: !isFullscreenOrMaximized,
|
||||
title: product.nameLong,
|
||||
webPreferences: {
|
||||
// By default if Code is in the background, intervals and timeouts get throttled, so we
|
||||
// want to enforce that Code stays in the foreground. This triggers a disable_hidden_
|
||||
// flag that Electron provides via patch:
|
||||
// https://github.com/electron/libchromiumcontent/blob/master/patches/common/chromium/disable_hidden.patch
|
||||
backgroundThrottling: false,
|
||||
nodeIntegration: true,
|
||||
nodeIntegrationInWorker: RUN_TEXTMATE_IN_WORKER,
|
||||
webviewTag: true
|
||||
}
|
||||
};
|
||||
get hasHiddenTitleBarStyle(): boolean { return !!this.hiddenTitleBarStyle; }
|
||||
|
||||
if (isLinux) {
|
||||
options.icon = path.join(this.environmentService.appRoot, 'resources/linux/code.png'); // Windows and Mac are better off using the embedded icon(s)
|
||||
}
|
||||
get isExtensionDevelopmentHost(): boolean { return !!(this.config && this.config.extensionDevelopmentPath); }
|
||||
|
||||
const windowConfig = this.configurationService.getValue<IWindowSettings>('window');
|
||||
|
||||
if (isMacintosh && !this.useNativeFullScreen()) {
|
||||
options.fullscreenable = false; // enables simple fullscreen mode
|
||||
}
|
||||
|
||||
if (isMacintosh) {
|
||||
options.acceptFirstMouse = true; // enabled by default
|
||||
|
||||
if (windowConfig && windowConfig.clickThroughInactive === false) {
|
||||
options.acceptFirstMouse = false;
|
||||
}
|
||||
}
|
||||
|
||||
const useNativeTabs = isMacintosh && windowConfig && windowConfig.nativeTabs === true;
|
||||
if (useNativeTabs) {
|
||||
options.tabbingIdentifier = product.nameShort; // this opts in to sierra tabs
|
||||
}
|
||||
|
||||
const useCustomTitleStyle = getTitleBarStyle(this.configurationService, this.environmentService, !!config.extensionDevelopmentPath) === 'custom';
|
||||
if (useCustomTitleStyle) {
|
||||
options.titleBarStyle = 'hidden';
|
||||
this.hiddenTitleBarStyle = true;
|
||||
if (!isMacintosh) {
|
||||
options.frame = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the browser window.
|
||||
this._win = new BrowserWindow(options);
|
||||
this._id = this._win.id;
|
||||
|
||||
if (isMacintosh && useCustomTitleStyle) {
|
||||
this._win.setSheetOffset(22); // offset dialogs by the height of the custom title bar if we have any
|
||||
}
|
||||
|
||||
// TODO@Ben (Electron 4 regression): when running on multiple displays where the target display
|
||||
// to open the window has a larger resolution than the primary display, the window will not size
|
||||
// correctly unless we set the bounds again (https://github.com/microsoft/vscode/issues/74872)
|
||||
//
|
||||
// However, when running with native tabs with multiple windows we cannot use this workaround
|
||||
// because there is a potential that the new window will be added as native tab instead of being
|
||||
// a window on its own. In that case calling setBounds() would cause https://github.com/microsoft/vscode/issues/75830
|
||||
if (isMacintosh && hasMultipleDisplays && (!useNativeTabs || BrowserWindow.getAllWindows().length === 1)) {
|
||||
if ([this.windowState.width, this.windowState.height, this.windowState.x, this.windowState.y].every(value => typeof value === 'number')) {
|
||||
this._win.setBounds({
|
||||
width: this.windowState.width!,
|
||||
height: this.windowState.height!,
|
||||
x: this.windowState.x!,
|
||||
y: this.windowState.y!
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (isFullscreenOrMaximized) {
|
||||
this._win.maximize();
|
||||
|
||||
if (this.windowState.mode === WindowMode.Fullscreen) {
|
||||
this.setFullScreen(true);
|
||||
}
|
||||
|
||||
if (!this._win.isVisible()) {
|
||||
this._win.show(); // to reduce flicker from the default window size to maximize, we only show after maximize
|
||||
}
|
||||
}
|
||||
|
||||
this._lastFocusTime = Date.now(); // since we show directly, we need to set the last focus time too
|
||||
}
|
||||
|
||||
hasHiddenTitleBarStyle(): boolean {
|
||||
return this.hiddenTitleBarStyle;
|
||||
}
|
||||
|
||||
get isExtensionDevelopmentHost(): boolean {
|
||||
return !!this.config.extensionDevelopmentPath;
|
||||
}
|
||||
|
||||
get isExtensionTestHost(): boolean {
|
||||
return !!this.config.extensionTestsPath;
|
||||
}
|
||||
|
||||
get config(): IWindowConfiguration {
|
||||
return this.currentConfig;
|
||||
}
|
||||
|
||||
get id(): number {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get win(): BrowserWindow {
|
||||
return this._win;
|
||||
}
|
||||
get isExtensionTestHost(): boolean { return !!(this.config && this.config.extensionTestsPath); }
|
||||
|
||||
setRepresentedFilename(filename: string): void {
|
||||
if (isMacintosh) {
|
||||
@@ -243,7 +250,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
}
|
||||
}
|
||||
|
||||
getRepresentedFilename(): string {
|
||||
getRepresentedFilename(): string | undefined {
|
||||
if (isMacintosh) {
|
||||
return this.win.getRepresentedFilename();
|
||||
}
|
||||
@@ -263,25 +270,15 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
this._win.focus();
|
||||
}
|
||||
|
||||
get lastFocusTime(): number {
|
||||
return this._lastFocusTime;
|
||||
}
|
||||
get lastFocusTime(): number { return this._lastFocusTime; }
|
||||
|
||||
get backupPath(): string | undefined {
|
||||
return this.currentConfig ? this.currentConfig.backupPath : undefined;
|
||||
}
|
||||
get backupPath(): string | undefined { return this.currentConfig ? this.currentConfig.backupPath : undefined; }
|
||||
|
||||
get openedWorkspace(): IWorkspaceIdentifier | undefined {
|
||||
return this.currentConfig ? this.currentConfig.workspace : undefined;
|
||||
}
|
||||
get openedWorkspace(): IWorkspaceIdentifier | undefined { return this.currentConfig ? this.currentConfig.workspace : undefined; }
|
||||
|
||||
get openedFolderUri(): URI | undefined {
|
||||
return this.currentConfig ? this.currentConfig.folderUri : undefined;
|
||||
}
|
||||
get openedFolderUri(): URI | undefined { return this.currentConfig ? this.currentConfig.folderUri : undefined; }
|
||||
|
||||
get remoteAuthority(): string | undefined {
|
||||
return this.currentConfig ? this.currentConfig.remoteAuthority : undefined;
|
||||
}
|
||||
get remoteAuthority(): string | undefined { return this.currentConfig ? this.currentConfig.remoteAuthority : undefined; }
|
||||
|
||||
setReady(): void {
|
||||
this._readyState = ReadyState.READY;
|
||||
@@ -307,26 +304,34 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
return this._readyState === ReadyState.READY;
|
||||
}
|
||||
|
||||
private handleMarketplaceRequests(): void {
|
||||
get whenClosedOrLoaded(): Promise<void> {
|
||||
return new Promise<void>(resolve => {
|
||||
|
||||
// Resolve marketplace headers
|
||||
this.marketplaceHeadersPromise = resolveMarketplaceHeaders(product.version, this.environmentService, this.fileService);
|
||||
function handle() {
|
||||
closeListener.dispose();
|
||||
loadListener.dispose();
|
||||
|
||||
// Inject headers when requests are incoming
|
||||
const urls = ['https://marketplace.visualstudio.com/*', 'https://*.vsassets.io/*'];
|
||||
this._win.webContents.session.webRequest.onBeforeSendHeaders({ urls }, (details, cb) => {
|
||||
this.marketplaceHeadersPromise.then(headers => {
|
||||
const requestHeaders = objects.assign(details.requestHeaders, headers) as { [key: string]: string | undefined };
|
||||
if (!this.configurationService.getValue('extensions.disableExperimentalAzureSearch')) {
|
||||
requestHeaders['Cookie'] = `${requestHeaders['Cookie'] ? requestHeaders['Cookie'] + ';' : ''}EnableExternalSearchForVSCode=true`;
|
||||
}
|
||||
cb({ cancel: false, requestHeaders });
|
||||
});
|
||||
resolve();
|
||||
}
|
||||
|
||||
const closeListener = this.onClose(() => handle());
|
||||
const loadListener = this.onLoad(() => handle());
|
||||
});
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
|
||||
// Crashes & Unrsponsive
|
||||
this._win.webContents.on('crashed', () => this.onWindowError(WindowError.CRASHED));
|
||||
this._win.on('unresponsive', () => this.onWindowError(WindowError.UNRESPONSIVE));
|
||||
|
||||
// Window close
|
||||
this._win.on('closed', () => {
|
||||
this._onClose.fire();
|
||||
|
||||
this.dispose();
|
||||
});
|
||||
|
||||
// Prevent loading of svgs
|
||||
this._win.webContents.session.webRequest.onBeforeRequest(null!, (details, callback) => {
|
||||
if (details.url.indexOf('.svg') > 0) {
|
||||
@@ -376,7 +381,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
return; // disposed
|
||||
}
|
||||
|
||||
if (!this.useNativeFullScreen() && this.isFullScreen()) {
|
||||
if (!this.useNativeFullScreen() && this.isFullScreen) {
|
||||
this.setFullScreen(false);
|
||||
this.setFullScreen(true);
|
||||
}
|
||||
@@ -430,13 +435,97 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
|
||||
// Handle Workspace events
|
||||
this._register(this.workspacesMainService.onUntitledWorkspaceDeleted(e => this.onUntitledWorkspaceDeleted(e)));
|
||||
|
||||
// Inject headers when requests are incoming
|
||||
const urls = ['https://marketplace.visualstudio.com/*', 'https://*.vsassets.io/*'];
|
||||
this._win.webContents.session.webRequest.onBeforeSendHeaders({ urls }, (details, cb) => {
|
||||
this.marketplaceHeadersPromise.then(headers => {
|
||||
const requestHeaders = objects.assign(details.requestHeaders, headers) as { [key: string]: string | undefined };
|
||||
if (!this.configurationService.getValue('extensions.disableExperimentalAzureSearch')) {
|
||||
requestHeaders['Cookie'] = `${requestHeaders['Cookie'] ? requestHeaders['Cookie'] + ';' : ''}EnableExternalSearchForVSCode=true`;
|
||||
}
|
||||
cb({ cancel: false, requestHeaders });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private onWindowError(error: WindowError): void {
|
||||
this.logService.error(error === WindowError.CRASHED ? '[VS Code]: render process crashed!' : '[VS Code]: detected unresponsive');
|
||||
|
||||
type WindowErrorClassification = {
|
||||
type: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
};
|
||||
type WindowErrorEvent = {
|
||||
type: WindowError;
|
||||
};
|
||||
this.telemetryService.publicLog2<WindowErrorEvent, WindowErrorClassification>('windowerror', { type: error });
|
||||
|
||||
// Unresponsive
|
||||
if (error === WindowError.UNRESPONSIVE) {
|
||||
if (this.isExtensionDevelopmentHost || this.isExtensionTestHost || (this._win && this._win.webContents && this._win.webContents.isDevToolsOpened())) {
|
||||
// TODO@Ben Workaround for https://github.com/Microsoft/vscode/issues/56994
|
||||
// In certain cases the window can report unresponsiveness because a breakpoint was hit
|
||||
// and the process is stopped executing. The most typical cases are:
|
||||
// - devtools are opened and debugging happens
|
||||
// - window is an extensions development host that is being debugged
|
||||
// - window is an extension test development host that is being debugged
|
||||
return;
|
||||
}
|
||||
|
||||
// Show Dialog
|
||||
this.dialogMainService.showMessageBox({
|
||||
title: product.nameLong,
|
||||
type: 'warning',
|
||||
buttons: [mnemonicButtonLabel(nls.localize({ key: 'reopen', comment: ['&& denotes a mnemonic'] }, "&&Reopen")), mnemonicButtonLabel(nls.localize({ key: 'wait', comment: ['&& denotes a mnemonic'] }, "&&Keep Waiting")), mnemonicButtonLabel(nls.localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))],
|
||||
message: nls.localize('appStalled', "The window is no longer responding"),
|
||||
detail: nls.localize('appStalledDetail', "You can reopen or close the window or keep waiting."),
|
||||
noLink: true
|
||||
}, this._win).then(result => {
|
||||
if (!this._win) {
|
||||
return; // Return early if the window has been going down already
|
||||
}
|
||||
|
||||
if (result.response === 0) {
|
||||
this.reload();
|
||||
} else if (result.response === 2) {
|
||||
this.destroyWindow();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Crashed
|
||||
else {
|
||||
this.dialogMainService.showMessageBox({
|
||||
title: product.nameLong,
|
||||
type: 'warning',
|
||||
buttons: [mnemonicButtonLabel(nls.localize({ key: 'reopen', comment: ['&& denotes a mnemonic'] }, "&&Reopen")), mnemonicButtonLabel(nls.localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))],
|
||||
message: nls.localize('appCrashed', "The window has crashed"),
|
||||
detail: nls.localize('appCrashedDetail', "We are sorry for the inconvenience! You can reopen the window to continue where you left off."),
|
||||
noLink: true
|
||||
}, this._win).then(result => {
|
||||
if (!this._win) {
|
||||
return; // Return early if the window has been going down already
|
||||
}
|
||||
|
||||
if (result.response === 0) {
|
||||
this.reload();
|
||||
} else if (result.response === 1) {
|
||||
this.destroyWindow();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private destroyWindow(): void {
|
||||
this._onDestroy.fire(); // 'close' event will not be fired on destroy(), so signal crash via explicit event
|
||||
this._win.destroy(); // make sure to destroy the window as it has crashed
|
||||
}
|
||||
|
||||
private onUntitledWorkspaceDeleted(workspace: IWorkspaceIdentifier): void {
|
||||
|
||||
// Make sure to update our workspace config if we detect that it
|
||||
// was deleted
|
||||
if (this.openedWorkspace && this.openedWorkspace.id === workspace.id) {
|
||||
if (this.openedWorkspace && this.openedWorkspace.id === workspace.id && this.currentConfig) {
|
||||
this.currentConfig.workspace = undefined;
|
||||
}
|
||||
}
|
||||
@@ -510,6 +599,9 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
}
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
// Event
|
||||
this._onLoad.fire();
|
||||
}
|
||||
|
||||
reload(configurationIn?: IWindowConfiguration, cli?: ParsedArgs): void {
|
||||
@@ -547,25 +639,25 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
|
||||
// Set zoomlevel
|
||||
const windowConfig = this.configurationService.getValue<IWindowSettings>('window');
|
||||
const zoomLevel = windowConfig && windowConfig.zoomLevel;
|
||||
const zoomLevel = windowConfig?.zoomLevel;
|
||||
if (typeof zoomLevel === 'number') {
|
||||
windowConfiguration.zoomLevel = zoomLevel;
|
||||
}
|
||||
|
||||
// Set fullscreen state
|
||||
windowConfiguration.fullscreen = this.isFullScreen();
|
||||
windowConfiguration.fullscreen = this.isFullScreen;
|
||||
|
||||
// Set Accessibility Config
|
||||
let autoDetectHighContrast = true;
|
||||
if (windowConfig && windowConfig.autoDetectHighContrast === false) {
|
||||
if (windowConfig?.autoDetectHighContrast === false) {
|
||||
autoDetectHighContrast = false;
|
||||
}
|
||||
windowConfiguration.highContrast = isWindows && autoDetectHighContrast && systemPreferences.isInvertedColorScheme();
|
||||
windowConfiguration.accessibilitySupport = app.isAccessibilitySupportEnabled();
|
||||
windowConfiguration.accessibilitySupport = app.accessibilitySupportEnabled;
|
||||
|
||||
// Title style related
|
||||
windowConfiguration.maximized = this._win.isMaximized();
|
||||
windowConfiguration.frameless = this.hasHiddenTitleBarStyle() && !isMacintosh;
|
||||
windowConfiguration.frameless = this.hasHiddenTitleBarStyle && !isMacintosh;
|
||||
|
||||
// Dump Perf Counters
|
||||
windowConfiguration.perfEntries = perf.exportEntries();
|
||||
@@ -611,7 +703,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
}
|
||||
|
||||
// fullscreen gets special treatment
|
||||
if (this.isFullScreen()) {
|
||||
if (this.isFullScreen) {
|
||||
const display = screen.getDisplayMatching(this.getBounds());
|
||||
|
||||
const defaultState = defaultWindowState();
|
||||
@@ -733,7 +825,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
// Multi Montior (fullscreen): try to find the previously used display
|
||||
if (state.display && state.mode === WindowMode.Fullscreen) {
|
||||
const display = displays.filter(d => d.id === state.display)[0];
|
||||
if (display && display.bounds && typeof display.bounds.x === 'number' && typeof display.bounds.y === 'number') {
|
||||
if (display && typeof display.bounds?.x === 'number' && typeof display.bounds?.y === 'number') {
|
||||
const defaults = defaultWindowState(WindowMode.Fullscreen); // make sure we have good values when the user restores the window
|
||||
defaults.x = display.bounds.x; // carefull to use displays x/y position so that the window ends up on the correct monitor
|
||||
defaults.y = display.bounds.y;
|
||||
@@ -786,7 +878,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
}
|
||||
|
||||
toggleFullScreen(): void {
|
||||
this.setFullScreen(!this.isFullScreen());
|
||||
this.setFullScreen(!this.isFullScreen);
|
||||
}
|
||||
|
||||
private setFullScreen(fullscreen: boolean): void {
|
||||
@@ -802,12 +894,12 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
this.sendWhenReady(fullscreen ? 'vscode:enterFullScreen' : 'vscode:leaveFullScreen');
|
||||
|
||||
// Respect configured menu bar visibility or default to toggle if not set
|
||||
this.setMenuBarVisibility(this.currentMenuBarVisibility, false);
|
||||
if (this.currentMenuBarVisibility) {
|
||||
this.setMenuBarVisibility(this.currentMenuBarVisibility, false);
|
||||
}
|
||||
}
|
||||
|
||||
isFullScreen(): boolean {
|
||||
return this._win.isFullScreen() || this._win.isSimpleFullScreen();
|
||||
}
|
||||
get isFullScreen(): boolean { return this._win.isFullScreen() || this._win.isSimpleFullScreen(); }
|
||||
|
||||
private setNativeFullScreen(fullscreen: boolean): void {
|
||||
if (this._win.isSimpleFullScreen()) {
|
||||
@@ -844,12 +936,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
}
|
||||
|
||||
private getMenuBarVisibility(): MenuBarVisibility {
|
||||
const windowConfig = this.configurationService.getValue<IWindowSettings>('window');
|
||||
if (!windowConfig || !windowConfig.menuBarVisibility) {
|
||||
return 'default';
|
||||
}
|
||||
|
||||
let menuBarVisibility = windowConfig.menuBarVisibility;
|
||||
let menuBarVisibility = getMenuBarVisibility(this.configurationService, this.environmentService, !!this.config?.extensionDevelopmentPath);
|
||||
if (['visible', 'toggle', 'hidden'].indexOf(menuBarVisibility) < 0) {
|
||||
menuBarVisibility = 'default';
|
||||
}
|
||||
@@ -883,7 +970,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
}
|
||||
|
||||
private doSetMenuBarVisibility(visibility: MenuBarVisibility): void {
|
||||
const isFullscreen = this.isFullScreen();
|
||||
const isFullscreen = this.isFullScreen;
|
||||
|
||||
switch (visibility) {
|
||||
case ('default'):
|
||||
|
||||
Reference in New Issue
Block a user