Merge from master

This commit is contained in:
Raj Musuku
2019-02-21 17:56:04 -08:00
parent 5a146e34fa
commit 666ae11639
11482 changed files with 119352 additions and 255574 deletions

View File

@@ -3,21 +3,20 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { Event, latch, anyEvent } from 'vs/base/common/event';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
import { IProcessEnvironment } from 'vs/base/common/platform';
import { ParsedArgs } from 'vs/platform/environment/common/environment';
import { IProcessEnvironment, isMacintosh, isWindows } from 'vs/base/common/platform';
import { ParsedArgs, IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IWorkspaceIdentifier, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IRecentlyOpened } from 'vs/platform/history/common/history';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import { PerformanceEntry } from 'vs/base/common/performance';
import { ExportData } from 'vs/base/common/performance';
import { LogLevel } from 'vs/platform/log/common/log';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import URI, { UriComponents } from 'vs/base/common/uri';
import { URI, UriComponents } from 'vs/base/common/uri';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
export const IWindowsService = createDecorator<IWindowsService>('windowsService');
@@ -84,13 +83,8 @@ export interface SaveDialogOptions {
showsTagField?: boolean;
}
export interface OpenDialogOptions {
title?: string;
defaultPath?: string;
buttonLabel?: string;
filters?: FileFilter[];
properties?: Array<'openFile' | 'openDirectory' | 'multiSelections' | 'showHiddenFiles' | 'createDirectory' | 'promptToCreate' | 'noResolveAliases' | 'treatPackageAsDirectory'>;
message?: string;
export interface INewWindowOptions {
remoteAuthority?: string;
}
export interface IDevToolsOptions {
@@ -126,8 +120,8 @@ export interface IWindowsService {
saveAndEnterWorkspace(windowId: number, path: string): TPromise<IEnterWorkspaceResult>;
toggleFullScreen(windowId: number): TPromise<void>;
setRepresentedFilename(windowId: number, fileName: string): TPromise<void>;
addRecentlyOpened(files: string[]): TPromise<void>;
removeFromRecentlyOpened(paths: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | string)[]): TPromise<void>;
addRecentlyOpened(files: URI[]): TPromise<void>;
removeFromRecentlyOpened(paths: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI | string)[]): TPromise<void>;
clearRecentlyOpened(): TPromise<void>;
getRecentlyOpened(windowId: number): TPromise<IRecentlyOpened>;
focusWindow(windowId: number): TPromise<void>;
@@ -143,6 +137,7 @@ export interface IWindowsService {
relaunch(options: { addArgs?: string[], removeArgs?: string[] }): TPromise<void>;
// macOS Native Tabs
newWindowTab(): TPromise<void>;
showPreviousWindowTab(): TPromise<void>;
showNextWindowTab(): TPromise<void>;
moveWindowTabToNewWindow(): TPromise<void>;
@@ -158,7 +153,7 @@ export interface IWindowsService {
// Global methods
openWindow(windowId: number, paths: URI[], options?: { forceNewWindow?: boolean, forceReuseWindow?: boolean, forceOpenWorkspaceAsFile?: boolean, args?: ParsedArgs }): TPromise<void>;
openNewWindow(): TPromise<void>;
openNewWindow(options?: INewWindowOptions): TPromise<void>;
showWindow(windowId: number): TPromise<void>;
getWindows(): TPromise<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]>;
getWindowCount(): TPromise<number>;
@@ -174,6 +169,7 @@ export interface IWindowsService {
startCrashReporter(config: CrashReporterStartOptions): TPromise<void>;
openAboutDialog(): TPromise<void>;
resolveProxy(windowId: number, url: string): Promise<string | undefined>;
}
export const IWindowService = createDecorator<IWindowService>('windowService');
@@ -221,6 +217,7 @@ export interface IWindowService {
showMessageBox(options: MessageBoxOptions): TPromise<IMessageBoxResult>;
showSaveDialog(options: SaveDialogOptions): TPromise<string>;
showOpenDialog(options: OpenDialogOptions): TPromise<string[]>;
resolveProxy(url: string): Promise<string | undefined>;
}
export type MenuBarVisibility = 'default' | 'visible' | 'toggle' | 'hidden';
@@ -241,13 +238,47 @@ export interface IWindowSettings {
menuBarVisibility: MenuBarVisibility;
newWindowDimensions: 'default' | 'inherit' | 'maximized' | 'fullscreen';
nativeTabs: boolean;
nativeFullScreen: boolean;
enableMenuBarMnemonics: boolean;
closeWhenEmpty: boolean;
smoothScrollingWorkaround: boolean;
clickThroughInactive: boolean;
}
export enum OpenContext {
export function getTitleBarStyle(configurationService: IConfigurationService, environment: IEnvironmentService, isExtensionDevelopment = environment.isExtensionDevelopment): 'native' | 'custom' {
const configuration = configurationService.getValue<IWindowSettings>('window');
const isDev = !environment.isBuilt || isExtensionDevelopment;
if (isMacintosh && isDev) {
return 'native'; // not enabled when developing due to https://github.com/electron/electron/issues/3647
}
if (configuration) {
const useNativeTabs = isMacintosh && configuration.nativeTabs === true;
if (useNativeTabs) {
return 'native'; // native tabs on sierra do not work with custom title style
}
const useSimpleFullScreen = isMacintosh && configuration.nativeFullScreen === false;
if (useSimpleFullScreen) {
return 'native'; // simple fullscreen does not work well with custom title style (https://github.com/Microsoft/vscode/issues/63291)
}
const smoothScrollingWorkaround = isWindows && configuration.smoothScrollingWorkaround === true;
if (smoothScrollingWorkaround) {
return 'native'; // smooth scrolling workaround does not work with custom title style
}
const style = configuration.titleBarStyle;
if (style === 'native') {
return 'native';
}
}
return 'custom'; // default to custom on all OS
}
export const enum OpenContext {
// opening when running from the command line
CLI,
@@ -268,7 +299,7 @@ export enum OpenContext {
API
}
export enum ReadyState {
export const enum ReadyState {
/**
* This window has not loaded any HTML yet
@@ -291,10 +322,25 @@ export enum ReadyState {
READY
}
export interface IPath {
export interface IPath extends IPathData {
// the file path to open within a Code instance
filePath?: string;
fileUri?: URI;
}
export interface IPathsToWaitFor extends IPathsToWaitForData {
paths: IPath[];
}
export interface IPathsToWaitForData {
paths: IPathData[];
waitMarkerFilePath: string;
}
export interface IPathData {
// the file path to open within a Code instance
fileUri?: UriComponents;
// the line number in the file path to open
lineNumber?: number;
@@ -303,16 +349,11 @@ export interface IPath {
columnNumber?: number;
}
export interface IPathsToWaitFor {
paths: IPath[];
waitMarkerFilePath: string;
}
export interface IOpenFileRequest {
filesToOpen?: IPath[];
filesToCreate?: IPath[];
filesToDiff?: IPath[];
filesToWait?: IPathsToWaitFor;
filesToOpen?: IPathData[];
filesToCreate?: IPathData[];
filesToDiff?: IPathData[];
filesToWait?: IPathsToWaitForData;
termProgram?: string;
}
@@ -320,11 +361,13 @@ export interface IAddFoldersRequest {
foldersToAdd: UriComponents[];
}
export interface IWindowConfiguration extends ParsedArgs, IOpenFileRequest {
export interface IWindowConfiguration extends ParsedArgs {
machineId: string;
windowId: number;
logLevel: LogLevel;
mainPid: number;
appRoot: string;
execPath: string;
isInitialStartup?: boolean;
@@ -337,24 +380,32 @@ export interface IWindowConfiguration extends ParsedArgs, IOpenFileRequest {
workspace?: IWorkspaceIdentifier;
folderUri?: ISingleFolderWorkspaceIdentifier;
remoteAuthority?: string;
zoomLevel?: number;
fullscreen?: boolean;
maximized?: boolean;
highContrast?: boolean;
baseTheme?: string;
backgroundColor?: string;
frameless?: boolean;
accessibilitySupport?: boolean;
partsSplashData?: string;
perfEntries: PerformanceEntry[];
perfStartTime?: number;
perfAppReady?: number;
perfWindowLoadTime?: number;
perfEntries: ExportData;
filesToOpen?: IPath[];
filesToCreate?: IPath[];
filesToDiff?: IPath[];
filesToWait?: IPathsToWaitFor;
termProgram?: string;
}
export interface IRunActionInWindowRequest {
id: string;
from: 'menu' | 'touchbar' | 'mouse';
args?: any[];
}
export class ActiveWindowManager implements IDisposable {
@@ -371,7 +422,7 @@ export class ActiveWindowManager implements IDisposable {
.then(id => (typeof this._activeWindowId === 'undefined') && this.setActiveWindow(id));
}
private setActiveWindow(windowId: number) {
private setActiveWindow(windowId: number | undefined) {
if (this.firstActiveWindowIdPromise) {
this.firstActiveWindowIdPromise = null;
}
@@ -390,4 +441,4 @@ export class ActiveWindowManager implements IDisposable {
dispose() {
this.disposables = dispose(this.disposables);
}
}
}

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Event, filterEvent, mapEvent, anyEvent } from 'vs/base/common/event';
import { TPromise } from 'vs/base/common/winjs.base';
import { IWindowService, IWindowsService, INativeOpenDialogOptions, IEnterWorkspaceResult, IMessageBoxResult, IWindowConfiguration, IDevToolsOptions } from 'vs/platform/windows/common/windows';
@@ -12,7 +10,7 @@ import { IRecentlyOpened } from 'vs/platform/history/common/history';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import { IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces';
import { ParsedArgs } from 'vs/platform/environment/common/environment';
import URI from 'vs/base/common/uri';
import { URI } from 'vs/base/common/uri';
export class WindowService implements IWindowService {
@@ -165,4 +163,8 @@ export class WindowService implements IWindowService {
updateTouchBar(items: ISerializableCommandAction[][]): TPromise<void> {
return this.windowsService.updateTouchBar(this.windowId, items);
}
resolveProxy(url: string): Promise<string | undefined> {
return this.windowsService.resolveProxy(this.windowId, url);
}
}

View File

@@ -3,17 +3,15 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { OpenContext, IWindowConfiguration, ReadyState, INativeOpenDialogOptions, IEnterWorkspaceResult, IMessageBoxResult } from 'vs/platform/windows/common/windows';
import { OpenContext, IWindowConfiguration, INativeOpenDialogOptions, IEnterWorkspaceResult, IMessageBoxResult, INewWindowOptions } from 'vs/platform/windows/common/windows';
import { ParsedArgs } from 'vs/platform/environment/common/environment';
import { Event } from 'vs/base/common/event';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IProcessEnvironment } from 'vs/base/common/platform';
import { IWorkspaceIdentifier, IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import URI from 'vs/base/common/uri';
import { URI } from 'vs/base/common/uri';
export interface IWindowState {
width?: number;
@@ -24,7 +22,7 @@ export interface IWindowState {
display?: number;
}
export enum WindowMode {
export const enum WindowMode {
Maximized,
Normal,
Minimized, // not used anymore, but also cannot remove due to existing stored UI state (needs migration)
@@ -40,13 +38,17 @@ export interface ICodeWindow {
openedWorkspace: IWorkspaceIdentifier;
backupPath: string;
remoteAuthority: string;
isExtensionDevelopmentHost: boolean;
isExtensionTestHost: boolean;
lastFocusTime: number;
readyState: ReadyState;
ready(): TPromise<ICodeWindow>;
isReady: boolean;
ready(): Thenable<ICodeWindow>;
addTabbedWindow(window: ICodeWindow): void;
load(config: IWindowConfiguration, isReload?: boolean, disableExtensions?: boolean): void;
reload(configuration?: IWindowConfiguration, cli?: ParsedArgs): void;
@@ -60,6 +62,8 @@ export interface ICodeWindow {
sendWhenReady(channel: string, ...args: any[]): void;
toggleFullScreen(): void;
isFullScreen(): boolean;
isMinimized(): boolean;
hasHiddenTitleBarStyle(): boolean;
setRepresentedFilename(name: string): void;
getRepresentedFilename(): string;
@@ -103,13 +107,14 @@ export interface IWindowsMainService {
pickFolderAndOpen(options: INativeOpenDialogOptions): void;
pickFileAndOpen(options: INativeOpenDialogOptions): void;
pickWorkspaceAndOpen(options: INativeOpenDialogOptions): void;
showMessageBox(options: Electron.MessageBoxOptions, win?: ICodeWindow): TPromise<IMessageBoxResult>;
showSaveDialog(options: Electron.SaveDialogOptions, win?: ICodeWindow): TPromise<string>;
showOpenDialog(options: Electron.OpenDialogOptions, win?: ICodeWindow): TPromise<string[]>;
showMessageBox(options: Electron.MessageBoxOptions, win?: ICodeWindow): Thenable<IMessageBoxResult>;
showSaveDialog(options: Electron.SaveDialogOptions, win?: ICodeWindow): Thenable<string>;
showOpenDialog(options: Electron.OpenDialogOptions, win?: ICodeWindow): Thenable<string[]>;
focusLastActive(cli: ParsedArgs, context: OpenContext): ICodeWindow;
getLastActiveWindow(): ICodeWindow;
waitForWindowCloseOrLoad(windowId: number): TPromise<void>;
openNewWindow(context: OpenContext): ICodeWindow[];
openNewWindow(context: OpenContext, options?: INewWindowOptions): ICodeWindow[];
openNewTabbedWindow(context: OpenContext): ICodeWindow[];
sendToFocused(channel: string, ...args: any[]): void;
sendToAll(channel: string, payload: any, windowIdsToIgnore?: number[]): void;
getFocusedWindow(): ICodeWindow;
@@ -127,6 +132,7 @@ export interface IOpenConfiguration {
urisToOpen?: URI[];
preferNewWindow?: boolean;
forceNewWindow?: boolean;
forceNewTabbedWindow?: boolean;
forceReuseWindow?: boolean;
forceEmpty?: boolean;
diffMode?: boolean;

View File

@@ -3,15 +3,14 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as nls from 'vs/nls';
import * as os from 'os';
import { TPromise } from 'vs/base/common/winjs.base';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { assign } from 'vs/base/common/objects';
import URI from 'vs/base/common/uri';
import { URI } from 'vs/base/common/uri';
import product from 'vs/platform/node/product';
import { IWindowsService, OpenContext, INativeOpenDialogOptions, IEnterWorkspaceResult, IMessageBoxResult, IDevToolsOptions } from 'vs/platform/windows/common/windows';
import { IWindowsService, OpenContext, INativeOpenDialogOptions, IEnterWorkspaceResult, IMessageBoxResult, IDevToolsOptions, INewWindowOptions } from 'vs/platform/windows/common/windows';
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
import { shell, crashReporter, app, Menu, clipboard } from 'electron';
import { Event, fromNodeEventEmitter, mapEvent, filterEvent, anyEvent, latch } from 'vs/base/common/event';
@@ -23,7 +22,7 @@ import { IWorkspaceIdentifier, IWorkspaceFolderCreationData, ISingleFolderWorksp
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import { Schemas } from 'vs/base/common/network';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { isWindows, isMacintosh } from 'vs/base/common/platform';
import { isMacintosh, isLinux } from 'vs/base/common/platform';
import { ILogService } from 'vs/platform/log/common/log';
export class WindowsService implements IWindowsService, IURLHandler, IDisposable {
@@ -35,15 +34,14 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
private _activeWindowId: number | undefined;
readonly onWindowOpen: Event<number> = filterEvent(fromNodeEventEmitter(app, 'browser-window-created', (_, w: Electron.BrowserWindow) => w.id), id => !!this.windowsMainService.getWindowById(id));
readonly onWindowBlur: Event<number> = filterEvent(fromNodeEventEmitter(app, 'browser-window-blur', (_, w: Electron.BrowserWindow) => w.id), id => !!this.windowsMainService.getWindowById(id));
readonly onWindowMaximize: Event<number> = filterEvent(fromNodeEventEmitter(app, 'browser-window-maximize', (_, w: Electron.BrowserWindow) => w.id), id => !!this.windowsMainService.getWindowById(id));
readonly onWindowUnmaximize: Event<number> = filterEvent(fromNodeEventEmitter(app, 'browser-window-unmaximize', (_, w: Electron.BrowserWindow) => w.id), id => !!this.windowsMainService.getWindowById(id));
readonly onWindowFocus: Event<number> = anyEvent(
mapEvent(filterEvent(mapEvent(this.windowsMainService.onWindowsCountChanged, () => this.windowsMainService.getLastActiveWindow()), w => !!w), w => w.id),
filterEvent(fromNodeEventEmitter(app, 'browser-window-focus', (_, w: Electron.BrowserWindow) => w.id), id => !!this.windowsMainService.getWindowById(id))
);
readonly onWindowBlur: Event<number> = filterEvent(fromNodeEventEmitter(app, 'browser-window-blur', (_, w: Electron.BrowserWindow) => w.id), id => !!this.windowsMainService.getWindowById(id));
readonly onWindowMaximize: Event<number> = filterEvent(fromNodeEventEmitter(app, 'browser-window-maximize', (_, w: Electron.BrowserWindow) => w.id), id => !!this.windowsMainService.getWindowById(id));
readonly onWindowUnmaximize: Event<number> = filterEvent(fromNodeEventEmitter(app, 'browser-window-unmaximize', (_, w: Electron.BrowserWindow) => w.id), id => !!this.windowsMainService.getWindowById(id));
readonly onRecentlyOpenedChange: Event<void> = this.historyService.onRecentlyOpenedChange;
constructor(
@@ -90,21 +88,21 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
return TPromise.as(null);
}
showMessageBox(windowId: number, options: Electron.MessageBoxOptions): TPromise<IMessageBoxResult> {
showMessageBox(windowId: number, options: Electron.MessageBoxOptions): Thenable<IMessageBoxResult> {
this.logService.trace('windowsService#showMessageBox', windowId);
const codeWindow = this.windowsMainService.getWindowById(windowId);
return this.windowsMainService.showMessageBox(options, codeWindow);
}
showSaveDialog(windowId: number, options: Electron.SaveDialogOptions): TPromise<string> {
showSaveDialog(windowId: number, options: Electron.SaveDialogOptions): Thenable<string> {
this.logService.trace('windowsService#showSaveDialog', windowId);
const codeWindow = this.windowsMainService.getWindowById(windowId);
return this.windowsMainService.showSaveDialog(options, codeWindow);
}
showOpenDialog(windowId: number, options: Electron.OpenDialogOptions): TPromise<string[]> {
showOpenDialog(windowId: number, options: Electron.OpenDialogOptions): Thenable<string[]> {
this.logService.trace('windowsService#showOpenDialog', windowId);
const codeWindow = this.windowsMainService.getWindowById(windowId);
@@ -139,7 +137,7 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
if (codeWindow) {
const contents = codeWindow.win.webContents;
if (isMacintosh && codeWindow.hasHiddenTitleBarStyle() && !codeWindow.win.isFullScreen() && !contents.isDevToolsOpened()) {
if (isMacintosh && codeWindow.hasHiddenTitleBarStyle() && !codeWindow.isFullScreen() && !contents.isDevToolsOpened()) {
contents.openDevTools({ mode: 'undocked' }); // due to https://github.com/electron/electron/issues/3647
} else {
contents.toggleDevTools();
@@ -226,14 +224,14 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
return TPromise.as(null);
}
addRecentlyOpened(files: string[]): TPromise<void> {
addRecentlyOpened(files: URI[]): TPromise<void> {
this.logService.trace('windowsService#addRecentlyOpened');
this.historyService.addRecentlyOpened(void 0, files);
return TPromise.as(null);
}
removeFromRecentlyOpened(paths: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | string)[]): TPromise<void> {
removeFromRecentlyOpened(paths: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI | string)[]): TPromise<void> {
this.logService.trace('windowsService#removeFromRecentlyOpened');
this.historyService.removeFromRecentlyOpened(paths);
@@ -258,6 +256,14 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
return TPromise.as(this.historyService.getRecentlyOpened());
}
newWindowTab(): TPromise<void> {
this.logService.trace('windowsService#newWindowTab');
this.windowsMainService.openNewTabbedWindow(OpenContext.API);
return TPromise.as(void 0);
}
showPreviousWindowTab(): TPromise<void> {
this.logService.trace('windowsService#showPreviousWindowTab');
Menu.sendActionToFirstResponder('selectPreviousTab:');
@@ -411,9 +417,11 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
return TPromise.as(null);
}
openNewWindow(): TPromise<void> {
this.logService.trace('windowsService#openNewWindow');
this.windowsMainService.openNewWindow(OpenContext.API);
openNewWindow(options?: INewWindowOptions): TPromise<void> {
this.logService.trace('windowsService#openNewWindow ' + JSON.stringify(options));
this.windowsMainService.openNewWindow(OpenContext.API, options);
return TPromise.as(null);
}
@@ -495,23 +503,33 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
this.logService.trace('windowsService#openAboutDialog');
const lastActiveWindow = this.windowsMainService.getFocusedWindow() || this.windowsMainService.getLastActiveWindow();
let version = app.getVersion();
if (product.target) {
version = `${version} (${product.target} setup)`;
}
// {{SQL CARBON EDIT}}
const detail = nls.localize('aboutDetail',
"Version {0}\nCommit {1}\nDate {2}\nVS Code {8}\nShell {3}\nRenderer {4}\nNode {5}\nV8: {6}\nArchitecture {7}",
app.getVersion(),
"Version: {0}\nCommit: {1}\nDate: {2}\nVS Code {8}\nElectron: {3}\nChrome: {4}\nNode.js: {5}\nV8: {6}\nOS: {7}",
version,
product.commit || 'Unknown',
product.date || 'Unknown',
process.versions['electron'],
process.versions['chrome'],
process.versions['node'],
process.versions['v8'],
process.arch,
`${os.type()} ${os.arch()} ${os.release()}`,
product.vscodeVersion
);
const buttons = [nls.localize('okButton', "OK")];
if (isWindows) {
buttons.push(mnemonicButtonLabel(nls.localize({ key: 'copy', comment: ['&& denotes a mnemonic'] }, "&&Copy"))); // https://github.com/Microsoft/vscode/issues/37608
const ok = nls.localize('okButton', "OK");
const copy = mnemonicButtonLabel(nls.localize({ key: 'copy', comment: ['&& denotes a mnemonic'] }, "&&Copy"));
let buttons: string[];
if (isLinux) {
buttons = [copy, ok];
} else {
buttons = [ok, copy];
}
this.windowsMainService.showMessageBox({
@@ -520,9 +538,10 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
message: product.nameLong,
detail: `\n${detail}`,
buttons,
noLink: true
noLink: true,
defaultId: buttons.indexOf(ok)
}, lastActiveWindow).then(result => {
if (isWindows && result.button === 1) {
if (buttons[result.button] === copy) {
clipboard.writeText(detail);
}
});
@@ -548,6 +567,19 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
return TPromise.wrap(true);
}
resolveProxy(windowId: number, url: string): Promise<string | undefined> {
return new Promise(resolve => {
const codeWindow = this.windowsMainService.getWindowById(windowId);
if (codeWindow) {
codeWindow.win.webContents.session.resolveProxy(url, proxy => {
resolve(proxy);
});
} else {
resolve();
}
});
}
dispose(): void {
this.disposables = dispose(this.disposables);
}

View File

@@ -3,80 +3,17 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { Event, buffer } from 'vs/base/common/event';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IWindowsService, INativeOpenDialogOptions, IEnterWorkspaceResult, CrashReporterStartOptions, IMessageBoxResult, MessageBoxOptions, SaveDialogOptions, OpenDialogOptions, IDevToolsOptions } from 'vs/platform/windows/common/windows';
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/node/ipc';
import { IWindowsService, INativeOpenDialogOptions, IEnterWorkspaceResult, CrashReporterStartOptions, IMessageBoxResult, MessageBoxOptions, SaveDialogOptions, OpenDialogOptions, IDevToolsOptions, INewWindowOptions } from 'vs/platform/windows/common/windows';
import { IWorkspaceIdentifier, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IRecentlyOpened } from 'vs/platform/history/common/history';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import URI from 'vs/base/common/uri';
import { URI } from 'vs/base/common/uri';
import { ParsedArgs } from 'vs/platform/environment/common/environment';
export interface IWindowsChannel extends IChannel {
listen(event: 'onWindowOpen'): Event<number>;
listen(event: 'onWindowFocus'): Event<number>;
listen(event: 'onWindowBlur'): Event<number>;
listen(event: 'onWindowMaximize'): Event<number>;
listen(event: 'onWindowUnmaximize'): Event<number>;
listen(event: 'onRecentlyOpenedChange'): Event<void>;
listen<T>(event: string, arg?: any): Event<T>;
call(command: 'pickFileFolderAndOpen', arg: INativeOpenDialogOptions): TPromise<void>;
call(command: 'pickFileAndOpen', arg: INativeOpenDialogOptions): TPromise<void>;
call(command: 'pickFolderAndOpen', arg: INativeOpenDialogOptions): TPromise<void>;
call(command: 'pickWorkspaceAndOpen', arg: INativeOpenDialogOptions): TPromise<void>;
call(command: 'showMessageBox', arg: [number, MessageBoxOptions]): TPromise<IMessageBoxResult>;
call(command: 'showSaveDialog', arg: [number, SaveDialogOptions]): TPromise<string>;
call(command: 'showOpenDialog', arg: [number, OpenDialogOptions]): TPromise<string[]>;
call(command: 'reloadWindow', arg: [number, ParsedArgs]): TPromise<void>;
call(command: 'openDevTools', arg: [number, IDevToolsOptions]): TPromise<void>;
call(command: 'toggleDevTools', arg: number): TPromise<void>;
call(command: 'closeWorkspace', arg: number): TPromise<void>;
call(command: 'enterWorkspace', arg: [number, string]): TPromise<IEnterWorkspaceResult>;
call(command: 'createAndEnterWorkspace', arg: [number, IWorkspaceFolderCreationData[], string]): TPromise<IEnterWorkspaceResult>;
call(command: 'saveAndEnterWorkspace', arg: [number, string]): TPromise<IEnterWorkspaceResult>;
call(command: 'toggleFullScreen', arg: number): TPromise<void>;
call(command: 'setRepresentedFilename', arg: [number, string]): TPromise<void>;
call(command: 'addRecentlyOpened', arg: string[]): TPromise<void>;
call(command: 'removeFromRecentlyOpened', arg: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | string)[]): TPromise<void>;
call(command: 'clearRecentlyOpened'): TPromise<void>;
call(command: 'getRecentlyOpened', arg: number): TPromise<IRecentlyOpened>;
call(command: 'showPreviousWindowTab'): TPromise<void>;
call(command: 'showNextWindowTab'): TPromise<void>;
call(command: 'moveWindowTabToNewWindow'): TPromise<void>;
call(command: 'mergeAllWindowTabs'): TPromise<void>;
call(command: 'toggleWindowTabsBar'): TPromise<void>;
call(command: 'updateTouchBar', arg: [number, ISerializableCommandAction[][]]): TPromise<void>;
call(command: 'focusWindow', arg: number): TPromise<void>;
call(command: 'closeWindow', arg: number): TPromise<void>;
call(command: 'isFocused', arg: number): TPromise<boolean>;
call(command: 'isMaximized', arg: number): TPromise<boolean>;
call(command: 'maximizeWindow', arg: number): TPromise<void>;
call(command: 'unmaximizeWindow', arg: number): TPromise<void>;
call(command: 'minimizeWindow', arg: number): TPromise<void>;
call(command: 'onWindowTitleDoubleClick', arg: number): TPromise<void>;
call(command: 'setDocumentEdited', arg: [number, boolean]): TPromise<void>;
call(command: 'quit'): TPromise<void>;
call(command: 'openWindow', arg: [number, URI[], { forceNewWindow?: boolean, forceReuseWindow?: boolean, forceOpenWorkspaceAsFile?: boolean, args?: ParsedArgs }]): TPromise<void>;
call(command: 'openNewWindow'): TPromise<void>;
call(command: 'showWindow', arg: number): TPromise<void>;
call(command: 'getWindows'): TPromise<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]>;
call(command: 'getWindowCount'): TPromise<number>;
call(command: 'relaunch', arg: [{ addArgs?: string[], removeArgs?: string[] }]): TPromise<void>;
call(command: 'whenSharedProcessReady'): TPromise<void>;
call(command: 'toggleSharedProcess'): TPromise<void>;
call(command: 'log', arg: [string, string[]]): TPromise<void>;
call(command: 'showItemInFolder', arg: string): TPromise<void>;
call(command: 'getActiveWindowId'): TPromise<number>;
call(command: 'openExternal', arg: string): TPromise<boolean>;
call(command: 'startCrashReporter', arg: CrashReporterStartOptions): TPromise<void>;
call(command: 'openAboutDialog'): TPromise<void>;
}
export class WindowsChannel implements IWindowsChannel {
export class WindowsChannel implements IServerChannel {
private onWindowOpen: Event<number>;
private onWindowFocus: Event<number>;
@@ -94,7 +31,7 @@ export class WindowsChannel implements IWindowsChannel {
this.onRecentlyOpenedChange = buffer(service.onRecentlyOpenedChange, true);
}
listen<T>(event: string, arg?: any): Event<any> {
listen(_, event: string): Event<any> {
switch (event) {
case 'onWindowOpen': return this.onWindowOpen;
case 'onWindowFocus': return this.onWindowFocus;
@@ -104,10 +41,10 @@ export class WindowsChannel implements IWindowsChannel {
case 'onRecentlyOpenedChange': return this.onRecentlyOpenedChange;
}
throw new Error('No event found');
throw new Error(`Event not found: ${event}`);
}
call(command: string, arg?: any): TPromise<any> {
call(_, command: string, arg?: any): Thenable<any> {
switch (command) {
case 'pickFileFolderAndOpen': return this.service.pickFileFolderAndOpen(arg);
case 'pickFileAndOpen': return this.service.pickFileAndOpen(arg);
@@ -123,7 +60,7 @@ export class WindowsChannel implements IWindowsChannel {
case 'enterWorkspace': return this.service.enterWorkspace(arg[0], arg[1]);
case 'createAndEnterWorkspace': {
const rawFolders: IWorkspaceFolderCreationData[] = arg[1];
let folders: IWorkspaceFolderCreationData[];
let folders: IWorkspaceFolderCreationData[] | undefined = undefined;
if (Array.isArray(rawFolders)) {
folders = rawFolders.map(rawFolder => {
return {
@@ -138,15 +75,16 @@ export class WindowsChannel implements IWindowsChannel {
case 'saveAndEnterWorkspace': return this.service.saveAndEnterWorkspace(arg[0], arg[1]);
case 'toggleFullScreen': return this.service.toggleFullScreen(arg);
case 'setRepresentedFilename': return this.service.setRepresentedFilename(arg[0], arg[1]);
case 'addRecentlyOpened': return this.service.addRecentlyOpened(arg);
case 'addRecentlyOpened': return this.service.addRecentlyOpened(arg.map(URI.revive));
case 'removeFromRecentlyOpened': {
let paths: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | string)[] = arg;
let paths: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI | string)[] = arg;
if (Array.isArray(paths)) {
paths = paths.map(path => isWorkspaceIdentifier(path) || typeof path === 'string' ? path : URI.revive(path));
}
return this.service.removeFromRecentlyOpened(paths);
}
case 'clearRecentlyOpened': return this.service.clearRecentlyOpened();
case 'newWindowTab': return this.service.newWindowTab();
case 'showPreviousWindowTab': return this.service.showPreviousWindowTab();
case 'showNextWindowTab': return this.service.showNextWindowTab();
case 'moveWindowTabToNewWindow': return this.service.moveWindowTabToNewWindow();
@@ -164,7 +102,7 @@ export class WindowsChannel implements IWindowsChannel {
case 'onWindowTitleDoubleClick': return this.service.onWindowTitleDoubleClick(arg);
case 'setDocumentEdited': return this.service.setDocumentEdited(arg[0], arg[1]);
case 'openWindow': return this.service.openWindow(arg[0], arg[1] ? (<URI[]>arg[1]).map(r => URI.revive(r)) : arg[1], arg[2]);
case 'openNewWindow': return this.service.openNewWindow();
case 'openNewWindow': return this.service.openNewWindow(arg);
case 'showWindow': return this.service.showWindow(arg);
case 'getWindows': return this.service.getWindows();
case 'getWindowCount': return this.service.getWindowCount();
@@ -178,8 +116,10 @@ export class WindowsChannel implements IWindowsChannel {
case 'openExternal': return this.service.openExternal(arg);
case 'startCrashReporter': return this.service.startCrashReporter(arg);
case 'openAboutDialog': return this.service.openAboutDialog();
case 'resolveProxy': return this.service.resolveProxy(arg[0], arg[1]);
}
return undefined;
throw new Error(`Call not found: ${command}`);
}
}
@@ -187,7 +127,7 @@ export class WindowsChannelClient implements IWindowsService {
_serviceBrand: any;
constructor(private channel: IWindowsChannel) { }
constructor(private channel: IChannel) { }
get onWindowOpen(): Event<number> { return this.channel.listen('onWindowOpen'); }
get onWindowFocus(): Event<number> { return this.channel.listen('onWindowFocus'); }
@@ -197,206 +137,215 @@ export class WindowsChannelClient implements IWindowsService {
get onRecentlyOpenedChange(): Event<void> { return this.channel.listen('onRecentlyOpenedChange'); }
pickFileFolderAndOpen(options: INativeOpenDialogOptions): TPromise<void> {
return this.channel.call('pickFileFolderAndOpen', options);
return TPromise.wrap(this.channel.call('pickFileFolderAndOpen', options));
}
pickFileAndOpen(options: INativeOpenDialogOptions): TPromise<void> {
return this.channel.call('pickFileAndOpen', options);
return TPromise.wrap(this.channel.call('pickFileAndOpen', options));
}
pickFolderAndOpen(options: INativeOpenDialogOptions): TPromise<void> {
return this.channel.call('pickFolderAndOpen', options);
return TPromise.wrap(this.channel.call('pickFolderAndOpen', options));
}
pickWorkspaceAndOpen(options: INativeOpenDialogOptions): TPromise<void> {
return this.channel.call('pickWorkspaceAndOpen', options);
return TPromise.wrap(this.channel.call('pickWorkspaceAndOpen', options));
}
showMessageBox(windowId: number, options: MessageBoxOptions): TPromise<IMessageBoxResult> {
return this.channel.call('showMessageBox', [windowId, options]);
return TPromise.wrap(this.channel.call('showMessageBox', [windowId, options]));
}
showSaveDialog(windowId: number, options: SaveDialogOptions): TPromise<string> {
return this.channel.call('showSaveDialog', [windowId, options]);
return TPromise.wrap(this.channel.call('showSaveDialog', [windowId, options]));
}
showOpenDialog(windowId: number, options: OpenDialogOptions): TPromise<string[]> {
return this.channel.call('showOpenDialog', [windowId, options]);
return TPromise.wrap(this.channel.call('showOpenDialog', [windowId, options]));
}
reloadWindow(windowId: number, args?: ParsedArgs): TPromise<void> {
return this.channel.call('reloadWindow', [windowId, args]);
return TPromise.wrap(this.channel.call('reloadWindow', [windowId, args]));
}
openDevTools(windowId: number, options?: IDevToolsOptions): TPromise<void> {
return this.channel.call('openDevTools', [windowId, options]);
return TPromise.wrap(this.channel.call('openDevTools', [windowId, options]));
}
toggleDevTools(windowId: number): TPromise<void> {
return this.channel.call('toggleDevTools', windowId);
return TPromise.wrap(this.channel.call('toggleDevTools', windowId));
}
closeWorkspace(windowId: number): TPromise<void> {
return this.channel.call('closeWorkspace', windowId);
return TPromise.wrap(this.channel.call('closeWorkspace', windowId));
}
enterWorkspace(windowId: number, path: string): TPromise<IEnterWorkspaceResult> {
return this.channel.call('enterWorkspace', [windowId, path]);
return TPromise.wrap(this.channel.call('enterWorkspace', [windowId, path]));
}
createAndEnterWorkspace(windowId: number, folders?: IWorkspaceFolderCreationData[], path?: string): TPromise<IEnterWorkspaceResult> {
return this.channel.call('createAndEnterWorkspace', [windowId, folders, path]);
return TPromise.wrap(this.channel.call('createAndEnterWorkspace', [windowId, folders, path]));
}
saveAndEnterWorkspace(windowId: number, path: string): TPromise<IEnterWorkspaceResult> {
return this.channel.call('saveAndEnterWorkspace', [windowId, path]);
return TPromise.wrap(this.channel.call('saveAndEnterWorkspace', [windowId, path]));
}
toggleFullScreen(windowId: number): TPromise<void> {
return this.channel.call('toggleFullScreen', windowId);
return TPromise.wrap(this.channel.call('toggleFullScreen', windowId));
}
setRepresentedFilename(windowId: number, fileName: string): TPromise<void> {
return this.channel.call('setRepresentedFilename', [windowId, fileName]);
return TPromise.wrap(this.channel.call('setRepresentedFilename', [windowId, fileName]));
}
addRecentlyOpened(files: string[]): TPromise<void> {
return this.channel.call('addRecentlyOpened', files);
addRecentlyOpened(files: URI[]): TPromise<void> {
return TPromise.wrap(this.channel.call('addRecentlyOpened', files));
}
removeFromRecentlyOpened(paths: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | string)[]): TPromise<void> {
return this.channel.call('removeFromRecentlyOpened', paths);
removeFromRecentlyOpened(paths: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI)[]): TPromise<void> {
return TPromise.wrap(this.channel.call('removeFromRecentlyOpened', paths));
}
clearRecentlyOpened(): TPromise<void> {
return this.channel.call('clearRecentlyOpened');
return TPromise.wrap(this.channel.call('clearRecentlyOpened'));
}
getRecentlyOpened(windowId: number): TPromise<IRecentlyOpened> {
return this.channel.call('getRecentlyOpened', windowId)
return TPromise.wrap<IRecentlyOpened>(this.channel.call('getRecentlyOpened', windowId))
.then(recentlyOpened => {
recentlyOpened.workspaces = recentlyOpened.workspaces.map(workspace => isWorkspaceIdentifier(workspace) ? workspace : URI.revive(workspace));
recentlyOpened.files = recentlyOpened.files.map(URI.revive);
return recentlyOpened;
});
}
newWindowTab(): TPromise<void> {
return TPromise.wrap(this.channel.call('newWindowTab'));
}
showPreviousWindowTab(): TPromise<void> {
return this.channel.call('showPreviousWindowTab');
return TPromise.wrap(this.channel.call('showPreviousWindowTab'));
}
showNextWindowTab(): TPromise<void> {
return this.channel.call('showNextWindowTab');
return TPromise.wrap(this.channel.call('showNextWindowTab'));
}
moveWindowTabToNewWindow(): TPromise<void> {
return this.channel.call('moveWindowTabToNewWindow');
return TPromise.wrap(this.channel.call('moveWindowTabToNewWindow'));
}
mergeAllWindowTabs(): TPromise<void> {
return this.channel.call('mergeAllWindowTabs');
return TPromise.wrap(this.channel.call('mergeAllWindowTabs'));
}
toggleWindowTabsBar(): TPromise<void> {
return this.channel.call('toggleWindowTabsBar');
return TPromise.wrap(this.channel.call('toggleWindowTabsBar'));
}
focusWindow(windowId: number): TPromise<void> {
return this.channel.call('focusWindow', windowId);
return TPromise.wrap(this.channel.call('focusWindow', windowId));
}
closeWindow(windowId: number): TPromise<void> {
return this.channel.call('closeWindow', windowId);
return TPromise.wrap(this.channel.call('closeWindow', windowId));
}
isFocused(windowId: number): TPromise<boolean> {
return this.channel.call('isFocused', windowId);
return TPromise.wrap(this.channel.call('isFocused', windowId));
}
isMaximized(windowId: number): TPromise<boolean> {
return this.channel.call('isMaximized', windowId);
return TPromise.wrap(this.channel.call('isMaximized', windowId));
}
maximizeWindow(windowId: number): TPromise<void> {
return this.channel.call('maximizeWindow', windowId);
return TPromise.wrap(this.channel.call('maximizeWindow', windowId));
}
unmaximizeWindow(windowId: number): TPromise<void> {
return this.channel.call('unmaximizeWindow', windowId);
return TPromise.wrap(this.channel.call('unmaximizeWindow', windowId));
}
minimizeWindow(windowId: number): TPromise<void> {
return this.channel.call('minimizeWindow', windowId);
return TPromise.wrap(this.channel.call('minimizeWindow', windowId));
}
onWindowTitleDoubleClick(windowId: number): TPromise<void> {
return this.channel.call('onWindowTitleDoubleClick', windowId);
return TPromise.wrap(this.channel.call('onWindowTitleDoubleClick', windowId));
}
setDocumentEdited(windowId: number, flag: boolean): TPromise<void> {
return this.channel.call('setDocumentEdited', [windowId, flag]);
return TPromise.wrap(this.channel.call('setDocumentEdited', [windowId, flag]));
}
quit(): TPromise<void> {
return this.channel.call('quit');
return TPromise.wrap(this.channel.call('quit'));
}
relaunch(options: { addArgs?: string[], removeArgs?: string[] }): TPromise<void> {
return this.channel.call('relaunch', [options]);
return TPromise.wrap(this.channel.call('relaunch', [options]));
}
whenSharedProcessReady(): TPromise<void> {
return this.channel.call('whenSharedProcessReady');
return TPromise.wrap(this.channel.call('whenSharedProcessReady'));
}
toggleSharedProcess(): TPromise<void> {
return this.channel.call('toggleSharedProcess');
return TPromise.wrap(this.channel.call('toggleSharedProcess'));
}
openWindow(windowId: number, paths: URI[], options?: { forceNewWindow?: boolean, forceReuseWindow?: boolean, forceOpenWorkspaceAsFile?: boolean, args?: ParsedArgs }): TPromise<void> {
return this.channel.call('openWindow', [windowId, paths, options]);
return TPromise.wrap(this.channel.call('openWindow', [windowId, paths, options]));
}
openNewWindow(): TPromise<void> {
return this.channel.call('openNewWindow');
openNewWindow(options?: INewWindowOptions): TPromise<void> {
return this.channel.call('openNewWindow', options);
}
showWindow(windowId: number): TPromise<void> {
return this.channel.call('showWindow', windowId);
return TPromise.wrap(this.channel.call('showWindow', windowId));
}
getWindows(): TPromise<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]> {
return this.channel.call('getWindows').then(result => { result.forEach(win => win.folderUri = win.folderUri ? URI.revive(win.folderUri) : win.folderUri); return result; });
return TPromise.wrap(this.channel.call<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]>('getWindows').then(result => { result.forEach(win => win.folderUri = win.folderUri ? URI.revive(win.folderUri) : win.folderUri); return result; }));
}
getWindowCount(): TPromise<number> {
return this.channel.call('getWindowCount');
return TPromise.wrap(this.channel.call('getWindowCount'));
}
log(severity: string, ...messages: string[]): TPromise<void> {
return this.channel.call('log', [severity, messages]);
return TPromise.wrap(this.channel.call('log', [severity, messages]));
}
showItemInFolder(path: string): TPromise<void> {
return this.channel.call('showItemInFolder', path);
return TPromise.wrap(this.channel.call('showItemInFolder', path));
}
getActiveWindowId(): TPromise<number | undefined> {
return this.channel.call('getActiveWindowId');
return TPromise.wrap(this.channel.call('getActiveWindowId'));
}
openExternal(url: string): TPromise<boolean> {
return this.channel.call('openExternal', url);
return TPromise.wrap(this.channel.call('openExternal', url));
}
startCrashReporter(config: CrashReporterStartOptions): TPromise<void> {
return this.channel.call('startCrashReporter', config);
return TPromise.wrap(this.channel.call('startCrashReporter', config));
}
updateTouchBar(windowId: number, items: ISerializableCommandAction[][]): TPromise<void> {
return this.channel.call('updateTouchBar', [windowId, items]);
return TPromise.wrap(this.channel.call('updateTouchBar', [windowId, items]));
}
openAboutDialog(): TPromise<void> {
return this.channel.call('openAboutDialog');
return TPromise.wrap(this.channel.call('openAboutDialog'));
}
resolveProxy(windowId: number, url: string): Promise<string | undefined> {
return Promise.resolve(this.channel.call('resolveProxy', [windowId, url]));
}
}