mirror of
https://github.com/coder/code-server.git
synced 2026-06-21 17:37:11 +02:00
chore(vscode): update to 1.56.0
This commit is contained in:
@@ -3,13 +3,14 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { isMacintosh, isLinux, isWeb, IProcessEnvironment, isNative } from 'vs/base/common/platform';
|
||||
import { isMacintosh, isLinux, isWeb, isNative } from 'vs/base/common/platform';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||
import { LogLevel } from 'vs/platform/log/common/log';
|
||||
import { PerformanceMark } from 'vs/base/common/performance';
|
||||
import { ISandboxConfiguration } from 'vs/base/parts/sandbox/common/sandboxTypes';
|
||||
|
||||
export const WindowMinimumSize = {
|
||||
WIDTH: 400,
|
||||
@@ -218,8 +219,6 @@ export interface IColorScheme {
|
||||
}
|
||||
|
||||
export interface IWindowConfiguration {
|
||||
sessionId: string;
|
||||
|
||||
remoteAuthority?: string;
|
||||
|
||||
colorScheme: IColorScheme;
|
||||
@@ -231,32 +230,34 @@ export interface IWindowConfiguration {
|
||||
|
||||
export interface IOSConfiguration {
|
||||
readonly release: string;
|
||||
readonly hostname: string;
|
||||
}
|
||||
|
||||
export interface INativeWindowConfiguration extends IWindowConfiguration, NativeParsedArgs {
|
||||
export interface INativeWindowConfiguration extends IWindowConfiguration, NativeParsedArgs, ISandboxConfiguration {
|
||||
mainPid: number;
|
||||
|
||||
windowId: number;
|
||||
machineId: string;
|
||||
|
||||
appRoot: string;
|
||||
execPath: string;
|
||||
backupPath?: string;
|
||||
|
||||
nodeCachedDataDir?: string;
|
||||
homeDir: string;
|
||||
tmpDir: string;
|
||||
userDataDir: string;
|
||||
|
||||
partsSplashPath: string;
|
||||
|
||||
workspace?: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier;
|
||||
|
||||
isInitialStartup?: boolean;
|
||||
logLevel: LogLevel;
|
||||
zoomLevel?: number;
|
||||
|
||||
fullscreen?: boolean;
|
||||
maximized?: boolean;
|
||||
accessibilitySupport?: boolean;
|
||||
|
||||
perfMarks: PerformanceMark[];
|
||||
|
||||
userEnv: IProcessEnvironment;
|
||||
filesToWait?: IPathsToWaitFor;
|
||||
|
||||
os: IOSConfiguration;
|
||||
|
||||
@@ -3,17 +3,15 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { release } from 'os';
|
||||
import { join } from 'vs/base/common/path';
|
||||
import { localize } from 'vs/nls';
|
||||
import { getMarks, mark } from 'vs/base/common/performance';
|
||||
import { 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, nativeTheme, Event, RenderProcessGoneDetails } from 'electron';
|
||||
import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display, TouchBarSegmentedControl, NativeImage, BrowserWindowConstructorOptions, SegmentedControlSegment, Event, RenderProcessGoneDetails, WebFrameMain } from 'electron';
|
||||
import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService';
|
||||
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 { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { WindowMinimumSize, IWindowSettings, MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility, zoomLevelToZoomFactor, INativeWindowConfiguration } from 'vs/platform/windows/common/windows';
|
||||
@@ -32,11 +30,12 @@ import { mnemonicButtonLabel } from 'vs/base/common/labels';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
|
||||
import { IStorageMainService } from 'vs/platform/storage/electron-main/storageMainService';
|
||||
import { ByteSize, IFileService } from 'vs/platform/files/common/files';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { FileAccess, Schemas } from 'vs/base/common/network';
|
||||
import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { INativeHostMainService } from 'vs/platform/native/electron-main/nativeHostMainService';
|
||||
import { IProtocolMainService } from 'vs/platform/protocol/electron-main/protocol';
|
||||
|
||||
export interface IWindowCreationOptions {
|
||||
state: IWindowState;
|
||||
@@ -48,6 +47,11 @@ interface ITouchBarSegment extends SegmentedControlSegment {
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface ILoadOptions {
|
||||
isReload?: boolean;
|
||||
disableExtensions?: boolean;
|
||||
}
|
||||
|
||||
const enum ReadyState {
|
||||
|
||||
/**
|
||||
@@ -73,7 +77,7 @@ const enum ReadyState {
|
||||
|
||||
export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
|
||||
private static readonly MAX_URL_LENGTH = 2 * ByteSize.MB; // https://cs.chromium.org/chromium/src/url/url_constants.cc?l=32
|
||||
//#region Events
|
||||
|
||||
private readonly _onWillLoad = this._register(new Emitter<ILoadEvent>());
|
||||
readonly onWillLoad = this._onWillLoad.event;
|
||||
@@ -87,6 +91,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
private readonly _onDidDestroy = this._register(new Emitter<void>());
|
||||
readonly onDidDestroy = this._onDidDestroy.event;
|
||||
|
||||
//#endregion
|
||||
|
||||
private hiddenTitleBarStyle: boolean | undefined;
|
||||
private showTimeoutHandle: NodeJS.Timeout | undefined;
|
||||
private windowState: IWindowState;
|
||||
@@ -104,6 +110,36 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
private currentHttpProxy: string | undefined = undefined;
|
||||
private currentNoProxy: string | undefined = undefined;
|
||||
|
||||
private _id: number;
|
||||
get id(): number { return this._id; }
|
||||
|
||||
private _win: BrowserWindow;
|
||||
get win(): BrowserWindow | null { return this._win; }
|
||||
|
||||
private _lastFocusTime = -1;
|
||||
get lastFocusTime(): number { return this._lastFocusTime; }
|
||||
|
||||
get backupPath(): string | undefined { return this.currentConfig?.backupPath; }
|
||||
|
||||
get openedWorkspace(): IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | undefined { return this.currentConfig?.workspace; }
|
||||
|
||||
get remoteAuthority(): string | undefined { return this.currentConfig?.remoteAuthority; }
|
||||
|
||||
private pendingLoadConfig: INativeWindowConfiguration | undefined;
|
||||
|
||||
private currentConfig: INativeWindowConfiguration | undefined;
|
||||
get config(): INativeWindowConfiguration | undefined { return this.currentConfig; }
|
||||
|
||||
private readonly configObjectUrl = this._register(this.protocolMainService.createIPCObjectUrl<INativeWindowConfiguration>());
|
||||
|
||||
get hasHiddenTitleBarStyle(): boolean { return !!this.hiddenTitleBarStyle; }
|
||||
|
||||
get isExtensionDevelopmentHost(): boolean { return !!(this.currentConfig?.extensionDevelopmentPath); }
|
||||
|
||||
get isExtensionTestHost(): boolean { return !!(this.currentConfig?.extensionTestsPath); }
|
||||
|
||||
get isExtensionDevelopmentTestFromCli(): boolean { return this.isExtensionDevelopmentHost && this.isExtensionTestHost && !this.currentConfig?.debugId; }
|
||||
|
||||
constructor(
|
||||
config: IWindowCreationOptions,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@@ -118,7 +154,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
@IDialogMainService private readonly dialogMainService: IDialogMainService,
|
||||
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
|
||||
@INativeHostMainService private readonly nativeHostMainService: INativeHostMainService,
|
||||
@IProductService private readonly productService: IProductService
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@IProtocolMainService private readonly protocolMainService: IProtocolMainService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -132,7 +169,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
// 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 windowConfig = this.configurationService.getValue<IWindowSettings | undefined>('window');
|
||||
const windowSettings = this.configurationService.getValue<IWindowSettings | undefined>('window');
|
||||
|
||||
const options: BrowserWindowConstructorOptions = {
|
||||
width: this.windowState.width,
|
||||
@@ -146,30 +183,35 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
title: this.productService.nameLong,
|
||||
webPreferences: {
|
||||
preload: FileAccess.asFileUri('vs/base/parts/sandbox/electron-browser/preload.js', require).fsPath,
|
||||
additionalArguments: this.environmentMainService.sandbox ?
|
||||
[`--vscode-window-config=${this.configObjectUrl.resource.toString()}`, '--context-isolation' /* TODO@bpasero: Use process.contextIsolateed when 13-x-y is adopted (https://github.com/electron/electron/pull/28030) */] :
|
||||
[`--vscode-window-config=${this.configObjectUrl.resource.toString()}`],
|
||||
v8CacheOptions: browserCodeLoadingCacheStrategy,
|
||||
enableWebSQL: false,
|
||||
enableRemoteModule: false,
|
||||
spellcheck: false,
|
||||
nativeWindowOpen: true,
|
||||
webviewTag: true,
|
||||
zoomFactor: zoomLevelToZoomFactor(windowConfig?.zoomLevel),
|
||||
zoomFactor: zoomLevelToZoomFactor(windowSettings?.zoomLevel),
|
||||
...this.environmentMainService.sandbox ?
|
||||
|
||||
// Sandbox
|
||||
{
|
||||
sandbox: true,
|
||||
contextIsolation: true
|
||||
sandbox: true
|
||||
} :
|
||||
|
||||
// No Sandbox
|
||||
{
|
||||
nodeIntegration: true
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (browserCodeLoadingCacheStrategy) {
|
||||
this.logService.info(`window#ctor: using vscode-file protocol and V8 cache options: ${browserCodeLoadingCacheStrategy}`);
|
||||
this.logService.info(`window#ctor: using vscode-file:// protocol and V8 cache options: ${browserCodeLoadingCacheStrategy}`);
|
||||
} else {
|
||||
this.logService.trace(`window#ctor: vscode-file:// protocol is explicitly disabled`);
|
||||
}
|
||||
|
||||
// Apply icon to window
|
||||
@@ -188,12 +230,12 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
if (isMacintosh) {
|
||||
options.acceptFirstMouse = true; // enabled by default
|
||||
|
||||
if (windowConfig?.clickThroughInactive === false) {
|
||||
if (windowSettings?.clickThroughInactive === false) {
|
||||
options.acceptFirstMouse = false;
|
||||
}
|
||||
}
|
||||
|
||||
const useNativeTabs = isMacintosh && windowConfig?.nativeTabs === true;
|
||||
const useNativeTabs = isMacintosh && windowSettings?.nativeTabs === true;
|
||||
if (useNativeTabs) {
|
||||
options.tabbingIdentifier = this.productService.nameShort; // this opts in to sierra tabs
|
||||
}
|
||||
@@ -207,8 +249,11 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
}
|
||||
}
|
||||
|
||||
// Create the browser window.
|
||||
// Create the browser window
|
||||
mark('code/willCreateCodeBrowserWindow');
|
||||
this._win = new BrowserWindow(options);
|
||||
mark('code/didCreateCodeBrowserWindow');
|
||||
|
||||
this._id = this._win.id;
|
||||
|
||||
// Open devtools if instructed from command line args
|
||||
@@ -240,6 +285,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
}
|
||||
|
||||
if (isFullscreenOrMaximized) {
|
||||
mark('code/willMaximizeCodeWindow');
|
||||
this._win.maximize();
|
||||
|
||||
if (this.windowState.mode === WindowMode.Fullscreen) {
|
||||
@@ -249,6 +295,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
if (!this._win.isVisible()) {
|
||||
this._win.show(); // to reduce flicker from the default window size to maximize, we only show after maximize
|
||||
}
|
||||
mark('code/didMaximizeCodeWindow');
|
||||
}
|
||||
|
||||
this._lastFocusTime = Date.now(); // since we show directly, we need to set the last focus time too
|
||||
@@ -271,25 +318,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private pendingLoadConfig: INativeWindowConfiguration | undefined;
|
||||
|
||||
private currentConfig: INativeWindowConfiguration | undefined;
|
||||
get config(): INativeWindowConfiguration | undefined { return this.currentConfig; }
|
||||
|
||||
private _id: number;
|
||||
get id(): number { return this._id; }
|
||||
|
||||
private _win: BrowserWindow;
|
||||
get win(): BrowserWindow | null { return this._win; }
|
||||
|
||||
get hasHiddenTitleBarStyle(): boolean { return !!this.hiddenTitleBarStyle; }
|
||||
|
||||
get isExtensionDevelopmentHost(): boolean { return !!(this.currentConfig?.extensionDevelopmentPath); }
|
||||
|
||||
get isExtensionTestHost(): boolean { return !!(this.currentConfig?.extensionTestsPath); }
|
||||
|
||||
get isExtensionDevelopmentTestFromCli(): boolean { return this.isExtensionDevelopmentHost && this.isExtensionTestHost && !this.currentConfig?.debugId; }
|
||||
|
||||
setRepresentedFilename(filename: string): void {
|
||||
if (isMacintosh) {
|
||||
this._win.setRepresentedFilename(filename);
|
||||
@@ -345,15 +373,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
this._win.focus();
|
||||
}
|
||||
|
||||
private _lastFocusTime = -1;
|
||||
get lastFocusTime(): number { return this._lastFocusTime; }
|
||||
|
||||
get backupPath(): string | undefined { return this.currentConfig?.backupPath; }
|
||||
|
||||
get openedWorkspace(): IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | undefined { return this.currentConfig?.workspace; }
|
||||
|
||||
get remoteAuthority(): string | undefined { return this.currentConfig?.remoteAuthority; }
|
||||
|
||||
private readyState = ReadyState.NONE;
|
||||
|
||||
setReady(): void {
|
||||
@@ -400,7 +419,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
|
||||
private registerListeners(): void {
|
||||
|
||||
// Crashes & Unrsponsive & Failed to load
|
||||
// Crashes & Unresponsive & Failed to load
|
||||
this._win.on('unresponsive', () => this.onWindowError(WindowError.UNRESPONSIVE));
|
||||
this._win.webContents.on('render-process-gone', (event, details) => this.onWindowError(WindowError.CRASHED, details));
|
||||
this._win.webContents.on('did-fail-load', (event, errorCode, errorDescription) => this.onWindowError(WindowError.LOAD, errorDescription));
|
||||
@@ -413,15 +432,25 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
});
|
||||
|
||||
// Block all SVG requests from unsupported origins
|
||||
const svgFileSchemes = new Set([Schemas.file, Schemas.vscodeFileResource, Schemas.vscodeRemoteResource, 'devtools']);
|
||||
const supportedSvgSchemes = new Set([Schemas.file, Schemas.vscodeFileResource, Schemas.vscodeRemoteResource, 'devtools']); // TODO: handle webview origin
|
||||
|
||||
// But allow them if the are made from inside an webview
|
||||
const isSafeFrame = (requestFrame: WebFrameMain | undefined): boolean => {
|
||||
for (let frame: WebFrameMain | null | undefined = requestFrame; frame; frame = frame.parent) {
|
||||
if (frame.url.startsWith(`${Schemas.vscodeWebview}://`)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this._win.webContents.session.webRequest.onBeforeRequest((details, callback) => {
|
||||
const uri = URI.parse(details.url);
|
||||
|
||||
// Prevent loading of remote svgs
|
||||
if (uri.path.endsWith('.svg')) {
|
||||
const safeScheme = svgFileSchemes.has(uri.scheme) || uri.path.includes(Schemas.vscodeRemoteResource);
|
||||
if (!safeScheme) {
|
||||
return callback({ cancel: true });
|
||||
const isSafeResourceUrl = supportedSvgSchemes.has(uri.scheme) || uri.path.includes(Schemas.vscodeRemoteResource);
|
||||
if (!isSafeResourceUrl) {
|
||||
const isSafeContext = isSafeFrame(details.frame);
|
||||
return callback({ cancel: !isSafeContext });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,17 +458,15 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
});
|
||||
|
||||
// Configure SVG header content type properly
|
||||
// https://github.com/microsoft/vscode/issues/97564
|
||||
this._win.webContents.session.webRequest.onHeadersReceived((details, callback) => {
|
||||
const responseHeaders = details.responseHeaders as Record<string, (string) | (string[])>;
|
||||
const contentTypes = (responseHeaders['content-type'] || responseHeaders['Content-Type']);
|
||||
|
||||
if (contentTypes && Array.isArray(contentTypes)) {
|
||||
const uri = URI.parse(details.url);
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/97564
|
||||
// ensure local svg files have Content-Type image/svg+xml
|
||||
if (uri.path.endsWith('.svg')) {
|
||||
if (svgFileSchemes.has(uri.scheme)) {
|
||||
if (supportedSvgSchemes.has(uri.scheme)) {
|
||||
responseHeaders['Content-Type'] = ['image/svg+xml'];
|
||||
|
||||
return callback({ cancel: false, responseHeaders });
|
||||
@@ -449,7 +476,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
// remote extension schemes have the following format
|
||||
// http://127.0.0.1:<port>/vscode-remote-resource?path=
|
||||
if (!uri.path.includes(Schemas.vscodeRemoteResource) && contentTypes.some(contentType => contentType.toLowerCase().includes('image/svg'))) {
|
||||
return callback({ cancel: true });
|
||||
const isSafeContext = isSafeFrame(details.frame);
|
||||
return callback({ cancel: !isSafeContext });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -680,58 +708,17 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
}
|
||||
}
|
||||
|
||||
load(config: INativeWindowConfiguration, { isReload, disableExtensions }: { isReload?: boolean, disableExtensions?: boolean } = Object.create(null)): void {
|
||||
|
||||
// If this window was loaded before from the command line
|
||||
// (as indicated by VSCODE_CLI environment), make sure to
|
||||
// preserve that user environment in subsequent loads,
|
||||
// unless the new configuration context was also a CLI
|
||||
// (for https://github.com/microsoft/vscode/issues/108571)
|
||||
const currentUserEnv = (this.currentConfig ?? this.pendingLoadConfig)?.userEnv;
|
||||
if (currentUserEnv && isLaunchedFromCli(currentUserEnv) && !isLaunchedFromCli(config.userEnv)) {
|
||||
config.userEnv = { ...currentUserEnv, ...config.userEnv }; // still allow to override certain environment as passed in
|
||||
}
|
||||
|
||||
// If named pipe was instantiated for the crashpad_handler process, reuse the same
|
||||
// pipe for new app instances connecting to the original app instance.
|
||||
// Ref: https://github.com/microsoft/vscode/issues/115874
|
||||
if (process.env['CHROME_CRASHPAD_PIPE_NAME']) {
|
||||
Object.assign(config.userEnv, {
|
||||
CHROME_CRASHPAD_PIPE_NAME: process.env['CHROME_CRASHPAD_PIPE_NAME']
|
||||
});
|
||||
}
|
||||
|
||||
// If this is the first time the window is loaded, we associate the paths
|
||||
// directly with the window because we assume the loading will just work
|
||||
if (this.readyState === ReadyState.NONE) {
|
||||
this.currentConfig = config;
|
||||
}
|
||||
|
||||
// Otherwise, the window is currently showing a folder and if there is an
|
||||
// unload handler preventing the load, we cannot just associate the paths
|
||||
// because the loading might be vetoed. Instead we associate it later when
|
||||
// the window load event has fired.
|
||||
else {
|
||||
this.pendingLoadConfig = config;
|
||||
this.readyState = ReadyState.NAVIGATING;
|
||||
}
|
||||
|
||||
// Add disable-extensions to the config, but do not preserve it on currentConfig or
|
||||
// pendingLoadConfig so that it is applied only on this load
|
||||
const configuration = { ...config };
|
||||
if (disableExtensions !== undefined) {
|
||||
configuration['disable-extensions'] = disableExtensions;
|
||||
}
|
||||
load(configuration: INativeWindowConfiguration, options: ILoadOptions = Object.create(null)): void {
|
||||
|
||||
// Clear Document Edited if needed
|
||||
if (this.isDocumentEdited()) {
|
||||
if (!isReload || !this.backupMainService.isHotExitEnabled()) {
|
||||
if (!options.isReload || !this.backupMainService.isHotExitEnabled()) {
|
||||
this.setDocumentEdited(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear Title and Filename if needed
|
||||
if (!isReload) {
|
||||
if (!options.isReload) {
|
||||
if (this.getRepresentedFilename()) {
|
||||
this.setRepresentedFilename('');
|
||||
}
|
||||
@@ -739,9 +726,30 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
this._win.setTitle(this.productService.nameLong);
|
||||
}
|
||||
|
||||
// Update configuration values based on our window context
|
||||
// and set it into the config object URL for usage.
|
||||
this.updateConfiguration(configuration, options);
|
||||
|
||||
// If this is the first time the window is loaded, we associate the paths
|
||||
// directly with the window because we assume the loading will just work
|
||||
if (this.readyState === ReadyState.NONE) {
|
||||
this.currentConfig = configuration;
|
||||
}
|
||||
|
||||
// Otherwise, the window is currently showing a folder and if there is an
|
||||
// unload handler preventing the load, we cannot just associate the paths
|
||||
// because the loading might be vetoed. Instead we associate it later when
|
||||
// the window load event has fired.
|
||||
else {
|
||||
this.pendingLoadConfig = configuration;
|
||||
this.readyState = ReadyState.NAVIGATING;
|
||||
}
|
||||
|
||||
// Load URL
|
||||
mark('code/willOpenNewWindow');
|
||||
this._win.loadURL(this.getUrl(configuration));
|
||||
this._win.loadURL(FileAccess.asBrowserUri(this.environmentMainService.sandbox ?
|
||||
'vs/code/electron-sandbox/workbench/workbench.html' :
|
||||
'vs/code/electron-browser/workbench/workbench.html', require
|
||||
).toString(true));
|
||||
|
||||
// Make window visible if it did not open in N seconds because this indicates an error
|
||||
// Only do this when running out of sources and not when running tests
|
||||
@@ -759,6 +767,45 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
this._onWillLoad.fire({ workspace: configuration.workspace });
|
||||
}
|
||||
|
||||
private updateConfiguration(configuration: INativeWindowConfiguration, options: ILoadOptions): void {
|
||||
|
||||
// If this window was loaded before from the command line
|
||||
// (as indicated by VSCODE_CLI environment), make sure to
|
||||
// preserve that user environment in subsequent loads,
|
||||
// unless the new configuration context was also a CLI
|
||||
// (for https://github.com/microsoft/vscode/issues/108571)
|
||||
const currentUserEnv = (this.currentConfig ?? this.pendingLoadConfig)?.userEnv;
|
||||
if (currentUserEnv && isLaunchedFromCli(currentUserEnv) && !isLaunchedFromCli(configuration.userEnv)) {
|
||||
configuration.userEnv = { ...currentUserEnv, ...configuration.userEnv }; // still allow to override certain environment as passed in
|
||||
}
|
||||
|
||||
// If named pipe was instantiated for the crashpad_handler process, reuse the same
|
||||
// pipe for new app instances connecting to the original app instance.
|
||||
// Ref: https://github.com/microsoft/vscode/issues/115874
|
||||
if (process.env['CHROME_CRASHPAD_PIPE_NAME']) {
|
||||
Object.assign(configuration.userEnv, {
|
||||
CHROME_CRASHPAD_PIPE_NAME: process.env['CHROME_CRASHPAD_PIPE_NAME']
|
||||
});
|
||||
}
|
||||
|
||||
// Add disable-extensions to the config, but do not preserve it on currentConfig or
|
||||
// pendingLoadConfig so that it is applied only on this load
|
||||
if (options.disableExtensions !== undefined) {
|
||||
configuration['disable-extensions'] = options.disableExtensions;
|
||||
}
|
||||
|
||||
// Update window related properties
|
||||
configuration.fullscreen = this.isFullScreen;
|
||||
configuration.maximized = this._win.isMaximized();
|
||||
|
||||
// Update with latest perf marks
|
||||
mark('code/willOpenNewWindow');
|
||||
configuration.perfMarks = getMarks();
|
||||
|
||||
// Update in config object URL for usage in renderer
|
||||
this.configObjectUrl.update(configuration);
|
||||
}
|
||||
|
||||
async reload(cli?: NativeParsedArgs): Promise<void> {
|
||||
|
||||
// Copy our current config for reuse
|
||||
@@ -816,87 +863,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
return configuration.workspace;
|
||||
}
|
||||
|
||||
private getUrl(windowConfiguration: INativeWindowConfiguration): string {
|
||||
|
||||
// Set window ID
|
||||
windowConfiguration.windowId = this._win.id;
|
||||
windowConfiguration.sessionId = `window:${this._win.id}`;
|
||||
windowConfiguration.logLevel = this.logService.getLevel();
|
||||
windowConfiguration.logsPath = this.environmentMainService.logsPath;
|
||||
|
||||
// Set zoomlevel
|
||||
const windowConfig = this.configurationService.getValue<IWindowSettings | undefined>('window');
|
||||
const zoomLevel = windowConfig?.zoomLevel;
|
||||
if (typeof zoomLevel === 'number') {
|
||||
windowConfiguration.zoomLevel = zoomLevel;
|
||||
}
|
||||
|
||||
// Set fullscreen state
|
||||
windowConfiguration.fullscreen = this.isFullScreen;
|
||||
|
||||
// Set Accessibility Config
|
||||
windowConfiguration.colorScheme = {
|
||||
dark: nativeTheme.shouldUseDarkColors,
|
||||
highContrast: nativeTheme.shouldUseInvertedColorScheme || nativeTheme.shouldUseHighContrastColors
|
||||
};
|
||||
windowConfiguration.autoDetectHighContrast = windowConfig?.autoDetectHighContrast ?? true;
|
||||
windowConfiguration.accessibilitySupport = app.accessibilitySupportEnabled;
|
||||
|
||||
// Title style related
|
||||
windowConfiguration.maximized = this._win.isMaximized();
|
||||
|
||||
// Dump Perf Counters
|
||||
windowConfiguration.perfMarks = getMarks();
|
||||
|
||||
// Parts splash
|
||||
windowConfiguration.partsSplashPath = join(this.environmentMainService.userDataPath, 'rapid_render.json');
|
||||
|
||||
// OS Info
|
||||
windowConfiguration.os = {
|
||||
release: release()
|
||||
};
|
||||
|
||||
// Config (combination of process.argv and window configuration)
|
||||
const environment = parseArgs(process.argv, OPTIONS);
|
||||
const config = Object.assign(environment, windowConfiguration) as unknown as { [key: string]: unknown };
|
||||
for (const key in config) {
|
||||
const configValue = config[key];
|
||||
if (configValue === undefined || configValue === null || configValue === '' || configValue === false) {
|
||||
delete config[key]; // only send over properties that have a true value
|
||||
}
|
||||
}
|
||||
|
||||
// In the unlikely event of the URL becoming larger than 2MB, remove parts of
|
||||
// it that are not under our control. Mainly, the user environment can be very
|
||||
// large depending on user configuration, so we can only remove it in that case.
|
||||
let configUrl = this.doGetUrl(config);
|
||||
if (configUrl.length > CodeWindow.MAX_URL_LENGTH) {
|
||||
this.logService.warn('Application URL exceeds maximum of 2MB and was shortened.');
|
||||
|
||||
configUrl = this.doGetUrl({ ...config, userEnv: undefined });
|
||||
|
||||
if (configUrl.length > CodeWindow.MAX_URL_LENGTH) {
|
||||
this.logService.error('Application URL exceeds maximum of 2MB and cannot be loaded.');
|
||||
}
|
||||
}
|
||||
|
||||
return configUrl;
|
||||
}
|
||||
|
||||
private doGetUrl(config: object): string {
|
||||
let workbench: string;
|
||||
if (this.environmentMainService.sandbox) {
|
||||
workbench = 'vs/code/electron-sandbox/workbench/workbench.html';
|
||||
} else {
|
||||
workbench = 'vs/code/electron-browser/workbench/workbench.html';
|
||||
}
|
||||
|
||||
return FileAccess
|
||||
.asBrowserUri(workbench, require)
|
||||
.with({ query: `config=${encodeURIComponent(JSON.stringify(config))}` })
|
||||
.toString(true);
|
||||
}
|
||||
|
||||
serializeWindowState(): IWindowState {
|
||||
if (!this._win) {
|
||||
return defaultWindowState();
|
||||
@@ -969,6 +935,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
}
|
||||
|
||||
private restoreWindowState(state?: IWindowState): [IWindowState, boolean? /* has multiple displays */] {
|
||||
mark('code/willRestoreCodeWindowState');
|
||||
|
||||
let hasMultipleDisplays = false;
|
||||
if (state) {
|
||||
try {
|
||||
@@ -981,6 +949,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
}
|
||||
}
|
||||
|
||||
mark('code/didRestoreCodeWindowState');
|
||||
|
||||
return [state || defaultWindowState(), hasMultipleDisplays];
|
||||
}
|
||||
|
||||
@@ -1382,7 +1352,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
return segments;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
override dispose(): void {
|
||||
super.dispose();
|
||||
|
||||
if (this.showTimeoutHandle) {
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { statSync } from 'fs';
|
||||
import { release, hostname } from 'os';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { mark, getMarks } from 'vs/base/common/performance';
|
||||
import { basename, normalize, join, posix } from 'vs/base/common/path';
|
||||
import { localize } from 'vs/nls';
|
||||
import { coalesce, distinct, firstOrDefault } from 'vs/base/common/arrays';
|
||||
@@ -13,13 +16,13 @@ import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/e
|
||||
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||
import { IStateService } from 'vs/platform/state/node/state';
|
||||
import { CodeWindow } from 'vs/platform/windows/electron-main/window';
|
||||
import { BrowserWindow, MessageBoxOptions, WebContents } from 'electron';
|
||||
import { ILifecycleMainService, UnloadReason, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
|
||||
import { app, BrowserWindow, MessageBoxOptions, nativeTheme, WebContents } from 'electron';
|
||||
import { ILifecycleMainService, UnloadReason } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IWindowSettings, IPath, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions, IAddFoldersRequest, IPathsToWaitFor, INativeWindowConfiguration, INativeOpenFileRequest } from 'vs/platform/windows/common/windows';
|
||||
import { findWindowOnFile, findWindowOnWorkspaceOrFolder, findWindowOnExtensionDevelopmentPath } from 'vs/platform/windows/electron-main/windowsFinder';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IOpenEmptyConfiguration, OpenContext } from 'vs/platform/windows/electron-main/windows';
|
||||
import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService';
|
||||
@@ -33,7 +36,7 @@ import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
|
||||
import { IWindowState, WindowsStateHandler } from 'vs/platform/windows/electron-main/windowsStateHandler';
|
||||
import { getSingleFolderWorkspaceIdentifier, getWorkspaceIdentifier, IWorkspacesManagementMainService } from 'vs/platform/workspaces/electron-main/workspacesManagementMainService';
|
||||
import { once } from 'vs/base/common/functional';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService';
|
||||
import { assertIsDefined, withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { isWindowsDriveLetter, toSlashes, parseLineAndColumnAware, sanitizeFilePath } from 'vs/base/common/extpath';
|
||||
@@ -42,6 +45,7 @@ import { getPathLabel } from 'vs/base/common/labels';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { cwd } from 'vs/base/common/process';
|
||||
import { IProtocolMainService } from 'vs/platform/protocol/electron-main/protocol';
|
||||
|
||||
//#region Helper Interfaces
|
||||
|
||||
@@ -151,17 +155,38 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IDialogMainService private readonly dialogMainService: IDialogMainService,
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
@IProductService private readonly productService: IProductService
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@IProtocolMainService private readonly protocolMainService: IProtocolMainService
|
||||
) {
|
||||
super();
|
||||
|
||||
this.lifecycleMainService.when(LifecycleMainPhase.Ready).then(() => this.registerListeners());
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
|
||||
// Signal a window is ready after having entered a workspace
|
||||
this._register(this.workspacesManagementMainService.onDidEnterWorkspace(event => this._onDidSignalReadyWindow.fire(event.window)));
|
||||
|
||||
// Update valid roots in protocol service for extension dev windows
|
||||
this._register(this.onDidSignalReadyWindow(window => {
|
||||
if (window.config?.extensionDevelopmentPath || window.config?.extensionTestsPath) {
|
||||
const disposables = new DisposableStore();
|
||||
disposables.add(Event.any(window.onDidClose, window.onDidDestroy)(() => disposables.dispose()));
|
||||
|
||||
// Allow access to extension development path
|
||||
if (window.config.extensionDevelopmentPath) {
|
||||
for (const extensionDevelopmentPath of window.config.extensionDevelopmentPath) {
|
||||
disposables.add(this.protocolMainService.addValidFileRoot(URI.file(extensionDevelopmentPath)));
|
||||
}
|
||||
}
|
||||
|
||||
// Allow access to extension tests path
|
||||
if (window.config.extensionTestsPath) {
|
||||
disposables.add(this.protocolMainService.addValidFileRoot(URI.file(window.config.extensionTestsPath)));
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
openEmptyWindow(openConfig: IOpenEmptyConfiguration, options?: IOpenEmptyWindowOptions): ICodeWindow[] {
|
||||
@@ -316,7 +341,15 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
// process can continue. We do this by deleting the waitMarkerFilePath.
|
||||
const waitMarkerFileURI = openConfig.waitMarkerFileURI;
|
||||
if (openConfig.context === OpenContext.CLI && waitMarkerFileURI && usedWindows.length === 1 && usedWindows[0]) {
|
||||
usedWindows[0].whenClosedOrLoaded.then(() => this.fileService.del(waitMarkerFileURI), () => undefined);
|
||||
(async () => {
|
||||
await usedWindows[0].whenClosedOrLoaded;
|
||||
|
||||
try {
|
||||
await this.fileService.del(waitMarkerFileURI);
|
||||
} catch (error) {
|
||||
// ignore - could have been deleted from the window already
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
return usedWindows;
|
||||
@@ -719,7 +752,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
// folder or file paths
|
||||
const cliPaths = cli._;
|
||||
for (const cliPath of cliPaths) {
|
||||
const path = cli.remote ? this.doResolvePathRemote(cliPath, cli.remote) : this.doResolveFilePath(cliPath, pathResolveOptions);
|
||||
const path = pathResolveOptions.remoteAuthority ? this.doResolvePathRemote(cliPath, pathResolveOptions) : this.doResolveFilePath(cliPath, pathResolveOptions);
|
||||
if (path) {
|
||||
pathsToOpen.push(path);
|
||||
}
|
||||
@@ -878,11 +911,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
let columnNumber: number | undefined;
|
||||
|
||||
if (options.gotoLineMode) {
|
||||
const parsedPath = parseLineAndColumnAware(path);
|
||||
lineNumber = parsedPath.line;
|
||||
columnNumber = parsedPath.column;
|
||||
|
||||
path = parsedPath.path;
|
||||
({ path, line: lineNumber, column: columnNumber } = parseLineAndColumnAware(path));
|
||||
}
|
||||
|
||||
// Ensure the path is normalized and absolute
|
||||
@@ -925,8 +954,17 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private doResolvePathRemote(path: string, remoteAuthority: string, forceOpenWorkspaceAsFile?: boolean): IPathToOpen | undefined {
|
||||
private doResolvePathRemote(path: string, options: IPathResolveOptions): IPathToOpen | undefined {
|
||||
const first = path.charCodeAt(0);
|
||||
const remoteAuthority = options.remoteAuthority;
|
||||
|
||||
// Extract line/col information from path
|
||||
let lineNumber: number | undefined;
|
||||
let columnNumber: number | undefined;
|
||||
|
||||
if (options.gotoLineMode) {
|
||||
({ path, line: lineNumber, column: columnNumber } = parseLineAndColumnAware(path));
|
||||
}
|
||||
|
||||
// make absolute
|
||||
if (first !== CharCode.Slash) {
|
||||
@@ -941,21 +979,21 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
|
||||
// guess the file type:
|
||||
// - if it ends with a slash it's a folder
|
||||
// - if it has a file extension, it's a file or a workspace
|
||||
// - if in goto line mode or if it has a file extension, it's a file or a workspace
|
||||
// - by defaults it's a folder
|
||||
if (path.charCodeAt(path.length - 1) !== CharCode.Slash) {
|
||||
|
||||
// file name ends with .code-workspace
|
||||
if (hasWorkspaceFileExtension(path)) {
|
||||
if (forceOpenWorkspaceAsFile) {
|
||||
return { fileUri: uri, remoteAuthority };
|
||||
if (options.forceOpenWorkspaceAsFile) {
|
||||
return { fileUri: uri, lineNumber, columnNumber, remoteAuthority: options.remoteAuthority };
|
||||
}
|
||||
return { workspace: getWorkspaceIdentifier(uri), remoteAuthority };
|
||||
}
|
||||
|
||||
// file name starts with a dot or has an file extension
|
||||
else if (posix.basename(path).indexOf('.') !== -1) {
|
||||
return { fileUri: uri, remoteAuthority };
|
||||
else if (options.gotoLineMode || posix.basename(path).indexOf('.') !== -1) {
|
||||
return { fileUri: uri, lineNumber, columnNumber, remoteAuthority };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1112,33 +1150,60 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
}
|
||||
|
||||
private openInBrowserWindow(options: IOpenBrowserWindowOptions): ICodeWindow {
|
||||
const windowConfig = this.configurationService.getValue<IWindowSettings | undefined>('window');
|
||||
|
||||
// Build `INativeWindowConfiguration` from config and options
|
||||
const configuration = { ...options.cli } as INativeWindowConfiguration;
|
||||
configuration.appRoot = this.environmentMainService.appRoot;
|
||||
configuration.machineId = this.machineId;
|
||||
configuration.nodeCachedDataDir = this.environmentMainService.nodeCachedDataDir;
|
||||
configuration.mainPid = process.pid;
|
||||
configuration.execPath = process.execPath;
|
||||
configuration.userEnv = { ...this.initialUserEnv, ...options.userEnv };
|
||||
configuration.isInitialStartup = options.initialStartup;
|
||||
configuration.workspace = options.workspace;
|
||||
configuration.remoteAuthority = options.remoteAuthority;
|
||||
// Build up the window configuration from provided options, config and environment
|
||||
const configuration: INativeWindowConfiguration = {
|
||||
|
||||
const filesToOpen = options.filesToOpen;
|
||||
if (filesToOpen) {
|
||||
configuration.filesToOpenOrCreate = filesToOpen.filesToOpenOrCreate;
|
||||
configuration.filesToDiff = filesToOpen.filesToDiff;
|
||||
configuration.filesToWait = filesToOpen.filesToWait;
|
||||
}
|
||||
// Inherit CLI arguments from environment and/or
|
||||
// the specific properties from this launch if provided
|
||||
...this.environmentMainService.args,
|
||||
...options.cli,
|
||||
|
||||
// if we know the backup folder upfront (for empty windows to restore), we can set it
|
||||
// directly here which helps for restoring UI state associated with that window.
|
||||
// For all other cases we first call into registerEmptyWindowBackupSync() to set it before
|
||||
// loading the window.
|
||||
if (options.emptyWindowBackupInfo) {
|
||||
configuration.backupPath = join(this.environmentMainService.backupHome, options.emptyWindowBackupInfo.backupFolder);
|
||||
}
|
||||
machineId: this.machineId,
|
||||
|
||||
windowId: -1, // Will be filled in by the window once loaded later
|
||||
|
||||
mainPid: process.pid,
|
||||
|
||||
appRoot: this.environmentMainService.appRoot,
|
||||
execPath: process.execPath,
|
||||
nodeCachedDataDir: this.environmentMainService.nodeCachedDataDir,
|
||||
partsSplashPath: join(this.environmentMainService.userDataPath, 'rapid_render.json'),
|
||||
// If we know the backup folder upfront (for empty windows to restore), we can set it
|
||||
// directly here which helps for restoring UI state associated with that window.
|
||||
// For all other cases we first call into registerEmptyWindowBackupSync() to set it before
|
||||
// loading the window.
|
||||
backupPath: options.emptyWindowBackupInfo ? join(this.environmentMainService.backupHome, options.emptyWindowBackupInfo.backupFolder) : undefined,
|
||||
|
||||
homeDir: this.environmentMainService.userHome.fsPath,
|
||||
tmpDir: this.environmentMainService.tmpDir.fsPath,
|
||||
userDataDir: this.environmentMainService.userDataPath,
|
||||
|
||||
remoteAuthority: options.remoteAuthority,
|
||||
workspace: options.workspace,
|
||||
userEnv: { ...this.initialUserEnv, ...options.userEnv },
|
||||
|
||||
filesToOpenOrCreate: options.filesToOpen?.filesToOpenOrCreate,
|
||||
filesToDiff: options.filesToOpen?.filesToDiff,
|
||||
filesToWait: options.filesToOpen?.filesToWait,
|
||||
|
||||
logLevel: this.logService.getLevel(),
|
||||
logsPath: this.environmentMainService.logsPath,
|
||||
|
||||
product,
|
||||
isInitialStartup: options.initialStartup,
|
||||
perfMarks: getMarks(),
|
||||
os: { release: release(), hostname: hostname() },
|
||||
zoomLevel: typeof windowConfig?.zoomLevel === 'number' ? windowConfig.zoomLevel : undefined,
|
||||
|
||||
autoDetectHighContrast: windowConfig?.autoDetectHighContrast ?? true,
|
||||
accessibilitySupport: app.accessibilitySupportEnabled,
|
||||
colorScheme: {
|
||||
dark: nativeTheme.shouldUseDarkColors,
|
||||
highContrast: nativeTheme.shouldUseInvertedColorScheme || nativeTheme.shouldUseHighContrastColors
|
||||
}
|
||||
};
|
||||
|
||||
let window: ICodeWindow | undefined;
|
||||
if (!options.forceNewWindow && !options.forceNewTabbedWindow) {
|
||||
@@ -1153,11 +1218,13 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
const state = this.windowsStateHandler.getNewWindowState(configuration);
|
||||
|
||||
// Create the window
|
||||
mark('code/willCreateCodeWindow');
|
||||
const createdWindow = window = this.instantiationService.createInstance(CodeWindow, {
|
||||
state,
|
||||
extensionDevelopmentPath: configuration.extensionDevelopmentPath,
|
||||
isExtensionTestHost: !!configuration.extensionTestsPath
|
||||
});
|
||||
mark('code/didCreateCodeWindow');
|
||||
|
||||
// Add as window tab if configured (macOS only)
|
||||
if (options.forceNewTabbedWindow) {
|
||||
@@ -1205,6 +1272,10 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
}
|
||||
}
|
||||
|
||||
// Update window identifier and session now
|
||||
// that we have the window object in hand.
|
||||
configuration.windowId = window.id;
|
||||
|
||||
// If the window was already loaded, make sure to unload it
|
||||
// first and only load the new configuration if that was
|
||||
// not vetoed
|
||||
|
||||
Reference in New Issue
Block a user