Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998 (#7880)

* Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998

* fix pipelines

* fix strict-null-checks

* add missing files
This commit is contained in:
Anthony Dresser
2019-10-21 22:12:22 -07:00
committed by GitHub
parent 7c9be74970
commit 1e22f47304
913 changed files with 18898 additions and 16536 deletions

View File

@@ -7,25 +7,8 @@
<!-- Disable pinch zooming -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<!-- Content Security Policy -->
<meta
http-equiv="Content-Security-Policy"
content="
default-src 'self';
img-src 'self' https: data: blob:;
media-src 'none';
script-src 'self' https://az416426.vo.msecnd.net 'unsafe-eval' https: 'sha256-AMRGFXNZ7mBnD/6F4lTV00XAjE5CBSM7ZeIv3DIp5YM=' 'sha256-meDZW3XhN5JmdjFUrWGhTouRKBiWYtXHltaKnqn/WMo=';
child-src 'self';
frame-src 'self' https://*.vscode-webview-test.com;
worker-src 'self';
style-src 'self' 'unsafe-inline';
connect-src 'self' ws: wss: https:;
font-src 'self' blob:;
manifest-src 'self';
">
<!-- Workbench Configuration -->
<meta id="vscode-workbench-web-configuration" data-settings="{{WORKBENCH_WEB_CONGIGURATION}}">
<meta id="vscode-workbench-web-configuration" data-settings="{{WORKBENCH_WEB_CONFIGURATION}}">
<!-- Workarounds/Hacks (remote user data uri) -->
<meta id="vscode-remote-user-data-uri" data-settings="{{REMOTE_USER_DATA_URI}}">
@@ -50,7 +33,6 @@
'xterm-addon-search': `${window.location.origin}/static/remote/web/node_modules/xterm-addon-search/lib/xterm-addon-search.js`,
'xterm-addon-web-links': `${window.location.origin}/static/remote/web/node_modules/xterm-addon-web-links/lib/xterm-addon-web-links.js`,
'semver-umd': `${window.location.origin}/static/remote/web/node_modules/semver-umd/lib/semver-umd.js`,
'@microsoft/applicationinsights-web': `${window.location.origin}/static/remote/web/node_modules/@microsoft/applicationinsights-web/dist/applicationinsights-web.js`,
}
};
</script>

View File

@@ -7,25 +7,8 @@
<!-- Disable pinch zooming -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<!-- Content Security Policy -->
<meta
http-equiv="Content-Security-Policy"
content="
default-src 'self';
img-src 'self' https: data: blob:;
media-src 'none';
script-src 'self' https://az416426.vo.msecnd.net 'unsafe-eval' https: 'sha256-4DqvCTjCHj2KW4QxC/Yt6uBwMRyYiEg7kOoykSEkonQ=';
child-src 'self';
frame-src 'self' https://*.vscode-webview-test.com;
worker-src 'self';
style-src 'self' 'unsafe-inline';
connect-src 'self' ws: wss: https:;
font-src 'self' blob:;
manifest-src 'self';
">
<!-- Workbench Configuration -->
<meta id="vscode-workbench-web-configuration" data-settings="{{WORKBENCH_WEB_CONGIGURATION}}">
<meta id="vscode-workbench-web-configuration" data-settings="{{WORKBENCH_WEB_CONFIGURATION}}">
<!-- Workarounds/Hacks (remote user data uri) -->
<meta id="vscode-remote-user-data-uri" data-settings="{{REMOTE_USER_DATA_URI}}">
@@ -37,7 +20,6 @@
<!-- Prefetch to avoid waterfall -->
<link rel="prefetch" href="./static/node_modules/semver-umd/lib/semver-umd.js">
<link rel="prefetch" href="./static/node_modules/@microsoft/applicationinsights-web/dist/applicationinsights-web.js">
</head>
<body aria-label="">
@@ -55,7 +37,6 @@
'xterm-addon-search': `${window.location.origin}/static/node_modules/xterm-addon-search/lib/xterm-addon-search.js`,
'xterm-addon-web-links': `${window.location.origin}/static/node_modules/xterm-addon-web-links/lib/xterm-addon-web-links.js`,
'semver-umd': `${window.location.origin}/static/node_modules/semver-umd/lib/semver-umd.js`,
'@microsoft/applicationinsights-web': `${window.location.origin}/static/node_modules/@microsoft/applicationinsights-web/dist/applicationinsights-web.js`,
}
};
</script>

View File

@@ -10,6 +10,8 @@ import { streamToBuffer } from 'vs/base/common/buffer';
import { Disposable } from 'vs/base/common/lifecycle';
import { request } from 'vs/base/parts/request/browser/request';
import { isFolderToOpen, isWorkspaceToOpen } from 'vs/platform/windows/common/windows';
import { isEqual } from 'vs/base/common/resources';
import { isStandalone } from 'vs/base/browser/browser';
interface ICredential {
service: string;
@@ -21,7 +23,7 @@ class LocalStorageCredentialsProvider implements ICredentialsProvider {
static readonly CREDENTIALS_OPENED_KEY = 'credentials.provider';
private _credentials!: ICredential[];
private _credentials: ICredential[] | undefined;
private get credentials(): ICredential[] {
if (!this._credentials) {
try {
@@ -102,10 +104,10 @@ class LocalStorageCredentialsProvider implements ICredentialsProvider {
class PollingURLCallbackProvider extends Disposable implements IURLCallbackProvider {
static FETCH_INTERVAL = 500; // fetch every 500ms
static FETCH_TIMEOUT = 5 * 60 * 1000; // ...but stop after 5min
static readonly FETCH_INTERVAL = 500; // fetch every 500ms
static readonly FETCH_TIMEOUT = 5 * 60 * 1000; // ...but stop after 5min
static QUERY_KEYS = {
static readonly QUERY_KEYS = {
REQUEST_ID: 'vscode-requestId',
SCHEME: 'vscode-scheme',
AUTHORITY: 'vscode-authority',
@@ -200,45 +202,119 @@ class PollingURLCallbackProvider extends Disposable implements IURLCallbackProvi
class WorkspaceProvider implements IWorkspaceProvider {
constructor(public readonly workspace: IWorkspace) { }
static QUERY_PARAM_EMPTY_WINDOW = 'ew';
static QUERY_PARAM_FOLDER = 'folder';
static QUERY_PARAM_WORKSPACE = 'workspace';
async open(workspace: IWorkspace, options?: { reuse?: boolean }): Promise<void> {
let targetHref: string | undefined = undefined;
constructor(
public readonly workspace: IWorkspace,
public readonly payload: object
) { }
async open(workspace: IWorkspace, options?: { reuse?: boolean, payload?: object }): Promise<void> {
if (options?.reuse && !options.payload && this.isSame(this.workspace, workspace)) {
return; // return early if workspace and environment is not changing and we are reusing window
}
// Empty
let targetHref: string | undefined = undefined;
if (!workspace) {
targetHref = `${document.location.origin}${document.location.pathname}?ew=true`;
targetHref = `${document.location.origin}${document.location.pathname}?${WorkspaceProvider.QUERY_PARAM_EMPTY_WINDOW}=true`;
}
// Folder
else if (isFolderToOpen(workspace)) {
targetHref = `${document.location.origin}${document.location.pathname}?folder=${workspace.folderUri.path}`;
targetHref = `${document.location.origin}${document.location.pathname}?${WorkspaceProvider.QUERY_PARAM_FOLDER}=${workspace.folderUri.path}`;
}
// Workspace
else if (isWorkspaceToOpen(workspace)) {
targetHref = `${document.location.origin}${document.location.pathname}?workspace=${workspace.workspaceUri.path}`;
targetHref = `${document.location.origin}${document.location.pathname}?${WorkspaceProvider.QUERY_PARAM_WORKSPACE}=${workspace.workspaceUri.path}`;
}
// Environment
if (options?.payload) {
targetHref += `&payload=${encodeURIComponent(JSON.stringify(options.payload))}`;
}
if (targetHref) {
if (options && options.reuse) {
if (options?.reuse) {
window.location.href = targetHref;
} else {
window.open(targetHref);
if (isStandalone) {
window.open(targetHref, '_blank', 'toolbar=no'); // ensures to open another 'standalone' window!
} else {
window.open(targetHref);
}
}
}
}
private isSame(workspaceA: IWorkspace, workspaceB: IWorkspace): boolean {
if (!workspaceA || !workspaceB) {
return workspaceA === workspaceB; // both empty
}
if (isFolderToOpen(workspaceA) && isFolderToOpen(workspaceB)) {
return isEqual(workspaceA.folderUri, workspaceB.folderUri); // same workspace
}
if (isWorkspaceToOpen(workspaceA) && isWorkspaceToOpen(workspaceB)) {
return isEqual(workspaceA.workspaceUri, workspaceB.workspaceUri); // same workspace
}
return false;
}
}
const options: IWorkbenchConstructionOptions & { folderUri?: UriComponents, workspaceUri?: UriComponents } = JSON.parse(document.getElementById('vscode-workbench-web-configuration')!.getAttribute('data-settings')!);
options.workspaceProvider = new WorkspaceProvider(options.folderUri ? { folderUri: URI.revive(options.folderUri) } : options.workspaceUri ? { workspaceUri: URI.revive(options.workspaceUri) } : undefined);
options.urlCallbackProvider = new PollingURLCallbackProvider();
options.credentialsProvider = new LocalStorageCredentialsProvider();
(function () {
if (Array.isArray(options.staticExtensions)) {
options.staticExtensions.forEach(extension => {
extension.extensionLocation = URI.revive(extension.extensionLocation);
});
}
// Find config element in DOM
const configElement = document.getElementById('vscode-workbench-web-configuration');
const configElementAttribute = configElement ? configElement.getAttribute('data-settings') : undefined;
if (!configElement || !configElementAttribute) {
throw new Error('Missing web configuration element');
}
create(document.body, options);
const options: IWorkbenchConstructionOptions & { folderUri?: UriComponents, workspaceUri?: UriComponents } = JSON.parse(configElementAttribute);
// Determine workspace to open
let workspace: IWorkspace;
if (options.folderUri) {
workspace = { folderUri: URI.revive(options.folderUri) };
} else if (options.workspaceUri) {
workspace = { workspaceUri: URI.revive(options.workspaceUri) };
} else {
workspace = undefined;
}
// Find payload
let payload = Object.create(null);
if (document.location.search) {
const query = document.location.search.substring(1);
const vars = query.split('&');
for (let p of vars) {
const pair = p.split('=');
if (pair.length === 2) {
const [key, value] = pair;
if (key === 'payload') {
payload = JSON.parse(decodeURIComponent(value));
break;
}
}
}
}
options.workspaceProvider = new WorkspaceProvider(workspace, payload);
options.urlCallbackProvider = new PollingURLCallbackProvider();
options.credentialsProvider = new LocalStorageCredentialsProvider();
if (Array.isArray(options.staticExtensions)) {
options.staticExtensions.forEach(extension => {
extension.extensionLocation = URI.revive(extension.extensionLocation);
});
}
// Finally create workbench
create(document.body, options);
})();

View File

@@ -10,4 +10,4 @@ const bootstrapWindow = require('../../../../bootstrap-window');
bootstrapWindow.load(['vs/code/electron-browser/issue/issueReporterMain'], function (issueReporter, configuration) {
issueReporter.startup(configuration);
}, { forceEnableDeveloperKeybindings: true });
}, { forceEnableDeveloperKeybindings: true, disallowReloadKeybinding: true });

View File

@@ -34,10 +34,9 @@ import { IssueReporterData, IssueReporterStyles, IssueType, ISettingsSearchIssue
import BaseHtml from 'vs/code/electron-browser/issue/issueReporterPage';
import { LoggerChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc';
import { ILogService, getLogLevel } from 'vs/platform/log/common/log';
import { OcticonLabel } from 'vs/base/browser/ui/octiconLabel/octiconLabel';
import { CodiconLabel } from 'vs/base/browser/ui/codiconLabel/codiconLabel';
import { normalizeGitHubUrl } from 'vs/code/electron-browser/issue/issueReporterUtil';
import { Button } from 'vs/base/browser/ui/button/button';
import { withUndefinedAsNull } from 'vs/base/common/types';
import { SystemInfo, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
import { SpdLogService } from 'vs/platform/log/node/spdlogService';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
@@ -232,7 +231,7 @@ export class IssueReporter extends Disposable {
styleTag.innerHTML = content.join('\n');
document.head.appendChild(styleTag);
document.body.style.color = withUndefinedAsNull(styles.color);
document.body.style.color = styles.color || '';
}
private handleExtensionData(extensions: IssueReporterExtensionData[]) {
@@ -649,8 +648,8 @@ export class IssueReporter extends Disposable {
issueState = $('span.issue-state');
const issueIcon = $('span.issue-icon');
const octicon = new OcticonLabel(issueIcon);
octicon.text = issue.state === 'open' ? '$(issue-opened)' : '$(issue-closed)';
const codicon = new CodiconLabel(issueIcon);
codicon.text = issue.state === 'open' ? '$(issue-opened)' : '$(issue-closed)';
const issueStateLabel = $('span.issue-state.label');
issueStateLabel.textContent = issue.state === 'open' ? localize('open', "Open") : localize('closed', "Closed");

View File

@@ -352,7 +352,7 @@ a {
text-overflow: ellipsis;
}
.issues-container > .issue > .issue-state .octicon {
.issues-container > .issue > .issue-state .codicon {
width: 16px;
}

View File

Before

Width:  |  Height:  |  Size: 139 B

After

Width:  |  Height:  |  Size: 139 B

View File

Before

Width:  |  Height:  |  Size: 118 B

After

Width:  |  Height:  |  Size: 118 B

View File

@@ -19,7 +19,6 @@ import { addDisposableListener } from 'vs/base/browser/dom';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { isRemoteDiagnosticError, IRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
let mapPidToWindowTitle = new Map<number, string>();
const DEBUG_FLAGS_PATTERN = /\s--(inspect|debug)(-brk|port)?=(\d+)?/;
@@ -374,9 +373,20 @@ function requestProcessList(totalWaitTime: number): void {
}, 200);
}
function createCloseListener(): void {
// Cmd/Ctrl + w closes process explorer
window.addEventListener('keydown', e => {
const cmdOrCtrlKey = platform.isMacintosh ? e.metaKey : e.ctrlKey;
if (cmdOrCtrlKey && e.keyCode === 87) {
ipcRenderer.send('vscode:closeProcessExplorer');
}
});
}
export function startup(data: ProcessExplorerData): void {
applyStyles(data.styles);
applyZoom(data.zoomLevel);
createCloseListener();
// Map window process pids to titles, annotate process names with this when rendering to distinguish between them
ipcRenderer.on('vscode:windowsInfoResponse', (_event: unknown, windows: any[]) => {

View File

@@ -13,7 +13,7 @@ import { IBackupWorkspacesFormat } from 'vs/platform/backup/node/backup';
export class StorageDataCleaner extends Disposable {
// Workspace/Folder storage names are MD5 hashes (128bits / 4 due to hex presentation)
private static NON_EMPTY_WORKSPACE_ID_LENGTH = 128 / 4;
private static readonly NON_EMPTY_WORKSPACE_ID_LENGTH = 128 / 4;
constructor(
@IEnvironmentService private readonly environmentService: IEnvironmentService

View File

@@ -3,9 +3,9 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { app, ipcMain as ipc, systemPreferences, shell, Event, contentTracing, protocol, powerMonitor, Event as IpcMainEvent, BrowserWindow } from 'electron';
import { app, ipcMain as ipc, systemPreferences, shell, Event, contentTracing, protocol, powerMonitor, IpcMainEvent, BrowserWindow } from 'electron';
import { IProcessEnvironment, isWindows, isMacintosh } from 'vs/base/common/platform';
import { WindowsManager } from 'vs/code/electron-main/windows';
import { WindowsMainService } from 'vs/platform/windows/electron-main/windowsMainService';
import { OpenContext, IWindowOpenable } from 'vs/platform/windows/common/windows';
import { ActiveWindowManager } from 'vs/code/node/activeWindowTracker';
import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
@@ -24,7 +24,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import { IStateService } from 'vs/platform/state/node/state';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IURLService } from 'vs/platform/url/common/url';
import { IURLService, IOpenURLOptions } from 'vs/platform/url/common/url';
import { URLHandlerChannelClient, URLHandlerRouter } from 'vs/platform/url/common/urlIpc';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService, combinedAppender, LogAppender } from 'vs/platform/telemetry/common/telemetryUtils';
@@ -74,8 +74,7 @@ import { FileService } from 'vs/platform/files/common/fileService';
import { IFileService } from 'vs/platform/files/common/files';
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
import { ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { ElectronMainService } from 'vs/platform/electron/electron-main/electronMainService';
import { IElectronMainService, ElectronMainService } from 'vs/platform/electron/electron-main/electronMainService';
import { ISharedProcessMainService, SharedProcessMainService } from 'vs/platform/ipc/electron-main/sharedProcessMainService';
import { assign } from 'vs/base/common/objects';
import { IDialogMainService, DialogMainService } from 'vs/platform/dialogs/electron-main/dialogs';
@@ -377,7 +376,7 @@ export class CodeApplication extends Disposable {
// Create driver
if (this.environmentService.driverHandle) {
const server = await serveDriver(electronIpcServer, this.environmentService.driverHandle!, this.environmentService, appInstantiationService);
const server = await serveDriver(electronIpcServer, this.environmentService.driverHandle, this.environmentService, appInstantiationService);
this.logService.info('Driver started at:', this.environmentService.driverHandle);
this._register(server);
@@ -450,7 +449,7 @@ export class CodeApplication extends Disposable {
break;
}
services.set(IWindowsMainService, new SyncDescriptor(WindowsManager, [machineId, this.userEnv]));
services.set(IWindowsMainService, new SyncDescriptor(WindowsMainService, [machineId, this.userEnv]));
services.set(IDialogMainService, new SyncDescriptor(DialogMainService));
services.set(ISharedProcessMainService, new SyncDescriptor(SharedProcessMainService, [sharedProcess]));
services.set(ILaunchMainService, new SyncDescriptor(LaunchMainService));
@@ -459,7 +458,7 @@ export class CodeApplication extends Disposable {
services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService, [diagnosticsChannel]));
services.set(IIssueService, new SyncDescriptor(IssueMainService, [machineId, this.userEnv]));
services.set(IElectronService, new SyncDescriptor(ElectronMainService));
services.set(IElectronMainService, new SyncDescriptor(ElectronMainService));
services.set(IWorkspacesService, new SyncDescriptor(WorkspacesService));
services.set(IMenubarService, new SyncDescriptor(MenubarMainService));
@@ -546,8 +545,8 @@ export class CodeApplication extends Disposable {
const issueChannel = createChannelReceiver(issueService);
electronIpcServer.registerChannel('issue', issueChannel);
const electronService = accessor.get(IElectronService);
const electronChannel = createChannelReceiver(electronService);
const electronMainService = accessor.get(IElectronMainService);
const electronChannel = createChannelReceiver(electronMainService);
electronIpcServer.registerChannel('electron', electronChannel);
sharedProcessClient.then(client => client.registerChannel('electron', electronChannel));
@@ -588,12 +587,14 @@ export class CodeApplication extends Disposable {
// Create a URL handler to open file URIs in the active window
const environmentService = accessor.get(IEnvironmentService);
urlService.registerHandler({
async handleURL(uri: URI): Promise<boolean> {
async handleURL(uri: URI, options?: IOpenURLOptions): Promise<boolean> {
// Catch file URLs
if (uri.authority === Schemas.file && !!uri.path) {
const cli = assign(Object.create(null), environmentService.args);
const urisToOpen = [{ fileUri: uri }];
// hey Ben, we need to convert this `code://file` URI into a `file://` URI
const urisToOpen = [{ fileUri: URI.file(uri.fsPath) }];
windowsMainService.open({ context: OpenContext.API, cli, urisToOpen, gotoLineMode: true });
@@ -605,7 +606,7 @@ export class CodeApplication extends Disposable {
});
// Create a URL handler which forwards to the last active window
const activeWindowManager = new ActiveWindowManager(electronService);
const activeWindowManager = new ActiveWindowManager(electronMainService);
const activeWindowRouter = new StaticRouter(ctx => activeWindowManager.getActiveClientId().then(id => ctx === id));
const urlHandlerRouter = new URLHandlerRouter(activeWindowRouter);
const urlHandlerChannel = electronIpcServer.getChannel('urlHandler', urlHandlerRouter);
@@ -615,7 +616,7 @@ export class CodeApplication extends Disposable {
// if there is none
if (isMacintosh) {
urlService.registerHandler({
async handleURL(uri: URI): Promise<boolean> {
async handleURL(uri: URI, options?: IOpenURLOptions): Promise<boolean> {
if (windowsMainService.getWindowCount() === 0) {
const cli = { ...environmentService.args };
const [window] = windowsMainService.open({ context: OpenContext.API, cli, forceEmpty: true, gotoLineMode: true });
@@ -662,7 +663,7 @@ export class CodeApplication extends Disposable {
}
// mac: open-file event received on startup
if (macOpenFiles && macOpenFiles.length && !hasCliArgs && !hasFolderURIs && !hasFileURIs) {
if (macOpenFiles.length && !hasCliArgs && !hasFolderURIs && !hasFileURIs) {
return windowsMainService.open({
context: OpenContext.DOCK,
cli: args,

View File

@@ -6,7 +6,7 @@
import 'vs/platform/update/common/update.config.contribution';
import { app, dialog } from 'electron';
import { assign } from 'vs/base/common/objects';
import * as platform from 'vs/base/common/platform';
import { isWindows, IProcessEnvironment, isMacintosh } from 'vs/base/common/platform';
import product from 'vs/platform/product/common/product';
import { parseMainProcessArgv } from 'vs/platform/environment/node/argvHelper';
import { addArg, createWaitMarkerFile } from 'vs/platform/environment/node/argv';
@@ -132,7 +132,7 @@ class CodeMain {
}
}
private createServices(args: ParsedArgs, bufferLogService: BufferLogService): [IInstantiationService, typeof process.env] {
private createServices(args: ParsedArgs, bufferLogService: BufferLogService): [IInstantiationService, IProcessEnvironment] {
const services = new ServiceCollection();
const environmentService = new EnvironmentService(args, process.execPath);
@@ -174,18 +174,17 @@ class CodeMain {
return Promise.all([environmentServiceInitialization, configurationServiceInitialization, stateServiceInitialization]);
}
private patchEnvironment(environmentService: IEnvironmentService): typeof process.env {
const instanceEnvironment: typeof process.env = {
VSCODE_IPC_HOOK: environmentService.mainIPCHandle,
VSCODE_NLS_CONFIG: process.env['VSCODE_NLS_CONFIG'],
VSCODE_LOGS: process.env['VSCODE_LOGS'],
// {{SQL CARBON EDIT}} We keep VSCODE_LOGS to not break functionality for merged code
ADS_LOGS: process.env['ADS_LOGS']
private patchEnvironment(environmentService: IEnvironmentService): IProcessEnvironment {
const instanceEnvironment: IProcessEnvironment = {
VSCODE_IPC_HOOK: environmentService.mainIPCHandle
};
if (process.env['VSCODE_PORTABLE']) {
instanceEnvironment['VSCODE_PORTABLE'] = process.env['VSCODE_PORTABLE'];
}
['VSCODE_NLS_CONFIG', 'VSCODE_LOGS', 'VSCODE_PORTABLE', 'ADS_LOGS'].forEach(key => { // {{SQL CARBON EDIT}} add ads logs
const value = process.env[key];
if (typeof value === 'string') {
instanceEnvironment[key] = value;
}
});
assign(process.env, instanceEnvironment);
@@ -215,7 +214,7 @@ class CodeMain {
}
// Since we are the second instance, we do not want to show the dock
if (platform.isMacintosh) {
if (isMacintosh) {
app.dock.hide();
}
@@ -226,7 +225,7 @@ class CodeMain {
} catch (error) {
// Handle unexpected connection errors by showing a dialog to the user
if (!retry || platform.isWindows || error.code !== 'ECONNREFUSED') {
if (!retry || isWindows || error.code !== 'ECONNREFUSED') {
if (error.code === 'EPERM') {
this.showStartupWarningDialog(
localize('secondInstanceAdmin', "A second instance of {0} is already running as administrator.", product.nameShort),
@@ -292,16 +291,16 @@ class CodeMain {
}
// Windows: allow to set foreground
if (platform.isWindows) {
if (isWindows) {
await this.windowsAllowSetForegroundWindow(launchService, logService);
}
// Send environment over...
logService.trace('Sending env to running instance...');
await launchService.start(environmentService.args, process.env as platform.IProcessEnvironment);
await launchService.start(environmentService.args, process.env as IProcessEnvironment);
// Cleanup
await client.dispose();
client.dispose();
// Now that we started, make sure the warning dialog is prevented
if (startupWarningDialogHandle) {
@@ -319,7 +318,7 @@ class CodeMain {
}
// dock might be hidden at this case due to a retry
if (platform.isMacintosh) {
if (isMacintosh) {
app.dock.show();
}
@@ -361,7 +360,7 @@ class CodeMain {
}
private async windowsAllowSetForegroundWindow(launchService: ILaunchMainService, logService: ILogService): Promise<void> {
if (platform.isWindows) {
if (isWindows) {
const processId = await launchService.getMainProcessId();
logService.trace('Sending some foreground love to the running instance:', processId);

View File

@@ -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'):

File diff suppressed because it is too large Load Diff

View File

@@ -1,93 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { URI, UriComponents } from 'vs/base/common/uri';
import { IWindowState as IWindowUIState } from 'vs/platform/windows/electron-main/windows';
import { IWindowState, IWindowsState } from 'vs/code/electron-main/windows';
export type WindowsStateStorageData = object;
interface ISerializedWindowsState {
lastActiveWindow?: ISerializedWindowState;
lastPluginDevelopmentHostWindow?: ISerializedWindowState;
openedWindows: ISerializedWindowState[];
}
interface ISerializedWindowState {
workspaceIdentifier?: { id: string; configURIPath: string };
folder?: string;
backupPath?: string;
remoteAuthority?: string;
uiState: IWindowUIState;
// deprecated
folderUri?: UriComponents;
folderPath?: string;
workspace?: { id: string; configPath: string };
}
export function restoreWindowsState(data: WindowsStateStorageData | undefined): IWindowsState {
const result: IWindowsState = { openedWindows: [] };
const windowsState = data as ISerializedWindowsState || { openedWindows: [] };
if (windowsState.lastActiveWindow) {
result.lastActiveWindow = restoreWindowState(windowsState.lastActiveWindow);
}
if (windowsState.lastPluginDevelopmentHostWindow) {
result.lastPluginDevelopmentHostWindow = restoreWindowState(windowsState.lastPluginDevelopmentHostWindow);
}
if (Array.isArray(windowsState.openedWindows)) {
result.openedWindows = windowsState.openedWindows.map(windowState => restoreWindowState(windowState));
}
return result;
}
function restoreWindowState(windowState: ISerializedWindowState): IWindowState {
const result: IWindowState = { uiState: windowState.uiState };
if (windowState.backupPath) {
result.backupPath = windowState.backupPath;
}
if (windowState.remoteAuthority) {
result.remoteAuthority = windowState.remoteAuthority;
}
if (windowState.folder) {
result.folderUri = URI.parse(windowState.folder);
} else if (windowState.folderUri) {
result.folderUri = URI.revive(windowState.folderUri);
} else if (windowState.folderPath) {
result.folderUri = URI.file(windowState.folderPath);
}
if (windowState.workspaceIdentifier) {
result.workspace = { id: windowState.workspaceIdentifier.id, configPath: URI.parse(windowState.workspaceIdentifier.configURIPath) };
} else if (windowState.workspace) {
result.workspace = { id: windowState.workspace.id, configPath: URI.file(windowState.workspace.configPath) };
}
return result;
}
export function getWindowsStateStoreData(windowsState: IWindowsState): WindowsStateStorageData {
return {
lastActiveWindow: windowsState.lastActiveWindow && serializeWindowState(windowsState.lastActiveWindow),
lastPluginDevelopmentHostWindow: windowsState.lastPluginDevelopmentHostWindow && serializeWindowState(windowsState.lastPluginDevelopmentHostWindow),
openedWindows: windowsState.openedWindows.map(ws => serializeWindowState(ws))
};
}
function serializeWindowState(windowState: IWindowState): ISerializedWindowState {
return {
workspaceIdentifier: windowState.workspace && { id: windowState.workspace.id, configURIPath: windowState.workspace.configPath.toString() },
folder: windowState.folderUri && windowState.folderUri.toString(),
backupPath: windowState.backupPath,
remoteAuthority: windowState.remoteAuthority,
uiState: windowState.uiState
};
}

View File

@@ -14,7 +14,7 @@ import * as paths from 'vs/base/common/path';
import { whenDeleted, writeFileSync } from 'vs/base/node/pfs';
import { findFreePort, randomPort } from 'vs/base/node/ports';
import { resolveTerminalEncoding } from 'vs/base/node/encoding';
import { isWindows } from 'vs/base/common/platform';
import { isWindows, isLinux } from 'vs/base/common/platform';
import { ProfilingSession, Target } from 'v8-inspect-profiler';
import { isString } from 'vs/base/common/types';
@@ -360,6 +360,10 @@ export async function main(argv: string[]): Promise<any> {
options['stdio'] = 'ignore';
}
if (isLinux) {
addArg(argv, '--no-sandbox'); // Electron 6 introduces a chrome-sandbox that requires root to run. This can fail. Disable sandbox via --no-sandbox
}
const child = spawn(process.execPath, argv.slice(2), options);
if (args.wait && waitMarkerFilePath) {

View File

@@ -19,12 +19,14 @@ export function validatePaths(args: ParsedArgs): ParsedArgs {
args._ = [];
}
// Normalize paths and watch out for goto line mode
const paths = doValidatePaths(args._, args.goto);
if (!args['remote']) {
// Normalize paths and watch out for goto line mode
const paths = doValidatePaths(args._, args.goto);
args._ = paths;
}
// Update environment
args._ = paths;
args.diff = args.diff && paths.length === 2;
args.diff = args.diff && args._.length === 2;
return args;
}
@@ -135,4 +137,4 @@ function toPath(p: IPathWithLineAndColumn): string {
}
return segments.join(':');
}
}

View File

@@ -6,11 +6,11 @@ import * as assert from 'assert';
import * as os from 'os';
import * as path from 'vs/base/common/path';
import { restoreWindowsState, getWindowsStateStoreData } from 'vs/code/electron-main/windowsStateStorage';
import { restoreWindowsState, getWindowsStateStoreData } from 'vs/platform/windows/electron-main/windowsStateStorage';
import { IWindowState as IWindowUIState, WindowMode } from 'vs/platform/windows/electron-main/windows';
import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri';
import { IWindowsState, IWindowState } from 'vs/code/electron-main/windows';
import { IWindowsState, IWindowState } from 'vs/platform/windows/electron-main/windowsMainService';
function getUIState(): IWindowUIState {
return {