mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-29 01:25:37 -05:00
Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998 (#7880)
* Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998 * fix pipelines * fix strict-null-checks * add missing files
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
})();
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -352,7 +352,7 @@ a {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.issues-container > .issue > .issue-state .octicon {
|
||||
.issues-container > .issue > .issue-state .codicon {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
|
||||
0
src/vs/code/electron-browser/processExplorer/media/collapsed.svg
Executable file → Normal file
0
src/vs/code/electron-browser/processExplorer/media/collapsed.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 139 B After Width: | Height: | Size: 139 B |
0
src/vs/code/electron-browser/processExplorer/media/expanded.svg
Executable file → Normal file
0
src/vs/code/electron-browser/processExplorer/media/expanded.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 118 B After Width: | Height: | Size: 118 B |
@@ -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[]) => {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
|
||||
};
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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(':');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user