Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)

* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973

* disable strict null check
This commit is contained in:
Anthony Dresser
2019-07-15 22:35:46 -07:00
committed by GitHub
parent f720ec642f
commit 0b7e7ddbf9
2406 changed files with 59140 additions and 35464 deletions

View File

@@ -7,14 +7,13 @@ import * as path from 'vs/base/common/path';
import * as objects from 'vs/base/common/objects';
import * as nls from 'vs/nls';
import { URI } from 'vs/base/common/uri';
import { IStateService } from 'vs/platform/state/common/state';
import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display } from 'electron';
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
import { ILogService } from 'vs/platform/log/common/log';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { parseArgs } from 'vs/platform/environment/node/argv';
import product from 'vs/platform/product/node/product';
import { IWindowSettings, MenuBarVisibility, IWindowConfiguration, ReadyState, IRunActionInWindowRequest, getTitleBarStyle } from 'vs/platform/windows/common/windows';
import { IWindowSettings, MenuBarVisibility, IWindowConfiguration, ReadyState, getTitleBarStyle } 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';
@@ -22,10 +21,14 @@ import { IWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/worksp
import { IBackupMainService } from 'vs/platform/backup/common/backup';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import * as perf from 'vs/base/common/performance';
import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/node/extensionGalleryService';
import { getBackgroundColor } from 'vs/code/electron-main/theme';
import { RunOnceScheduler } from 'vs/base/common/async';
import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/common/extensionGalleryService';
import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainService';
import { endsWith } from 'vs/base/common/strings';
import { RunOnceScheduler } from 'vs/base/common/async';
import { IFileService } from 'vs/platform/files/common/files';
import pkg from 'vs/platform/product/node/package';
const RUN_TEXTMATE_IN_WORKER = false;
export interface IWindowCreationOptions {
state: IWindowState;
@@ -41,14 +44,6 @@ export const defaultWindowState = function (mode = WindowMode.Normal): IWindowSt
};
};
interface IWorkbenchEditorConfiguration {
workbench: {
editor: {
swipeToNavigate: boolean
}
};
}
interface ITouchBarSegment extends Electron.SegmentedControlSegment {
id: string;
}
@@ -83,8 +78,9 @@ export class CodeWindow extends Disposable implements ICodeWindow {
config: IWindowCreationOptions,
@ILogService private readonly logService: ILogService,
@IEnvironmentService private readonly environmentService: IEnvironmentService,
@IFileService private readonly fileService: IFileService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IStateService private readonly stateService: IStateService,
@IThemeMainService private readonly themeMainService: IThemeMainService,
@IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService,
@IBackupMainService private readonly backupMainService: IBackupMainService,
) {
@@ -114,7 +110,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
private createBrowserWindow(config: IWindowCreationOptions): void {
// Load window state
this.windowState = this.restoreWindowState(config.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);
@@ -124,7 +121,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
height: this.windowState.height,
x: this.windowState.x,
y: this.windowState.y,
backgroundColor: getBackgroundColor(this.stateService),
backgroundColor: this.themeMainService.getBackgroundColor(),
minWidth: CodeWindow.MIN_WIDTH,
minHeight: CodeWindow.MIN_HEIGHT,
show: !isFullscreenOrMaximized,
@@ -134,7 +131,10 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// 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
backgroundThrottling: false,
nodeIntegration: true,
nodeIntegrationInWorker: RUN_TEXTMATE_IN_WORKER,
webviewTag: true
}
};
@@ -156,7 +156,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
}
if (isMacintosh && windowConfig && windowConfig.nativeTabs === true) {
const useNativeTabs = isMacintosh && windowConfig && windowConfig.nativeTabs === true;
if (useNativeTabs) {
options.tabbingIdentifier = product.nameShort; // this opts in to sierra tabs
}
@@ -177,6 +178,24 @@ export class CodeWindow extends Disposable implements ICodeWindow {
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();
@@ -204,12 +223,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
return !!this.config.extensionTestsPath;
}
/*
get extensionDevelopmentPaths(): string | string[] | undefined {
return this.config.extensionDevelopmentPath;
}
*/
get config(): IWindowConfiguration {
return this.currentConfig;
}
@@ -297,13 +310,13 @@ export class CodeWindow extends Disposable implements ICodeWindow {
private handleMarketplaceRequests(): void {
// Resolve marketplace headers
this.marketplaceHeadersPromise = resolveMarketplaceHeaders(this.environmentService);
this.marketplaceHeadersPromise = resolveMarketplaceHeaders(pkg.version, this.environmentService, this.fileService);
// 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);
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`;
}
@@ -327,12 +340,14 @@ export class CodeWindow extends Disposable implements ICodeWindow {
});
this._win.webContents.session.webRequest.onHeadersReceived(null!, (details, callback) => {
const contentType: string[] = (details.responseHeaders['content-type'] || details.responseHeaders['Content-Type']);
const responseHeaders = details.responseHeaders as { [key: string]: string[] };
const contentType: string[] = (responseHeaders['content-type'] || responseHeaders['Content-Type']);
if (contentType && Array.isArray(contentType) && contentType.some(x => x.toLowerCase().indexOf('image/svg') >= 0)) {
return callback({ cancel: true });
}
return callback({ cancel: false, responseHeaders: details.responseHeaders });
return callback({ cancel: false, responseHeaders });
});
// Remember that we loaded
@@ -358,9 +373,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
});
// App commands support
this.registerNavigationListenerOn('app-command', 'browser-backward', 'browser-forward', false);
// Window Focus
this._win.on('focus', () => {
this._lastFocusTime = Date.now();
@@ -446,30 +458,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
this.currentMenuBarVisibility = newMenuBarVisibility;
this.setMenuBarVisibility(newMenuBarVisibility);
}
// Swipe command support (macOS)
if (isMacintosh) {
const config = this.configurationService.getValue<IWorkbenchEditorConfiguration>();
if (config && config.workbench && config.workbench.editor && config.workbench.editor.swipeToNavigate) {
this.registerNavigationListenerOn('swipe', 'left', 'right', true);
} else {
this._win.removeAllListeners('swipe');
}
}
}
private registerNavigationListenerOn(command: 'swipe' | 'app-command', back: 'left' | 'browser-backward', forward: 'right' | 'browser-forward', acrossEditors: boolean) {
this._win.on(command as 'swipe' /* | 'app-command' */, (e: Electron.Event, cmd: string) => {
if (!this.isReady) {
return; // window must be ready
}
if (cmd === back) {
this.send('vscode:runAction', { id: acrossEditors ? 'workbench.action.openPreviousRecentlyUsedEditor' : 'workbench.action.navigateBack', from: 'mouse' } as IRunActionInWindowRequest);
} else if (cmd === forward) {
this.send('vscode:runAction', { id: acrossEditors ? 'workbench.action.openNextRecentlyUsedEditor' : 'workbench.action.navigateForward', from: 'mouse' } as IRunActionInWindowRequest);
}
});
}
addTabbedWindow(window: ICodeWindow): void {
@@ -599,9 +587,10 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// Config (combination of process.argv and window configuration)
const environment = parseArgs(process.argv);
const config = objects.assign(environment, windowConfiguration);
for (let key in config) {
if (config[key] === undefined || config[key] === null || config[key] === '' || config[key] === false) {
delete config[key]; // only send over properties that have a true value
for (const key in config) {
const configValue = (config as any)[key];
if (configValue === undefined || configValue === null || configValue === '' || configValue === false) {
delete (config as any)[key]; // only send over properties that have a true value
}
}
@@ -675,7 +664,12 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// only consider non-minimized window states
if (mode === WindowMode.Normal || mode === WindowMode.Maximized) {
const bounds = this.getBounds();
let bounds: Electron.Rectangle;
if (mode === WindowMode.Normal) {
bounds = this.getBounds();
} else {
bounds = this._win.getNormalBounds(); // make sure to persist the normal bounds when maximized to be able to restore them
}
state.x = bounds.x;
state.y = bounds.y;
@@ -686,18 +680,23 @@ export class CodeWindow extends Disposable implements ICodeWindow {
return state;
}
private restoreWindowState(state?: IWindowState): IWindowState {
private restoreWindowState(state?: IWindowState): [IWindowState, boolean? /* has multiple displays */] {
let hasMultipleDisplays = false;
if (state) {
try {
state = this.validateWindowState(state);
const displays = screen.getAllDisplays();
hasMultipleDisplays = displays.length > 1;
state = this.validateWindowState(state, displays);
} catch (err) {
this.logService.warn(`Unexpected error validating window state: ${err}\n${err.stack}`); // somehow display API can be picky about the state to validate
}
}
return state || defaultWindowState();
return [state || defaultWindowState(), hasMultipleDisplays];
}
private validateWindowState(state: IWindowState): IWindowState | undefined {
private validateWindowState(state: IWindowState, displays: Display[]): IWindowState | undefined {
if (typeof state.x !== 'number'
|| typeof state.y !== 'number'
|| typeof state.width !== 'number'
@@ -710,12 +709,10 @@ export class CodeWindow extends Disposable implements ICodeWindow {
return undefined;
}
const displays = screen.getAllDisplays();
// Single Monitor: be strict about x/y positioning
if (displays.length === 1) {
const displayWorkingArea = this.getWorkingArea(displays[0]);
if (state.mode !== WindowMode.Maximized && displayWorkingArea) {
if (displayWorkingArea) {
if (state.x < displayWorkingArea.x) {
state.x = displayWorkingArea.x; // prevent window from falling out of the screen to the left
}
@@ -741,10 +738,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
}
if (state.mode === WindowMode.Maximized) {
return defaultWindowState(WindowMode.Maximized); // when maximized, make sure we have good values when the user restores the window
}
return state;
}
@@ -772,14 +765,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
bounds.x + bounds.width > displayWorkingArea.x && // prevent window from falling out of the screen to the left
bounds.y + bounds.height > displayWorkingArea.y // prevent window from falling out of the scree nto the top
) {
if (state.mode === WindowMode.Maximized) {
const defaults = defaultWindowState(WindowMode.Maximized); // when maximized, make sure we have good values when the user restores the window
defaults.x = state.x; // carefull to keep x/y position so that the window ends up on the correct monitor
defaults.y = state.y;
return defaults;
}
return state;
}
@@ -853,16 +838,17 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
private useNativeFullScreen(): boolean {
const windowConfig = this.configurationService.getValue<IWindowSettings>('window');
if (!windowConfig || typeof windowConfig.nativeFullScreen !== 'boolean') {
return true; // default
}
return true; // TODO@ben enable simple fullscreen again (https://github.com/microsoft/vscode/issues/75054)
// const windowConfig = this.configurationService.getValue<IWindowSettings>('window');
// if (!windowConfig || typeof windowConfig.nativeFullScreen !== 'boolean') {
// return true; // default
// }
if (windowConfig.nativeTabs) {
return true; // https://github.com/electron/electron/issues/16142
}
// if (windowConfig.nativeTabs) {
// return true; // https://github.com/electron/electron/issues/16142
// }
return windowConfig.nativeFullScreen !== false;
// return windowConfig.nativeFullScreen !== false;
}
isMinimized(): boolean {