Merge VS Code 1.21 source code (#1067)

* Initial VS Code 1.21 file copy with patches

* A few more merges

* Post npm install

* Fix batch of build breaks

* Fix more build breaks

* Fix more build errors

* Fix more build breaks

* Runtime fixes 1

* Get connection dialog working with some todos

* Fix a few packaging issues

* Copy several node_modules to package build to fix loader issues

* Fix breaks from master

* A few more fixes

* Make tests pass

* First pass of license header updates

* Second pass of license header updates

* Fix restore dialog issues

* Remove add additional themes menu items

* fix select box issues where the list doesn't show up

* formatting

* Fix editor dispose issue

* Copy over node modules to correct location on all platforms
This commit is contained in:
Karl Burtram
2018-04-04 15:27:51 -07:00
committed by GitHub
parent 5fba3e31b4
commit dafb780987
9412 changed files with 141255 additions and 98813 deletions

View File

@@ -8,24 +8,20 @@
import 'vs/css!./media/actions';
import URI from 'vs/base/common/uri';
import * as collections from 'vs/base/common/collections';
import { TPromise } from 'vs/base/common/winjs.base';
import { Action } from 'vs/base/common/actions';
import { IWindowService, IWindowsService, MenuBarVisibility } from 'vs/platform/windows/common/windows';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import nls = require('vs/nls');
import product from 'vs/platform/node/product';
import pkg from 'vs/platform/node/package';
import errors = require('vs/base/common/errors');
import { IMessageService, Severity } from 'vs/platform/message/common/message';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { IExtensionManagementService, LocalExtensionType, ILocalExtension, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
import paths = require('vs/base/common/paths');
import { isMacintosh, isLinux, language } from 'vs/base/common/platform';
import { IQuickOpenService, IFilePickOpenEntry, ISeparator, IPickOpenAction, IPickOpenItem, IPickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen';
import { isMacintosh, isLinux } from 'vs/base/common/platform';
import { IQuickOpenService, IFilePickOpenEntry, ISeparator, IPickOpenAction, IPickOpenItem } from 'vs/platform/quickOpen/common/quickOpen';
import * as browser from 'vs/base/browser/browser';
import { IIntegrityService } from 'vs/platform/integrity/common/integrity';
import { IEntryRunContext } from 'vs/base/parts/quickopen/common/quickOpen';
@@ -41,38 +37,22 @@ import { getPathLabel, getBaseLabel } from 'vs/base/common/labels';
import { IViewlet } from 'vs/workbench/common/viewlet';
import { IPanel } from 'vs/workbench/common/panel';
import { IWorkspaceIdentifier, getWorkspaceLabel, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { FileKind, IFileService } from 'vs/platform/files/common/files';
import { FileKind } from 'vs/platform/files/common/files';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IExtensionService, ActivationTimes } from 'vs/platform/extensions/common/extensions';
import { IExtensionService, ActivationTimes } from 'vs/workbench/services/extensions/common/extensions';
import { getEntries } from 'vs/base/common/performance';
import { IEditor } from 'vs/platform/editor/common/editor';
import { ILogService, LogLevel } from 'vs/platform/log/common/log';
import { IssueType } from 'vs/platform/issue/common/issue';
import { domEvent } from 'vs/base/browser/event';
import { once } from 'vs/base/common/event';
import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
import { getDomNodePagePosition, createStyleSheet, createCSSRule } from 'vs/base/browser/dom';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { Context } from 'vs/platform/contextkey/browser/contextKeyService';
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
import { INotificationService } from 'vs/platform/notification/common/notification';
// --- actions
export class CloseEditorAction extends Action {
public static readonly ID = 'workbench.action.closeActiveEditor';
public static readonly LABEL = nls.localize('closeActiveEditor', "Close Editor");
constructor(
id: string,
label: string,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService
) {
super(id, label);
}
public run(): TPromise<void> {
const activeEditor = this.editorService.getActiveEditor();
if (activeEditor) {
return this.editorService.closeEditor(activeEditor.position, activeEditor.input);
}
return TPromise.as(null);
}
}
export class CloseCurrentWindowAction extends Action {
public static readonly ID = 'workbench.action.closeWindow';
@@ -91,14 +71,14 @@ export class CloseCurrentWindowAction extends Action {
export class CloseWorkspaceAction extends Action {
static ID = 'workbench.action.closeFolder';
static readonly ID = 'workbench.action.closeFolder';
static LABEL = nls.localize('closeWorkspace', "Close Workspace");
constructor(
id: string,
label: string,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IMessageService private messageService: IMessageService,
@INotificationService private notificationService: INotificationService,
@IWindowService private windowService: IWindowService
) {
super(id, label);
@@ -106,7 +86,7 @@ export class CloseWorkspaceAction extends Action {
run(): TPromise<void> {
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
this.messageService.show(Severity.Info, nls.localize('noWorkspaceOpened', "There is currently no workspace opened in this instance to close."));
this.notificationService.info(nls.localize('noWorkspaceOpened', "There is currently no workspace opened in this instance to close."));
return TPromise.as(null);
}
@@ -117,7 +97,7 @@ export class CloseWorkspaceAction extends Action {
export class NewWindowAction extends Action {
static ID = 'workbench.action.newWindow';
static readonly ID = 'workbench.action.newWindow';
static LABEL = nls.localize('newWindow', "New Window");
constructor(
@@ -135,7 +115,7 @@ export class NewWindowAction extends Action {
export class ToggleFullScreenAction extends Action {
static ID = 'workbench.action.toggleFullScreen';
static readonly ID = 'workbench.action.toggleFullScreen';
static LABEL = nls.localize('toggleFullScreen', "Toggle Full Screen");
constructor(id: string, label: string, @IWindowService private windowService: IWindowService) {
@@ -149,7 +129,7 @@ export class ToggleFullScreenAction extends Action {
export class ToggleMenuBarAction extends Action {
static ID = 'workbench.action.toggleMenuBar';
static readonly ID = 'workbench.action.toggleMenuBar';
static LABEL = nls.localize('toggleMenuBar', "Toggle Menu Bar");
private static readonly menuBarVisibilityKey = 'window.menuBarVisibility';
@@ -183,7 +163,7 @@ export class ToggleMenuBarAction extends Action {
export class ToggleDevToolsAction extends Action {
static ID = 'workbench.action.toggleDevTools';
static readonly ID = 'workbench.action.toggleDevTools';
static LABEL = nls.localize('toggleDevTools', "Toggle Developer Tools");
constructor(id: string, label: string, @IWindowService private windowsService: IWindowService) {
@@ -391,6 +371,7 @@ export class ShowStartupPerformance extends Action {
if (metrics.initialStartup) {
table.push({ Topic: '[main] start => app.isReady', 'Took (ms)': metrics.timers.ellapsedAppReady });
table.push({ Topic: '[main] nls:start => nls:end', 'Took (ms)': metrics.timers.ellapsedNlsGeneration });
table.push({ Topic: '[main] app.isReady => window.loadUrl()', 'Took (ms)': metrics.timers.ellapsedWindowLoad });
}
@@ -558,7 +539,7 @@ export class ShowStartupPerformance extends Action {
export class ReloadWindowAction extends Action {
static ID = 'workbench.action.reloadWindow';
static readonly ID = 'workbench.action.reloadWindow';
static LABEL = nls.localize('reloadWindow', "Reload Window");
constructor(
@@ -574,6 +555,24 @@ export class ReloadWindowAction extends Action {
}
}
export class ReloadWindowWithExtensionsDisabledAction extends Action {
static readonly ID = 'workbench.action.reloadWindowWithExtensionsDisabled';
static LABEL = nls.localize('reloadWindowWithExntesionsDisabled', "Reload Window With Extensions Disabled");
constructor(
id: string,
label: string,
@IWindowService private windowService: IWindowService
) {
super(id, label);
}
run(): TPromise<boolean> {
return this.windowService.reloadWindow({ _: [], 'disable-extensions': true }).then(() => true);
}
}
export abstract class BaseSwitchWindow extends Action {
private closeWindowAction: CloseWindowAction;
@@ -654,7 +653,7 @@ class CloseWindowAction extends Action implements IPickOpenAction {
export class SwitchWindow extends BaseSwitchWindow {
static ID = 'workbench.action.switchWindow';
static readonly ID = 'workbench.action.switchWindow';
static LABEL = nls.localize('switchWindow', "Switch Window...");
constructor(
@@ -676,7 +675,7 @@ export class SwitchWindow extends BaseSwitchWindow {
export class QuickSwitchWindow extends BaseSwitchWindow {
static ID = 'workbench.action.quickSwitchWindow';
static readonly ID = 'workbench.action.quickSwitchWindow';
static LABEL = nls.localize('quickSwitchWindow', "Quick Switch Window...");
constructor(
@@ -854,137 +853,44 @@ export class QuickOpenRecentAction extends BaseOpenRecentAction {
}
}
export class CloseMessagesAction extends Action {
public static readonly ID = 'workbench.action.closeMessages';
public static readonly LABEL = nls.localize('closeMessages', "Close Notification Messages");
constructor(
id: string,
label: string,
@IMessageService private messageService: IMessageService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService
) {
super(id, label);
}
public run(): TPromise<boolean> {
// Close any Message if visible
this.messageService.hideAll();
// Restore focus if we got an editor
const editor = this.editorService.getActiveEditor();
if (editor) {
editor.focus();
}
return TPromise.as(true);
}
}
export class ReportIssueAction extends Action {
public static readonly ID = 'workbench.action.reportIssues';
export class OpenIssueReporterAction extends Action {
public static readonly ID = 'workbench.action.openIssueReporter';
public static readonly LABEL = nls.localize({ key: 'reportIssueInEnglish', comment: ['Translate this to "Report Issue in English" in all languages please!'] }, "Report Issue");
constructor(
id: string,
label: string,
@IIntegrityService private integrityService: IIntegrityService,
@IExtensionManagementService private extensionManagementService: IExtensionManagementService,
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService,
@IEnvironmentService private environmentService: IEnvironmentService
@IWorkbenchIssueService private issueService: IWorkbenchIssueService
) {
super(id, label);
}
private _optimisticIsPure(): TPromise<boolean> {
let isPure = true;
let integrityPromise = this.integrityService.isPure().then(res => {
isPure = res.isPure;
});
return TPromise.any([TPromise.timeout(100), integrityPromise]).then(() => {
return isPure;
});
}
public run(): TPromise<boolean> {
return this._optimisticIsPure().then(isPure => {
return this.extensionManagementService.getInstalled(LocalExtensionType.User).then(extensions => {
extensions = extensions.filter(extension => this.extensionEnablementService.isEnabled(extension.identifier));
const issueUrl = this.generateNewIssueUrl(product.reportIssueUrl, pkg.name, pkg.version, product.commit, product.date, isPure, extensions, this.environmentService.disableExtensions);
window.open(issueUrl);
return TPromise.as(true);
});
});
}
private generateNewIssueUrl(baseUrl: string, name: string, version: string, commit: string, date: string, isPure: boolean, extensions: ILocalExtension[], areExtensionsDisabled: boolean): string {
// Avoid backticks, these can trigger XSS detectors. (https://github.com/Microsoft/vscode/issues/13098)
const osVersion = `${os.type()} ${os.arch()} ${os.release()}`;
const queryStringPrefix = baseUrl.indexOf('?') === -1 ? '?' : '&';
// {{SQL CARBON EDIT}}
const body = encodeURIComponent(
`- SQL Operations Studio Version: ${name} ${version}${isPure ? '' : ' **[Unsupported]**'} (${product.commit || 'Commit unknown'}, ${product.date || 'Date unknown'})
- OS Version: ${osVersion}
- Extensions: ${areExtensionsDisabled ? 'Extensions are disabled' : this.generateExtensionTable(extensions)}
---
Steps to Reproduce:
1.
2.` + (extensions.length ? `
<!-- Launch with \`code --disable-extensions\` to check. -->
Reproduces without extensions: Yes/No` : '')
);
return `${baseUrl}${queryStringPrefix}body=${body}`;
}
private generateExtensionTable(extensions: ILocalExtension[]): string {
const { nonThemes, themes } = collections.groupBy(extensions, ext => {
const manifestKeys = ext.manifest.contributes ? Object.keys(ext.manifest.contributes) : [];
const onlyTheme = !ext.manifest.activationEvents && manifestKeys.length === 1 && manifestKeys[0] === 'themes';
return onlyTheme ? 'themes' : 'nonThemes';
});
const themeExclusionStr = (themes && themes.length) ? `\n(${themes.length} theme extensions excluded)` : '';
extensions = nonThemes || [];
if (!extensions.length) {
return 'none' + themeExclusionStr;
}
let tableHeader = `Extension|Author (truncated)|Version
---|---|---`;
const table = extensions.map(e => {
return `${e.manifest.name}|${e.manifest.publisher.substr(0, 3)}|${e.manifest.version}`;
}).join('\n');
const extensionTable = `
${tableHeader}
${table}
${themeExclusionStr}
`;
// 2000 chars is browsers de-facto limit for URLs, 400 chars are allowed for other string parts of the issue URL
// http://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
if (encodeURIComponent(extensionTable).length > 1600) {
return 'the listing length exceeds browsers\' URL characters limit';
}
return extensionTable;
return this.issueService.openReporter()
.then(() => true);
}
}
export class ReportPerformanceIssueUsingReporterAction extends Action {
public static readonly ID = 'workbench.action.reportPerformanceIssueUsingReporter';
public static readonly LABEL = nls.localize('reportPerformanceIssue', "Report Performance Issue");
constructor(
id: string,
label: string,
@IWorkbenchIssueService private issueService: IWorkbenchIssueService
) {
super(id, label);
}
public run(): TPromise<boolean> {
// TODO: Reporter should send timings table as well
return this.issueService.openReporter({ issueType: IssueType.PerformanceIssue })
.then(() => true);
}
}
// NOTE: This is still used when running --prof-startup, which already opens a dialog, so the reporter is not used.
export class ReportPerformanceIssueAction extends Action {
public static readonly ID = 'workbench.action.reportPerformanceIssue';
@@ -1001,13 +907,13 @@ export class ReportPerformanceIssueAction extends Action {
}
public run(appendix?: string): TPromise<boolean> {
return this.integrityService.isPure().then(res => {
this.integrityService.isPure().then(res => {
const issueUrl = this.generatePerformanceIssueUrl(product.reportIssueUrl, pkg.name, pkg.version, product.commit, product.date, res.isPure, appendix);
window.open(issueUrl);
return TPromise.as(true);
});
return TPromise.wrap(true);
}
private generatePerformanceIssueUrl(baseUrl: string, name: string, version: string, commit: string, date: string, isPure: boolean, appendix?: string): string {
@@ -1191,7 +1097,7 @@ export class OpenTipsAndTricksUrlAction extends Action {
export class ToggleSharedProcessAction extends Action {
static ID = 'workbench.action.toggleSharedProcess';
static readonly ID = 'workbench.action.toggleSharedProcess';
static LABEL = nls.localize('toggleSharedProcess', "Toggle Shared Process");
constructor(id: string, label: string, @IWindowsService private windowsService: IWindowsService) {
@@ -1645,122 +1551,80 @@ export class ToggleWindowTabsBar extends Action {
}
}
export class ConfigureLocaleAction extends Action {
public static readonly ID = 'workbench.action.configureLocale';
public static readonly LABEL = nls.localize('configureLocale', "Configure Language");
export class ShowAboutDialogAction extends Action {
private static DEFAULT_CONTENT: string = [
'{',
`\t// ${nls.localize('displayLanguage', 'Defines VSCode\'s display language.')}`,
`\t// ${nls.localize('doc', 'See {0} for a list of supported languages.', 'https://go.microsoft.com/fwlink/?LinkId=761051')}`,
`\t// ${nls.localize('restart', 'Changing the value requires restarting VSCode.')}`,
`\t"locale":"${language}"`,
'}'
].join('\n');
public static readonly ID = 'workbench.action.showAboutDialog';
public static LABEL = nls.localize('about', "About {0}", product.applicationName);
constructor(id: string, label: string,
@IFileService private fileService: IFileService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IEnvironmentService private environmentService: IEnvironmentService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService
) {
super(id, label);
}
public run(event?: any): TPromise<IEditor> {
const file = URI.file(paths.join(this.environmentService.appSettingsHome, 'locale.json'));
return this.fileService.resolveFile(file).then(null, (error) => {
return this.fileService.createFile(file, ConfigureLocaleAction.DEFAULT_CONTENT);
}).then((stat) => {
if (!stat) {
return undefined;
}
return this.editorService.openEditor({
resource: stat.resource,
options: {
forceOpen: true
}
});
}, (error) => {
throw new Error(nls.localize('fail.createSettings', "Unable to create '{0}' ({1}).", getPathLabel(file, this.contextService), error));
});
}
}
export class OpenLogsFolderAction extends Action {
static ID = 'workbench.action.openLogsFolder';
static LABEL = nls.localize('openLogsFolder', "Open Logs Folder");
constructor(id: string, label: string,
@IEnvironmentService private environmentService: IEnvironmentService,
@IWindowsService private windowsService: IWindowsService,
constructor(
id: string,
label: string,
@IWindowsService private windowsService: IWindowsService
) {
super(id, label);
}
run(): TPromise<void> {
return this.windowsService.showItemInFolder(paths.join(this.environmentService.logsPath, 'main.log'));
return this.windowsService.openAboutDialog();
}
}
export class ShowLogsAction extends Action {
export class InspectContextKeysAction extends Action {
static ID = 'workbench.action.showLogs';
static LABEL = nls.localize('showLogs', "Show Logs...");
public static readonly ID = 'workbench.action.inspectContextKeys';
public static LABEL = nls.localize('inspect context keys', "Inspect Context Keys");
constructor(id: string, label: string,
@IEnvironmentService private environmentService: IEnvironmentService,
constructor(
id: string,
label: string,
@IContextKeyService private contextKeyService: IContextKeyService,
@IWindowService private windowService: IWindowService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IQuickOpenService private quickOpenService: IQuickOpenService
) {
super(id, label);
}
run(): TPromise<void> {
const entries: IPickOpenEntry[] = [
{ id: 'main', label: nls.localize('mainProcess', "Main"), run: () => this.editorService.openEditor({ resource: URI.file(paths.join(this.environmentService.logsPath, 'main.log')) }) },
{ id: 'shared', label: nls.localize('sharedProcess', "Shared"), run: () => this.editorService.openEditor({ resource: URI.file(paths.join(this.environmentService.logsPath, 'sharedprocess.log')) }) },
{ id: 'renderer', label: nls.localize('rendererProcess', "Renderer"), run: () => this.editorService.openEditor({ resource: URI.file(paths.join(this.environmentService.logsPath, `renderer${this.windowService.getCurrentWindowId()}.log`)) }) },
{ id: 'extenshionHost', label: nls.localize('extensionHost', "Extension Host"), run: () => this.editorService.openEditor({ resource: URI.file(paths.join(this.environmentService.logsPath, `exthost${this.windowService.getCurrentWindowId()}.log`)) }) }
];
const disposables: IDisposable[] = [];
return this.quickOpenService.pick(entries, { placeHolder: nls.localize('selectProcess', "Select process") }).then(entry => {
if (entry) {
entry.run(null);
}
});
const stylesheet = createStyleSheet();
disposables.push(toDisposable(() => stylesheet.parentNode.removeChild(stylesheet)));
createCSSRule('*', 'cursor: crosshair !important;', stylesheet);
const hoverFeedback = document.createElement('div');
document.body.appendChild(hoverFeedback);
disposables.push(toDisposable(() => document.body.removeChild(hoverFeedback)));
hoverFeedback.style.position = 'absolute';
hoverFeedback.style.pointerEvents = 'none';
hoverFeedback.style.backgroundColor = 'rgba(255, 0, 0, 0.5)';
hoverFeedback.style.zIndex = '1000';
const onMouseMove = domEvent(document.body, 'mousemove', true);
disposables.push(onMouseMove(e => {
const target = e.target as HTMLElement;
const position = getDomNodePagePosition(target);
hoverFeedback.style.top = `${position.top}px`;
hoverFeedback.style.left = `${position.left}px`;
hoverFeedback.style.width = `${position.width}px`;
hoverFeedback.style.height = `${position.height}px`;
}));
const onMouseDown = once(domEvent(document.body, 'mousedown', true));
onMouseDown(e => { e.preventDefault(); e.stopPropagation(); }, null, disposables);
const onMouseUp = once(domEvent(document.body, 'mouseup', true));
onMouseUp(e => {
e.preventDefault();
e.stopPropagation();
const context = this.contextKeyService.getContext(e.target as HTMLElement) as Context;
console.log(context.collectAllValues());
this.windowService.openDevTools();
dispose(disposables);
}, null, disposables);
return TPromise.as(null);
}
}
export class SetLogLevelAction extends Action {
static ID = 'workbench.action.setLogLevel';
static LABEL = nls.localize('setLogLevel', "Set Log Level");
constructor(id: string, label: string,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@ILogService private logService: ILogService
) {
super(id, label);
}
run(): TPromise<void> {
const entries = [
{ label: nls.localize('trace', "Trace"), level: LogLevel.Trace },
{ label: nls.localize('debug', "Debug"), level: LogLevel.Debug },
{ label: nls.localize('info', "Info"), level: LogLevel.Info },
{ label: nls.localize('warn', "Warning"), level: LogLevel.Warning },
{ label: nls.localize('err', "Error"), level: LogLevel.Error },
{ label: nls.localize('critical', "Critical"), level: LogLevel.Critical },
{ label: nls.localize('off', "Off"), level: LogLevel.Off }
];
return this.quickOpenService.pick(entries, { placeHolder: nls.localize('selectLogLevel', "Select log level"), autoFocus: { autoFocusIndex: this.logService.getLevel() } }).then(entry => {
if (entry) {
this.logService.setLevel(entry.level);
}
});
}
}

View File

@@ -3,8 +3,9 @@
<html>
<head>
<meta charset="utf-8" />
<!-- // {{SQL CARBON EDIT}} -->
<!-- // {{SQL CARBON EDIT}}
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data:; media-src 'none'; child-src 'self'; object-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https:;">
-->
</head>
<body class="monaco-shell vs-dark" aria-label="">
<script src="preload.js"></script>

View File

@@ -13,6 +13,7 @@ const perf = require('../../../base/common/performance');
perf.mark('renderer/started');
const path = require('path');
const fs = require('fs');
const electron = require('electron');
const remote = electron.remote;
const ipc = electron.ipcRenderer;
@@ -76,6 +77,18 @@ function uriFromPath(_path) {
return encodeURI('file://' + pathName);
}
function readFile(file) {
return new Promise(function(resolve, reject) {
fs.readFile(file, 'utf8', function(err, data) {
if (err) {
reject(err);
return;
}
resolve(data);
});
});
}
function registerListeners(enableDeveloperTools) {
// Devtools & reload support
@@ -135,6 +148,34 @@ function main() {
const args = parseURLQueryArgs();
const configuration = JSON.parse(args['config'] || '{}') || {};
//#region Add support for using node_modules.asar
(function () {
const path = require('path');
const Module = require('module');
let NODE_MODULES_PATH = path.join(configuration.appRoot, 'node_modules');
if (/[a-z]\:/.test(NODE_MODULES_PATH)) {
// Make drive letter uppercase
NODE_MODULES_PATH = NODE_MODULES_PATH.charAt(0).toUpperCase() + NODE_MODULES_PATH.substr(1);
}
const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar';
const originalResolveLookupPaths = Module._resolveLookupPaths;
Module._resolveLookupPaths = function (request, parent) {
const result = originalResolveLookupPaths(request, parent);
const paths = result[1];
for (let i = 0, len = paths.length; i < len; i++) {
if (paths[i] === NODE_MODULES_PATH) {
paths.splice(i, 0, NODE_MODULES_ASAR_PATH);
break;
}
}
return result;
};
})();
//#endregion
// Correctly inherit the parent's environment
assign(process.env, configuration.userEnv);
perf.importEntries(configuration.perfEntries);
@@ -149,13 +190,30 @@ function main() {
} catch (e) { /*noop*/ }
}
if (nlsConfig._resolvedLanguagePackCoreLocation) {
let bundles = Object.create(null);
nlsConfig.loadBundle = function(bundle, language, cb) {
let result = bundles[bundle];
if (result) {
cb(undefined, result);
return;
}
let bundleFile = path.join(nlsConfig._resolvedLanguagePackCoreLocation, bundle.replace(/\//g, '!') + '.nls.json');
readFile(bundleFile).then(function (content) {
let json = JSON.parse(content);
bundles[bundle] = json;
cb(undefined, json);
})
.catch(cb);
};
}
var locale = nlsConfig.availableLanguages['*'] || 'en';
if (locale === 'zh-tw') {
locale = 'zh-Hant';
} else if (locale === 'zh-cn') {
locale = 'zh-Hans';
}
window.document.documentElement.setAttribute('lang', locale);
const enableDeveloperTools = (process.env['VSCODE_DEV'] || !!configuration.extensionDevelopmentPath) && !configuration.extensionTestsPath;
@@ -178,6 +236,8 @@ function main() {
const loaderFilename = configuration.appRoot + '/out/vs/loader.js';
const loaderSource = require('fs').readFileSync(loaderFilename);
require('vm').runInThisContext(loaderSource, { filename: loaderFilename });
var define = global.define;
global.define = undefined;
window.nodeRequire = require.__$__nodeRequire;
@@ -186,8 +246,6 @@ function main() {
window.MonacoEnvironment = {};
const onNodeCachedData = window.MonacoEnvironment.onNodeCachedData = [];
// {{SQL CARBON EDIT}}
require.config({
baseUrl: uriFromPath(configuration.appRoot) + '/out',
'vs/nls': nlsConfig,
@@ -218,23 +276,20 @@ function main() {
}
// Perf Counters
const timers = window.MonacoEnvironment.timers = {
window.MonacoEnvironment.timers = {
isInitialStartup: !!configuration.isInitialStartup,
hasAccessibilitySupport: !!configuration.accessibilitySupport,
start: configuration.perfStartTime,
appReady: configuration.perfAppReady,
windowLoad: configuration.perfWindowLoadTime,
beforeLoadWorkbenchMain: Date.now()
windowLoad: configuration.perfWindowLoadTime
};
const workbenchMainClock = perf.time('loadWorkbenchMain');
perf.mark('willLoadWorkbenchMain');
require([
'vs/workbench/workbench.main',
'vs/nls!vs/workbench/workbench.main',
'vs/css!vs/workbench/workbench.main'
], function () {
workbenchMainClock.stop();
timers.afterLoadWorkbenchMain = Date.now();
perf.mark('didLoadWorkbenchMain');
process.lazyEnv.then(function () {
perf.mark('main/startup');

View File

@@ -18,14 +18,40 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import URI from 'vs/base/common/uri';
import { IEditorOptions, Position as EditorPosition } from 'vs/platform/editor/common/editor';
import { openFolderCommand, openFileInNewWindowCommand, openFileFolderInNewWindowCommand, openFolderInNewWindowCommand, openWorkspaceInNewWindowCommand } from 'vs/workbench/browser/actions/workspaceActions';
import { WorkbenchListFocusContextKey, IListService } from 'vs/platform/list/browser/listService';
import { WorkbenchListFocusContextKey, IListService, WorkbenchListSupportsMultiSelectContextKey } from 'vs/platform/list/browser/listService';
import { PagedList } from 'vs/base/browser/ui/list/listPaging';
import { range } from 'vs/base/common/arrays';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ITree } from 'vs/base/parts/tree/browser/tree';
// --- List Commands
export function registerCommands(): void {
function focusDown(accessor: ServicesAccessor, arg2?: number): void {
const focused = accessor.get(IListService).lastFocusedList;
const count = typeof arg2 === 'number' ? arg2 : 1;
// List
if (focused instanceof List || focused instanceof PagedList) {
const list = focused;
list.focusNext(count);
const listFocus = list.getFocus();
if (listFocus.length) {
list.reveal(listFocus[0]);
}
}
// Tree
else if (focused) {
const tree = focused;
tree.focusNext(count, { origin: 'keyboard' });
tree.reveal(tree.getFocus()).done(null, errors.onUnexpectedError);
}
}
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.focusDown',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
@@ -35,28 +61,96 @@ export function registerCommands(): void {
primary: KeyCode.DownArrow,
secondary: [KeyMod.WinCtrl | KeyCode.KEY_N]
},
handler: (accessor, arg2) => focusDown(accessor, arg2)
});
function expandMultiSelection(focused: List<any> | PagedList<any> | ITree, previousFocus: any): void {
// List
if (focused instanceof List || focused instanceof PagedList) {
const list = focused;
const focus = list.getFocus() ? list.getFocus()[0] : void 0;
const selection = list.getSelection();
if (selection && selection.indexOf(focus) >= 0) {
list.setSelection(selection.filter(s => s !== previousFocus));
} else {
list.setSelection(selection.concat(focus));
}
}
// Tree
else if (focused) {
const tree = focused;
const focus = tree.getFocus();
const selection = tree.getSelection();
if (selection && selection.indexOf(focus) >= 0) {
tree.setSelection(selection.filter(s => s !== previousFocus));
} else {
tree.setSelection(selection.concat(focus));
}
}
}
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.expandSelectionDown',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: WorkbenchListFocusContextKey,
primary: KeyMod.Shift | KeyCode.DownArrow,
handler: (accessor, arg2) => {
const focused = accessor.get(IListService).lastFocusedList;
const count = typeof arg2 === 'number' ? arg2 : 1;
// List
if (focused instanceof List || focused instanceof PagedList) {
const list = focused;
list.focusNext(count);
list.reveal(list.getFocus()[0]);
// Focus down first
const previousFocus = list.getFocus() ? list.getFocus()[0] : void 0;
focusDown(accessor, arg2);
// Then adjust selection
expandMultiSelection(focused, previousFocus);
}
// Tree
else if (focused) {
const tree = focused;
tree.focusNext(count, { origin: 'keyboard' });
tree.reveal(tree.getFocus()).done(null, errors.onUnexpectedError);
// Focus down first
const previousFocus = tree.getFocus();
focusDown(accessor, arg2);
// Then adjust selection
expandMultiSelection(focused, previousFocus);
}
}
});
function focusUp(accessor: ServicesAccessor, arg2?: number): void {
const focused = accessor.get(IListService).lastFocusedList;
const count = typeof arg2 === 'number' ? arg2 : 1;
// List
if (focused instanceof List || focused instanceof PagedList) {
const list = focused;
list.focusPrevious(count);
const listFocus = list.getFocus();
if (listFocus.length) {
list.reveal(listFocus[0]);
}
}
// Tree
else if (focused) {
const tree = focused;
tree.focusPrevious(count, { origin: 'keyboard' });
tree.reveal(tree.getFocus()).done(null, errors.onUnexpectedError);
}
}
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.focusUp',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
@@ -66,24 +160,39 @@ export function registerCommands(): void {
primary: KeyCode.UpArrow,
secondary: [KeyMod.WinCtrl | KeyCode.KEY_P]
},
handler: (accessor, arg2) => focusUp(accessor, arg2)
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.expandSelectionUp',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: WorkbenchListFocusContextKey,
primary: KeyMod.Shift | KeyCode.UpArrow,
handler: (accessor, arg2) => {
const focused = accessor.get(IListService).lastFocusedList;
const count = typeof arg2 === 'number' ? arg2 : 1;
// List
if (focused instanceof List || focused instanceof PagedList) {
const list = focused;
list.focusPrevious(count);
list.reveal(list.getFocus()[0]);
// Focus up first
const previousFocus = list.getFocus() ? list.getFocus()[0] : void 0;
focusUp(accessor, arg2);
// Then adjust selection
expandMultiSelection(focused, previousFocus);
}
// Tree
else if (focused) {
const tree = focused;
tree.focusPrevious(count, { origin: 'keyboard' });
tree.reveal(tree.getFocus()).done(null, errors.onUnexpectedError);
// Focus up first
const previousFocus = tree.getFocus();
focusUp(accessor, arg2);
// Then adjust selection
expandMultiSelection(focused, previousFocus);
}
}
});
@@ -273,10 +382,9 @@ export function registerCommands(): void {
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: WorkbenchListFocusContextKey,
primary: KeyCode.Enter,
secondary: [KeyMod.CtrlCmd | KeyCode.Enter],
mac: {
primary: KeyCode.Enter,
secondary: [KeyMod.CtrlCmd | KeyCode.Enter, KeyMod.CtrlCmd | KeyCode.DownArrow]
secondary: [KeyMod.CtrlCmd | KeyCode.DownArrow]
},
handler: (accessor) => {
const focused = accessor.get(IListService).lastFocusedList;
@@ -300,6 +408,22 @@ export function registerCommands(): void {
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.selectAll',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: ContextKeyExpr.and(WorkbenchListFocusContextKey, WorkbenchListSupportsMultiSelectContextKey),
primary: KeyMod.CtrlCmd | KeyCode.KEY_A,
handler: (accessor) => {
const focused = accessor.get(IListService).lastFocusedList;
// List
if (focused instanceof List || focused instanceof PagedList) {
const list = focused;
list.setSelection(range(list.length));
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.toggleExpand',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
@@ -411,10 +535,11 @@ export function registerCommands(): void {
});
});
CommandsRegistry.registerCommand('_files.pickFolderAndOpen', openFolderCommand);
CommandsRegistry.registerCommand('_workbench.removeFromRecentlyOpened', function (accessor: ServicesAccessor, path: string) {
const windowsService = accessor.get(IWindowsService);
CommandsRegistry.registerCommand('workbench.action.files.openFileInNewWindow', openFileInNewWindowCommand);
CommandsRegistry.registerCommand('workbench.action.files.openFolderInNewWindow', openFolderInNewWindowCommand);
CommandsRegistry.registerCommand('workbench.action.files.openFileFolderInNewWindow', openFileFolderInNewWindowCommand);
CommandsRegistry.registerCommand('workbench.action.openWorkspaceInNewWindow', openWorkspaceInNewWindowCommand);
return windowsService.removeFromRecentlyOpened([path]).then(() => {
return void 0;
});
});
}

View File

@@ -14,15 +14,12 @@ import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'v
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform';
import { CloseEditorAction, KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, ReportIssueAction, ReportPerformanceIssueAction, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleFullScreenAction, ToggleMenuBarAction, CloseWorkspaceAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, CloseMessagesAction, NavigateUpAction, NavigateDownAction, NavigateLeftAction, NavigateRightAction, IncreaseViewSizeAction, DecreaseViewSizeAction, ShowStartupPerformance, ToggleSharedProcessAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, ConfigureLocaleAction, ShowLogsAction, OpenLogsFolderAction, SetLogLevelAction } from 'vs/workbench/electron-browser/actions';
import { MessagesVisibleContext } from 'vs/workbench/electron-browser/workbench';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, OpenIssueReporterAction, ReportPerformanceIssueUsingReporterAction, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleFullScreenAction, ToggleMenuBarAction, CloseWorkspaceAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, NavigateUpAction, NavigateDownAction, NavigateLeftAction, NavigateRightAction, IncreaseViewSizeAction, DecreaseViewSizeAction, ShowStartupPerformance, ToggleSharedProcessAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, ShowAboutDialogAction, InspectContextKeysAction } from 'vs/workbench/electron-browser/actions';
import { registerCommands } from 'vs/workbench/electron-browser/commands';
import { AddRootFolderAction, GlobalRemoveRootFolderAction, OpenWorkspaceAction, SaveWorkspaceAsAction, OpenWorkspaceConfigFileAction, OpenFolderAsWorkspaceInNewWindowAction, OpenFileFolderAction, OpenFileAction, OpenFolderAction } from 'vs/workbench/browser/actions/workspaceActions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { inQuickOpenContext, getQuickNavigateHandler } from 'vs/workbench/browser/parts/quickopen/quickopen';
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
// Contribute Commands
registerCommands();
@@ -31,16 +28,11 @@ registerCommands();
const viewCategory = nls.localize('view', "View");
const helpCategory = nls.localize('help', "Help");
const fileCategory = nls.localize('file', "File");
const devCategory = nls.localize('developer', "Developer");
const workbenchActionsRegistry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(NewWindowAction, NewWindowAction.ID, NewWindowAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_N }), 'New Window');
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(CloseCurrentWindowAction, CloseCurrentWindowAction.ID, CloseCurrentWindowAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_W }), 'Close Window');
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(SwitchWindow, SwitchWindow.ID, SwitchWindow.LABEL, { primary: null, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_W } }), 'Switch Window...');
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(QuickSwitchWindow, QuickSwitchWindow.ID, QuickSwitchWindow.LABEL), 'Quick Switch Window...');
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ShowLogsAction, ShowLogsAction.ID, ShowLogsAction.LABEL), 'Developer: Show Logs...', devCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenLogsFolderAction, OpenLogsFolderAction.ID, OpenLogsFolderAction.LABEL), 'Developer: Open Log Folder', devCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(SetLogLevelAction, SetLogLevelAction.ID, SetLogLevelAction.LABEL), 'Developer: Set Log Level', devCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenRecentAction, QuickOpenRecentAction.ID, QuickOpenRecentAction.LABEL), 'File: Quick Open Recent...', fileCategory);
if (isMacintosh) {
@@ -52,26 +44,34 @@ if (isMacintosh) {
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(CloseWorkspaceAction, CloseWorkspaceAction.ID, CloseWorkspaceAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_F) }), 'File: Close Workspace', fileCategory);
if (!!product.reportIssueUrl) {
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ReportIssueAction, ReportIssueAction.ID, ReportIssueAction.LABEL), 'Help: Report Issues', helpCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ReportPerformanceIssueAction, ReportPerformanceIssueAction.ID, ReportPerformanceIssueAction.LABEL), 'Help: Report Performance Issue', helpCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenIssueReporterAction, OpenIssueReporterAction.ID, OpenIssueReporterAction.LABEL), 'Help: Open Issue Reporter', helpCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ReportPerformanceIssueUsingReporterAction, ReportPerformanceIssueUsingReporterAction.ID, ReportPerformanceIssueUsingReporterAction.LABEL), 'Help: Report Performance Issue', helpCategory);
}
if (KeybindingsReferenceAction.AVAILABLE) {
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(KeybindingsReferenceAction, KeybindingsReferenceAction.ID, KeybindingsReferenceAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_R) }), 'Help: Keyboard Shortcuts Reference', helpCategory);
}
if (OpenDocumentationUrlAction.AVAILABLE) {
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenDocumentationUrlAction, OpenDocumentationUrlAction.ID, OpenDocumentationUrlAction.LABEL), 'Help: Documentation', helpCategory);
}
if (OpenIntroductoryVideosUrlAction.AVAILABLE) {
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenIntroductoryVideosUrlAction, OpenIntroductoryVideosUrlAction.ID, OpenIntroductoryVideosUrlAction.LABEL), 'Help: Introductory Videos', helpCategory);
}
if (OpenTipsAndTricksUrlAction.AVAILABLE) {
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenTipsAndTricksUrlAction, OpenTipsAndTricksUrlAction.ID, OpenTipsAndTricksUrlAction.LABEL), 'Help: Tips and Tricks', helpCategory);
}
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ShowAboutDialogAction, ShowAboutDialogAction.ID, ShowAboutDialogAction.LABEL), 'Help: About', helpCategory);
workbenchActionsRegistry.registerWorkbenchAction(
new SyncActionDescriptor(ZoomInAction, ZoomInAction.ID, ZoomInAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.US_EQUAL,
secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_EQUAL, KeyMod.CtrlCmd | KeyCode.NUMPAD_ADD]
}), 'View: Zoom In', viewCategory);
workbenchActionsRegistry.registerWorkbenchAction(
new SyncActionDescriptor(ZoomOutAction, ZoomOutAction.ID, ZoomOutAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.US_MINUS,
@@ -79,13 +79,13 @@ workbenchActionsRegistry.registerWorkbenchAction(
linux: { primary: KeyMod.CtrlCmd | KeyCode.US_MINUS, secondary: [KeyMod.CtrlCmd | KeyCode.NUMPAD_SUBTRACT] }
}), 'View: Zoom Out', viewCategory
);
workbenchActionsRegistry.registerWorkbenchAction(
new SyncActionDescriptor(ZoomResetAction, ZoomResetAction.ID, ZoomResetAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.NUMPAD_0
}), 'View: Reset Zoom', viewCategory
);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(CloseMessagesAction, CloseMessagesAction.ID, CloseMessagesAction.LABEL, { primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape] }, MessagesVisibleContext), 'Close Notification Messages');
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(CloseEditorAction, CloseEditorAction.ID, CloseEditorAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_W, win: { primary: KeyMod.CtrlCmd | KeyCode.F4, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_W] } }), 'View: Close Editor', viewCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleFullScreenAction, ToggleFullScreenAction.ID, ToggleFullScreenAction.LABEL, { primary: KeyCode.F11, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_F } }), 'View: Toggle Full Screen', viewCategory);
if (isWindows || isLinux) {
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleMenuBarAction, ToggleMenuBarAction.ID, ToggleMenuBarAction.LABEL), 'View: Toggle Menu Bar', viewCategory);
@@ -110,6 +110,7 @@ workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenFo
const developerCategory = nls.localize('developer', "Developer");
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ShowStartupPerformance, ShowStartupPerformance.ID, ShowStartupPerformance.LABEL), 'Developer: Startup Performance', developerCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleSharedProcessAction, ToggleSharedProcessAction.ID, ToggleSharedProcessAction.LABEL), 'Developer: Toggle Shared Process', developerCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(InspectContextKeysAction, InspectContextKeysAction.ID, InspectContextKeysAction.LABEL), 'Developer: Inspect Context Keys', developerCategory);
const recentFilesPickerContext = ContextKeyExpr.and(inQuickOpenContext, ContextKeyExpr.has(inRecentFilesPickerContextKey));
@@ -136,145 +137,148 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
// Configuration: Workbench
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
let workbenchProperties: { [path: string]: IJSONSchema; } = {
'workbench.editor.showTabs': {
'type': 'boolean',
'description': nls.localize('showEditorTabs', "Controls if opened editors should show in tabs or not."),
'default': true
},
'workbench.editor.labelFormat': {
'type': 'string',
'enum': ['default', 'short', 'medium', 'long'],
'enumDescriptions': [
nls.localize('workbench.editor.labelFormat.default', "Show the name of the file. When tabs are enabled and two files have the same name in one group the distinguinshing sections of each file's path are added. When tabs are disabled, the path relative to the workspace folder is shown if the editor is active."),
nls.localize('workbench.editor.labelFormat.short', "Show the name of the file followed by it's directory name."),
nls.localize('workbench.editor.labelFormat.medium', "Show the name of the file followed by it's path relative to the workspace folder."),
nls.localize('workbench.editor.labelFormat.long', "Show the name of the file followed by it's absolute path.")
],
'default': 'default',
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by parenthesis are not to be translated.'], key: 'tabDescription' },
"Controls the format of the label for an editor. Changing this setting can for example make it easier to understand the location of a file:\n- short: 'parent'\n- medium: 'workspace/src/parent'\n- long: '/home/user/workspace/src/parent'\n- default: '.../parent', when another tab shares the same title, or the relative workspace path if tabs are disabled"),
},
'workbench.editor.tabCloseButton': {
'type': 'string',
'enum': ['left', 'right', 'off'],
'default': 'right',
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorTabCloseButton' }, "Controls the position of the editor's tabs close buttons or disables them when set to 'off'.")
},
'workbench.editor.tabSizing': {
'type': 'string',
'enum': ['fit', 'shrink'],
'default': 'fit',
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'tabSizing' }, "Controls the sizing of editor tabs. Set to 'fit' to keep tabs always large enough to show the full editor label. Set to 'shrink' to allow tabs to get smaller when the available space is not enough to show all tabs at once.")
},
'workbench.editor.showIcons': {
'type': 'boolean',
'description': nls.localize('showIcons', "Controls if opened editors should show with an icon or not. This requires an icon theme to be enabled as well."),
'default': true
},
'workbench.editor.enablePreview': {
'type': 'boolean',
'description': nls.localize('enablePreview', "Controls if opened editors show as preview. Preview editors are reused until they are kept (e.g. via double click or editing) and show up with an italic font style."),
'default': true
},
'workbench.editor.enablePreviewFromQuickOpen': {
'type': 'boolean',
'description': nls.localize('enablePreviewFromQuickOpen', "Controls if opened editors from Quick Open show as preview. Preview editors are reused until they are kept (e.g. via double click or editing)."),
'default': true
},
'workbench.editor.openPositioning': {
'type': 'string',
'enum': ['left', 'right', 'first', 'last'],
'default': 'right',
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorOpenPositioning' }, "Controls where editors open. Select 'left' or 'right' to open editors to the left or right of the currently active one. Select 'first' or 'last' to open editors independently from the currently active one.")
},
'workbench.editor.revealIfOpen': {
'type': 'boolean',
'description': nls.localize('revealIfOpen', "Controls if an editor is revealed in any of the visible groups if opened. If disabled, an editor will prefer to open in the currently active editor group. If enabled, an already opened editor will be revealed instead of opened again in the currently active editor group. Note that there are some cases where this setting is ignored, e.g. when forcing an editor to open in a specific group or to the side of the currently active group."),
'default': false
},
'workbench.commandPalette.history': {
'type': 'number',
'description': nls.localize('commandHistory', "Controls the number of recently used commands to keep in history for the command palette. Set to 0 to disable command history."),
'default': 50
},
'workbench.commandPalette.preserveInput': {
'type': 'boolean',
'description': nls.localize('preserveInput', "Controls if the last typed input to the command palette should be restored when opening it the next time."),
'default': false
},
'workbench.quickOpen.closeOnFocusLost': {
'type': 'boolean',
'description': nls.localize('closeOnFocusLost', "Controls if Quick Open should close automatically once it loses focus."),
'default': true
},
'workbench.settings.openDefaultSettings': {
'type': 'boolean',
'description': nls.localize('openDefaultSettings', "Controls if opening settings also opens an editor showing all default settings."),
'default': true
},
'workbench.sideBar.location': {
'type': 'string',
'enum': ['left', 'right'],
'default': 'left',
'description': nls.localize('sideBarLocation', "Controls the location of the sidebar. It can either show on the left or right of the workbench.")
},
'workbench.statusBar.visible': {
'type': 'boolean',
'default': true,
'description': nls.localize('statusBarVisibility', "Controls the visibility of the status bar at the bottom of the workbench.")
},
'workbench.activityBar.visible': {
'type': 'boolean',
'default': true,
'description': nls.localize('activityBarVisibility', "Controls the visibility of the activity bar in the workbench.")
},
'workbench.editor.closeOnFileDelete': {
'type': 'boolean',
'description': nls.localize('closeOnFileDelete', "Controls if editors showing a file should close automatically when the file is deleted or renamed by some other process. Disabling this will keep the editor open as dirty on such an event. Note that deleting from within the application will always close the editor and that dirty files will never close to preserve your data."),
'default': true
}
};
if (product.quality !== 'stable') {
workbenchProperties['workbench.settings.enableNaturalLanguageSearch'] = {
'type': 'boolean',
'description': nls.localize('enableNaturalLanguageSettingsSearch', "Controls whether to enable the natural language search mode for settings."),
'default': true
};
}
if (isMacintosh) {
workbenchProperties['workbench.fontAliasing'] = {
'type': 'string',
'enum': ['default', 'antialiased', 'none'],
'default': 'default',
'description':
nls.localize('fontAliasing', "Controls font aliasing method in the workbench.\n- default: Sub-pixel font smoothing. On most non-retina displays this will give the sharpest text\n- antialiased: Smooth the font on the level of the pixel, as opposed to the subpixel. Can make the font appear lighter overall\n- none: Disables font smoothing. Text will show with jagged sharp edges"),
'enumDescriptions': [
nls.localize('workbench.fontAliasing.default', "Sub-pixel font smoothing. On most non-retina displays this will give the sharpest text."),
nls.localize('workbench.fontAliasing.antialiased', "Smooth the font on the level of the pixel, as opposed to the subpixel. Can make the font appear lighter overall."),
nls.localize('workbench.fontAliasing.none', "Disables font smoothing. Text will show with jagged sharp edges.")
],
};
workbenchProperties['workbench.editor.swipeToNavigate'] = {
'type': 'boolean',
'description': nls.localize('swipeToNavigate', "Navigate between open files using three-finger swipe horizontally."),
'default': false
};
}
configurationRegistry.registerConfiguration({
'id': 'workbench',
'order': 7,
'title': nls.localize('workbenchConfigurationTitle', "Workbench"),
'type': 'object',
'properties': workbenchProperties
'properties': {
'workbench.editor.showTabs': {
'type': 'boolean',
'description': nls.localize('showEditorTabs', "Controls if opened editors should show in tabs or not."),
'default': true
},
'workbench.editor.labelFormat': {
'type': 'string',
'enum': ['default', 'short', 'medium', 'long'],
'enumDescriptions': [
nls.localize('workbench.editor.labelFormat.default', "Show the name of the file. When tabs are enabled and two files have the same name in one group the distinguinshing sections of each file's path are added. When tabs are disabled, the path relative to the workspace folder is shown if the editor is active."),
nls.localize('workbench.editor.labelFormat.short', "Show the name of the file followed by it's directory name."),
nls.localize('workbench.editor.labelFormat.medium', "Show the name of the file followed by it's path relative to the workspace folder."),
nls.localize('workbench.editor.labelFormat.long', "Show the name of the file followed by it's absolute path.")
],
'default': 'default',
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by parenthesis are not to be translated.'], key: 'tabDescription' },
"Controls the format of the label for an editor. Changing this setting can for example make it easier to understand the location of a file:\n- short: 'parent'\n- medium: 'workspace/src/parent'\n- long: '/home/user/workspace/src/parent'\n- default: '.../parent', when another tab shares the same title, or the relative workspace path if tabs are disabled"),
},
'workbench.editor.tabCloseButton': {
'type': 'string',
'enum': ['left', 'right', 'off'],
'default': 'right',
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorTabCloseButton' }, "Controls the position of the editor's tabs close buttons or disables them when set to 'off'.")
},
'workbench.editor.tabSizing': {
'type': 'string',
'enum': ['fit', 'shrink'],
'default': 'fit',
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'tabSizing' }, "Controls the sizing of editor tabs. Set to 'fit' to keep tabs always large enough to show the full editor label. Set to 'shrink' to allow tabs to get smaller when the available space is not enough to show all tabs at once.")
},
'workbench.editor.showIcons': {
'type': 'boolean',
'description': nls.localize('showIcons', "Controls if opened editors should show with an icon or not. This requires an icon theme to be enabled as well."),
'default': true
},
'workbench.editor.enablePreview': {
'type': 'boolean',
'description': nls.localize('enablePreview', "Controls if opened editors show as preview. Preview editors are reused until they are kept (e.g. via double click or editing) and show up with an italic font style."),
'default': true
},
'workbench.editor.enablePreviewFromQuickOpen': {
'type': 'boolean',
'description': nls.localize('enablePreviewFromQuickOpen', "Controls if opened editors from Quick Open show as preview. Preview editors are reused until they are kept (e.g. via double click or editing)."),
'default': true
},
'workbench.editor.closeOnFileDelete': {
'type': 'boolean',
'description': nls.localize('closeOnFileDelete', "Controls if editors showing a file should close automatically when the file is deleted or renamed by some other process. Disabling this will keep the editor open as dirty on such an event. Note that deleting from within the application will always close the editor and that dirty files will never close to preserve your data."),
'default': true
},
'workbench.editor.openPositioning': {
'type': 'string',
'enum': ['left', 'right', 'first', 'last'],
'default': 'right',
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorOpenPositioning' }, "Controls where editors open. Select 'left' or 'right' to open editors to the left or right of the currently active one. Select 'first' or 'last' to open editors independently from the currently active one.")
},
'workbench.editor.revealIfOpen': {
'type': 'boolean',
'description': nls.localize('revealIfOpen', "Controls if an editor is revealed in any of the visible groups if opened. If disabled, an editor will prefer to open in the currently active editor group. If enabled, an already opened editor will be revealed instead of opened again in the currently active editor group. Note that there are some cases where this setting is ignored, e.g. when forcing an editor to open in a specific group or to the side of the currently active group."),
'default': false
},
'workbench.editor.swipeToNavigate': {
'type': 'boolean',
'description': nls.localize('swipeToNavigate', "Navigate between open files using three-finger swipe horizontally."),
'default': false,
'included': isMacintosh
},
'workbench.commandPalette.history': {
'type': 'number',
'description': nls.localize('commandHistory', "Controls the number of recently used commands to keep in history for the command palette. Set to 0 to disable command history."),
'default': 50
},
'workbench.commandPalette.preserveInput': {
'type': 'boolean',
'description': nls.localize('preserveInput', "Controls if the last typed input to the command palette should be restored when opening it the next time."),
'default': false
},
'workbench.quickOpen.closeOnFocusLost': {
'type': 'boolean',
'description': nls.localize('closeOnFocusLost', "Controls if Quick Open should close automatically once it loses focus."),
'default': true
},
'workbench.settings.openDefaultSettings': {
'type': 'boolean',
'description': nls.localize('openDefaultSettings', "Controls if opening settings also opens an editor showing all default settings."),
'default': true
},
'workbench.sideBar.location': {
'type': 'string',
'enum': ['left', 'right'],
'default': 'left',
'description': nls.localize('sideBarLocation', "Controls the location of the sidebar. It can either show on the left or right of the workbench.")
},
'workbench.panel.defaultLocation': {
'type': 'string',
'enum': ['bottom', 'right'],
'default': 'bottom',
'description': nls.localize('panelDefaultLocation', "Controls the default location of the panel. It can either show at the bottom or on the right of the workbench.")
},
'workbench.statusBar.visible': {
'type': 'boolean',
'default': true,
'description': nls.localize('statusBarVisibility', "Controls the visibility of the status bar at the bottom of the workbench.")
},
'workbench.activityBar.visible': {
'type': 'boolean',
'default': true,
'description': nls.localize('activityBarVisibility', "Controls the visibility of the activity bar in the workbench.")
},
'workbench.view.alwaysShowHeaderActions': {
'type': 'boolean',
'default': false,
'description': nls.localize('viewVisibility', "Controls the visibility of view header actions. View header actions may either be always visible, or only visible when that view is focused or hovered over.")
},
'workbench.fontAliasing': {
'type': 'string',
'enum': ['default', 'antialiased', 'none', 'auto'],
'default': 'default',
'description':
nls.localize('fontAliasing', "Controls font aliasing method in the workbench.\n- default: Sub-pixel font smoothing. On most non-retina displays this will give the sharpest text\n- antialiased: Smooth the font on the level of the pixel, as opposed to the subpixel. Can make the font appear lighter overall\n- none: Disables font smoothing. Text will show with jagged sharp edges\n- auto: Applies `default` or `antialiased` automatically based on the DPI of displays."),
'enumDescriptions': [
nls.localize('workbench.fontAliasing.default', "Sub-pixel font smoothing. On most non-retina displays this will give the sharpest text."),
nls.localize('workbench.fontAliasing.antialiased', "Smooth the font on the level of the pixel, as opposed to the subpixel. Can make the font appear lighter overall."),
nls.localize('workbench.fontAliasing.none', "Disables font smoothing. Text will show with jagged sharp edges."),
nls.localize('workbench.fontAliasing.auto', "Applies `default` or `antialiased` automatically based on the DPI of displays.")
],
'included': isMacintosh
},
'workbench.settings.enableNaturalLanguageSearch': {
'type': 'boolean',
'description': nls.localize('enableNaturalLanguageSettingsSearch', "Controls whether to enable the natural language search mode for settings."),
'default': true
}
}
});
// Configuration: Window
configurationRegistry.registerConfiguration({
@@ -304,8 +308,7 @@ configurationRegistry.registerConfiguration({
nls.localize('window.openFoldersInNewWindow.default', "Folders will open in a new window unless a folder is picked from within the application (e.g. via the File menu)")
],
'default': 'default',
'description': nls.localize('openFoldersInNewWindow', "Controls if folders should open in a new window or replace the last active window.\n- default: folders will open in a new window unless a folder is picked from within the application (e.g. via the File menu)\n- on: folders will open in a new window\n- off: folders will replace the last active window\nNote that there can still be cases where this setting is ignored (e.g. when using the -new-window or -reuse-window command line option)."
)
'description': nls.localize('openFoldersInNewWindow', "Controls if folders should open in a new window or replace the last active window.\n- default: folders will open in a new window unless a folder is picked from within the application (e.g. via the File menu)\n- on: folders will open in a new window\n- off: folders will replace the last active window\nNote that there can still be cases where this setting is ignored (e.g. when using the -new-window or -reuse-window command line option).")
},
'window.restoreWindows': {
'type': 'string',
@@ -375,7 +378,7 @@ configurationRegistry.registerConfiguration({
'type': 'boolean',
'default': true,
'description': nls.localize('autoDetectHighContrast', "If enabled, will automatically change to high contrast theme if Windows is using a high contrast theme, and to dark theme when switching away from a Windows high contrast theme."),
'included': !isWindows
'included': isWindows
},
'window.titleBarStyle': {
'type': 'string',
@@ -405,6 +408,11 @@ configurationRegistry.registerConfiguration({
'default': true,
'description': nls.localize('zenMode.fullScreen', "Controls if turning on Zen Mode also puts the workbench into full screen mode.")
},
'zenMode.centerLayout': {
'type': 'boolean',
'default': true,
'description': nls.localize('zenMode.centerLayout', "Controls if turning on Zen Mode also centers the layout.")
},
'zenMode.hideTabs': {
'type': 'boolean',
'default': true,
@@ -427,37 +435,3 @@ configurationRegistry.registerConfiguration({
}
}
});
// Register action to configure locale and related settings
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureLocaleAction, ConfigureLocaleAction.ID, ConfigureLocaleAction.LABEL), 'Configure Language');
let enumValues: string[] = ['de', 'en', 'en-US', 'es', 'fr', 'it', 'ja', 'ko', 'ru', 'zh-CN', 'zh-TW'];
if (product.quality !== 'stable') {
enumValues.push('hu');
}
const schemaId = 'vscode://schemas/locale';
// Keep en-US since we generated files with that content.
const schema: IJSONSchema =
{
id: schemaId,
allowComments: true,
description: 'Locale Definition file',
type: 'object',
default: {
'locale': 'en'
},
required: ['locale'],
properties: {
locale: {
type: 'string',
enum: enumValues,
description: nls.localize('JsonSchema.locale', 'The UI Language to use.')
}
}
};
const jsonRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
jsonRegistry.registerSchema(schemaId, schema);

View File

@@ -6,6 +6,7 @@
'use strict';
import nls = require('vs/nls');
import * as perf from 'vs/base/common/performance';
import { TPromise } from 'vs/base/common/winjs.base';
import { WorkbenchShell } from 'vs/workbench/electron-browser/shell';
import * as browser from 'vs/base/browser/browser';
@@ -30,23 +31,24 @@ import { IWindowConfiguration, IWindowsService } from 'vs/platform/windows/commo
import { WindowsChannelClient } from 'vs/platform/windows/common/windowsIpc';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { StorageService, inMemoryLocalStorageInstance } from 'vs/platform/storage/common/storageService';
import { StorageService, inMemoryLocalStorageInstance, IStorage } from 'vs/platform/storage/common/storageService';
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
import { webFrame, remote } from 'electron';
import { webFrame } from 'electron';
import { UpdateChannelClient } from 'vs/platform/update/common/updateIpc';
import { IUpdateService } from 'vs/platform/update/common/update';
import { URLChannelClient } from 'vs/platform/url/common/urlIpc';
import { IURLService } from 'vs/platform/url/common/url';
import { WorkspacesChannelClient } from 'vs/platform/workspaces/common/workspacesIpc';
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { createLogService } from 'vs/platform/log/node/spdlogService';
import { createSpdLogService } from 'vs/platform/log/node/spdlogService';
import fs = require('fs');
import { ConsoleLogService, MultiplexLogService } from 'vs/platform/log/common/log';
import { ConsoleLogService, MultiplexLogService, ILogService } from 'vs/platform/log/common/log';
import { IssueChannelClient } from 'vs/platform/issue/common/issueIpc';
import { IIssueService } from 'vs/platform/issue/common/issue';
import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc';
gracefulFs.gracefulify(fs); // enable gracefulFs
const currentWindowId = remote.getCurrentWindow().id;
export function startup(configuration: IWindowConfiguration): TPromise<void> {
// Ensure others can listen to zoom level changes
@@ -70,30 +72,23 @@ export function startup(configuration: IWindowConfiguration): TPromise<void> {
}
function openWorkbench(configuration: IWindowConfiguration): TPromise<void> {
const mainProcessClient = new ElectronIPCClient(String(`window${currentWindowId}`));
const mainServices = createMainProcessServices(mainProcessClient);
const mainProcessClient = new ElectronIPCClient(String(`window${configuration.windowId}`));
const mainServices = createMainProcessServices(mainProcessClient, configuration);
const environmentService = new EnvironmentService(configuration, configuration.execPath);
const spdlogService = createLogService(`renderer${currentWindowId}`, environmentService);
const consoleLogService = new ConsoleLogService(environmentService);
const logService = new MultiplexLogService([consoleLogService, spdlogService]);
const logService = createLogService(mainProcessClient, configuration, environmentService);
logService.trace('openWorkbench configuration', JSON.stringify(configuration));
// Since the configuration service is one of the core services that is used in so many places, we initialize it
// right before startup of the workbench shell to have its data ready for consumers
return createAndInitializeWorkspaceService(configuration, environmentService).then(workspaceService => {
const timerService = new TimerService((<any>window).MonacoEnvironment.timers as IInitData, workspaceService.getWorkbenchState() === WorkbenchState.EMPTY);
const storageService = createStorageService(workspaceService, environmentService);
timerService.beforeDOMContentLoaded = Date.now();
return domContentLoaded().then(() => {
timerService.afterDOMContentLoaded = Date.now();
// Open Shell
timerService.beforeWorkbenchOpen = Date.now();
perf.mark('willStartWorkbench');
const shell = new WorkbenchShell(document.body, {
contextService: workspaceService,
configurationService: workspaceService,
@@ -189,12 +184,29 @@ function createStorageService(workspaceService: IWorkspaceContextService, enviro
}
const disableStorage = !!environmentService.extensionTestsPath; // never keep any state when running extension tests!
const storage = disableStorage ? inMemoryLocalStorageInstance : window.localStorage;
let storage: IStorage;
if (disableStorage) {
storage = inMemoryLocalStorageInstance;
} else {
// TODO@Ben remove me after a while
perf.mark('willAccessLocalStorage');
storage = window.localStorage;
perf.mark('didAccessLocalStorage');
}
return new StorageService(storage, storage, workspaceId, secondaryWorkspaceId);
}
function createMainProcessServices(mainProcessClient: ElectronIPCClient): ServiceCollection {
function createLogService(mainProcessClient: ElectronIPCClient, configuration: IWindowConfiguration, environmentService: IEnvironmentService): ILogService {
const spdlogService = createSpdLogService(`renderer${configuration.windowId}`, configuration.logLevel, environmentService.logsPath);
const consoleLogService = new ConsoleLogService(configuration.logLevel);
const logService = new MultiplexLogService([consoleLogService, spdlogService]);
const logLevelClient = new LogLevelSetterChannelClient(mainProcessClient.getChannel('loglevel'));
return new FollowerLogService(logLevelClient, logService);
}
function createMainProcessServices(mainProcessClient: ElectronIPCClient, configuration: IWindowConfiguration): ServiceCollection {
const serviceCollection = new ServiceCollection();
const windowsChannel = mainProcessClient.getChannel('windows');
@@ -204,7 +216,10 @@ function createMainProcessServices(mainProcessClient: ElectronIPCClient): Servic
serviceCollection.set(IUpdateService, new SyncDescriptor(UpdateChannelClient, updateChannel));
const urlChannel = mainProcessClient.getChannel('url');
serviceCollection.set(IURLService, new SyncDescriptor(URLChannelClient, urlChannel, currentWindowId));
serviceCollection.set(IURLService, new SyncDescriptor(URLChannelClient, urlChannel, configuration.windowId));
const issueChannel = mainProcessClient.getChannel('issue');
serviceCollection.set(IIssueService, new SyncDescriptor(IssueChannelClient, issueChannel));
const workspacesChannel = mainProcessClient.getChannel('workspaces');
serviceCollection.set(IWorkspacesService, new WorkspacesChannelClient(workspacesChannel));

View File

@@ -124,7 +124,8 @@
outline-style: solid;
}
.monaco-shell .monaco-tree.focused.no-focused-item:focus:before {
.monaco-shell .monaco-tree.focused.no-focused-item:focus:before,
.monaco-shell .monaco-list:not(.element-focused):focus:before {
position: absolute;
top: 0;
left: 0;
@@ -157,7 +158,8 @@
outline: 0 !important; /* outline is not going well with decoration */
}
.monaco-shell .monaco-tree.focused:focus {
.monaco-shell .monaco-tree.focused:focus,
.monaco-shell .monaco-list:focus {
outline: 0 !important; /* tree indicates focus not via outline but through the focused item */
}

View File

@@ -26,4 +26,18 @@
.monaco-workbench.windows .monaco-action-bar .select-box {
margin-top: 7px; /* Center the select box */
}
.monaco-font-aliasing-antialiased {
-webkit-font-smoothing: antialiased;
}
.monaco-font-aliasing-none {
-webkit-font-smoothing: none;
}
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
.monaco-font-aliasing-auto {
-webkit-font-smoothing: antialiased;
}
}

View File

@@ -7,8 +7,8 @@
import 'vs/css!./media/shell';
import * as nls from 'vs/nls';
import * as platform from 'vs/base/common/platform';
import * as perf from 'vs/base/common/performance';
import { Dimension, Builder, $ } from 'vs/base/browser/builder';
import dom = require('vs/base/browser/dom');
import aria = require('vs/base/browser/ui/aria/aria');
@@ -30,12 +30,11 @@ import { ElectronWindow } from 'vs/workbench/electron-browser/window';
import { resolveWorkbenchCommonProperties } from 'vs/platform/telemetry/node/workbenchCommonProperties';
import { IWindowsService, IWindowService, IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { WindowService } from 'vs/platform/windows/electron-browser/windowService';
import { MessageService } from 'vs/workbench/services/message/electron-browser/messageService';
import { IRequestService } from 'vs/platform/request/node/request';
import { RequestService } from 'vs/platform/request/electron-browser/requestService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { SearchService } from 'vs/workbench/services/search/node/searchService';
import { LifecycleService } from 'vs/workbench/services/lifecycle/electron-browser/lifecycleService';
import { LifecycleService } from 'vs/platform/lifecycle/electron-browser/lifecycleService';
import { MarkerService } from 'vs/platform/markers/common/markerService';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
@@ -51,16 +50,14 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { ILifecycleService, LifecyclePhase, ShutdownReason, StartupKind } from 'vs/platform/lifecycle/common/lifecycle';
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IMessageService, IChoiceService, Severity } from 'vs/platform/message/common/message';
import { ChoiceChannel } from 'vs/platform/message/common/messageIpc';
import { ISearchService } from 'vs/platform/search/common/search';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { CommandService } from 'vs/platform/commands/common/commandService';
import { CommandService } from 'vs/workbench/services/commands/common/commandService';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/workbenchModeService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
@@ -71,7 +68,6 @@ import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'v
import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
import { ITimerService } from 'vs/workbench/services/timer/common/timerService';
import { remote } from 'electron';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { restoreFontInfo, readFontInfo, saveFontInfo } from 'vs/editor/browser/config/configuration';
import * as browser from 'vs/base/browser/browser';
@@ -88,6 +84,18 @@ import { IBroadcastService, BroadcastService } from 'vs/platform/broadcast/elect
import { HashService } from 'vs/workbench/services/hash/node/hashService';
import { IHashService } from 'vs/workbench/services/hash/common/hashService';
import { ILogService } from 'vs/platform/log/common/log';
import { WORKBENCH_BACKGROUND } from 'vs/workbench/common/theme';
import { stat } from 'fs';
import { join } from 'path';
import { ILocalizationsChannel, LocalizationsChannelClient } from 'vs/platform/localizations/common/localizationsIpc';
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
import { WorkbenchIssueService } from 'vs/workbench/services/issue/electron-browser/workbenchIssueService';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { NotificationService } from 'vs/workbench/services/notification/common/notificationService';
import { ChoiceChannel } from 'vs/platform/dialogs/common/choiceIpc';
import { IChoiceService, IConfirmationService } from 'vs/platform/dialogs/common/dialogs';
import { DialogService } from 'vs/workbench/services/dialogs/electron-browser/dialogs';
// {{SQL CARBON EDIT}}
import { FileTelemetryService } from 'sql/platform/telemetry/fileTelemetryService';
@@ -104,15 +112,12 @@ export interface ICoreServices {
storageService: IStorageService;
}
const currentWindow = remote.getCurrentWindow();
/**
* The workbench shell contains the workbench with a rich header containing navigation and the activity bar.
* With the Shell being the top level element in the page, it is also responsible for driving the layouting.
*/
export class WorkbenchShell {
private storageService: IStorageService;
private messageService: MessageService;
private environmentService: IEnvironmentService;
private logService: ILogService;
private contextViewService: ContextViewService;
@@ -126,6 +131,7 @@ export class WorkbenchShell {
private themeService: WorkbenchThemeService;
private lifecycleService: LifecycleService;
private mainProcessServices: ServiceCollection;
private notificationService: INotificationService;
private container: HTMLElement;
private toUnbind: IDisposable[];
@@ -167,17 +173,7 @@ export class WorkbenchShell {
const [instantiationService, serviceCollection] = this.initServiceCollection(parent.getHTMLElement());
// Workbench
this.workbench = instantiationService.createInstance(Workbench, parent.getHTMLElement(), workbenchContainer.getHTMLElement(), this.configuration, serviceCollection, this.lifecycleService);
try {
this.workbench.startup().done(startupInfos => this.onWorkbenchStarted(startupInfos, instantiationService));
} catch (error) {
// Log it
this.logService.error(toErrorMessage(error, true));
// Rethrow
throw error;
}
this.workbench = this.createWorkbench(instantiationService, serviceCollection, parent.getHTMLElement(), workbenchContainer.getHTMLElement());
// Window
this.workbench.getInstantiationService().createInstance(ElectronWindow, this.container);
@@ -194,32 +190,50 @@ export class WorkbenchShell {
return workbenchContainer;
}
private onWorkbenchStarted(info: IWorkbenchStartedInfo, instantiationService: IInstantiationService): void {
private createWorkbench(instantiationService: IInstantiationService, serviceCollection: ServiceCollection, parent: HTMLElement, workbenchContainer: HTMLElement): Workbench {
try {
const workbench = instantiationService.createInstance(Workbench, parent, workbenchContainer, this.configuration, serviceCollection, this.lifecycleService);
// Startup Telemetry
this.logStartupTelemetry(info);
// Set lifecycle phase to `Restoring`
this.lifecycleService.phase = LifecyclePhase.Restoring;
// Root Warning
if ((platform.isLinux || platform.isMacintosh) && process.getuid() === 0) {
// {{SQL CARBON EDIT}}
this.messageService.show(Severity.Warning, nls.localize('runningAsRoot', "It is recommended not to run SQL Operations Studio as 'root'."));
}
// Startup Workbench
workbench.startup().done(startupInfos => {
// Set lifecycle phase to `Runnning` so that other contributions can now do something
this.lifecycleService.phase = LifecyclePhase.Running;
// Set lifecycle phase to `Runnning` so that other contributions can now do something
this.lifecycleService.phase = LifecyclePhase.Running;
// Set lifecycle phase to `Runnning For A Bit` after a short delay
let timeoutHandle = setTimeout(() => {
timeoutHandle = void 0;
this.lifecycleService.phase = LifecyclePhase.Eventually;
}, 3000);
this.toUnbind.push({
dispose: () => {
if (timeoutHandle) {
clearTimeout(timeoutHandle);
// Startup Telemetry
this.logStartupTelemetry(startupInfos);
// Set lifecycle phase to `Runnning For A Bit` after a short delay
let eventuallPhaseTimeoutHandle = setTimeout(() => {
eventuallPhaseTimeoutHandle = void 0;
this.lifecycleService.phase = LifecyclePhase.Eventually;
}, 3000);
this.toUnbind.push({
dispose: () => {
if (eventuallPhaseTimeoutHandle) {
clearTimeout(eventuallPhaseTimeoutHandle);
}
}
});
// localStorage metrics (TODO@Ben remove me later)
if (!this.environmentService.extensionTestsPath && this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) {
this.logLocalStorageMetrics();
}
}
});
});
return workbench;
} catch (error) {
// Log it
this.logService.error(toErrorMessage(error, true));
// Rethrow
throw error;
}
}
private logStartupTelemetry(info: IWorkbenchStartedInfo): void {
@@ -264,9 +278,7 @@ export class WorkbenchShell {
});
// Telemetry: startup metrics
this.timerService.workbenchStarted = Date.now();
this.timerService.restoreEditorsDuration = info.restoreEditorsDuration;
this.timerService.restoreViewletDuration = info.restoreViewletDuration;
perf.mark('didStartWorkbench');
this.extensionService.whenInstalledExtensionsRegistered().done(() => {
/* __GDPR__
"startupTime" : {
@@ -279,15 +291,60 @@ export class WorkbenchShell {
});
}
private initServiceCollection(container: HTMLElement): [IInstantiationService, ServiceCollection] {
const disposables: IDisposable[] = [];
private logLocalStorageMetrics(): void {
if (this.lifecycleService.startupKind === StartupKind.ReloadedWindow || this.lifecycleService.startupKind === StartupKind.ReopenedWindow) {
return; // avoid logging localStorage metrics for reload/reopen, we prefer cold startup numbers
}
perf.mark('willReadLocalStorage');
const readyToSend = this.storageService.getBoolean('localStorageMetricsReadyToSend2');
perf.mark('didReadLocalStorage');
if (!readyToSend) {
this.storageService.store('localStorageMetricsReadyToSend2', true);
return; // avoid logging localStorage metrics directly after the update, we prefer cold startup numbers
}
if (!this.storageService.getBoolean('localStorageMetricsSent2')) {
perf.mark('willWriteLocalStorage');
this.storageService.store('localStorageMetricsSent2', true);
perf.mark('didWriteLocalStorage');
perf.mark('willStatLocalStorage');
stat(join(this.environmentService.userDataPath, 'Local Storage', 'file__0.localstorage'), (error, stat) => {
perf.mark('didStatLocalStorage');
/* __GDPR__
"localStorageTimers" : {
"statTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"accessTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"firstReadTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"subsequentReadTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"writeTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"keys" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"size": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('localStorageTimers2', {
'statTime': perf.getDuration('willStatLocalStorage', 'didStatLocalStorage'),
'accessTime': perf.getDuration('willAccessLocalStorage', 'didAccessLocalStorage'),
'firstReadTime': perf.getDuration('willReadWorkspaceIdentifier', 'didReadWorkspaceIdentifier'),
'subsequentReadTime': perf.getDuration('willReadLocalStorage', 'didReadLocalStorage'),
'writeTime': perf.getDuration('willWriteLocalStorage', 'didWriteLocalStorage'),
'keys': window.localStorage.length,
'size': stat ? stat.size : -1
});
});
}
}
private initServiceCollection(container: HTMLElement): [IInstantiationService, ServiceCollection] {
const serviceCollection = new ServiceCollection();
serviceCollection.set(IWorkspaceContextService, this.contextService);
serviceCollection.set(IConfigurationService, this.configurationService);
serviceCollection.set(IEnvironmentService, this.environmentService);
serviceCollection.set(ILogService, this.logService);
disposables.push(this.logService);
this.toUnbind.push(this.logService);
serviceCollection.set(ITimerService, this.timerService);
serviceCollection.set(IStorageService, this.storageService);
@@ -297,13 +354,16 @@ export class WorkbenchShell {
const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
this.broadcastService = new BroadcastService(currentWindow.id);
this.notificationService = new NotificationService();
serviceCollection.set(INotificationService, this.notificationService);
this.broadcastService = instantiationService.createInstance(BroadcastService, this.configuration.windowId);
serviceCollection.set(IBroadcastService, this.broadcastService);
serviceCollection.set(IWindowService, new SyncDescriptor(WindowService, currentWindow.id, this.configuration));
serviceCollection.set(IWindowService, new SyncDescriptor(WindowService, this.configuration.windowId, this.configuration));
const sharedProcess = (<IWindowsService>serviceCollection.get(IWindowsService)).whenSharedProcessReady()
.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${currentWindow.id}`));
.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${this.configuration.windowId}`));
sharedProcess
.done(client => client.registerChannel('choice', instantiationService.createInstance(ChoiceChannel)));
@@ -339,13 +399,13 @@ export class WorkbenchShell {
const errorTelemetry = new ErrorTelemetry(telemetryService);
disposables.push(telemetryService, errorTelemetry);
this.toUnbind.push(telemetryService, errorTelemetry);
} else {
this.telemetryService = NullTelemetryService;
}
serviceCollection.set(ITelemetryService, this.telemetryService);
disposables.push(configurationTelemetry(this.telemetryService, this.configurationService));
this.toUnbind.push(configurationTelemetry(this.telemetryService, this.configurationService));
let crashReporterService = NullCrashReporterService;
if (!this.environmentService.disableCrashReporter && product.crashReporter && product.hockeyApp) {
@@ -353,13 +413,12 @@ export class WorkbenchShell {
}
serviceCollection.set(ICrashReporterService, crashReporterService);
this.messageService = instantiationService.createInstance(MessageService, container);
serviceCollection.set(IMessageService, this.messageService);
serviceCollection.set(IChoiceService, this.messageService);
const dialog = instantiationService.createInstance(DialogService);
serviceCollection.set(IChoiceService, dialog);
serviceCollection.set(IConfirmationService, dialog);
const lifecycleService = instantiationService.createInstance(LifecycleService);
this.toUnbind.push(lifecycleService.onShutdown(reason => dispose(disposables)));
this.toUnbind.push(lifecycleService.onShutdown(reason => saveFontInfo(this.storageService)));
this.toUnbind.push(lifecycleService.onShutdown(reason => this.dispose(reason)));
serviceCollection.set(ILifecycleService, lifecycleService);
this.lifecycleService = lifecycleService;
@@ -368,14 +427,14 @@ export class WorkbenchShell {
const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
disposables.push(extensionEnablementService);
this.toUnbind.push(extensionEnablementService);
this.extensionService = instantiationService.createInstance(ExtensionService);
serviceCollection.set(IExtensionService, this.extensionService);
this.timerService.beforeExtensionLoad = Date.now();
perf.mark('willLoadExtensions');
this.extensionService.whenInstalledExtensionsRegistered().done(() => {
this.timerService.afterExtensionLoad = Date.now();
perf.mark('didLoadExtensions');
});
this.themeService = instantiationService.createInstance(WorkbenchThemeService, document.body);
@@ -404,10 +463,15 @@ export class WorkbenchShell {
serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
serviceCollection.set(IWorkbenchIssueService, new SyncDescriptor(WorkbenchIssueService));
serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
serviceCollection.set(IIntegrityService, new SyncDescriptor(IntegrityServiceImpl));
const localizationsChannel = getDelayedChannel<ILocalizationsChannel>(sharedProcess.then(c => c.getChannel('localizations')));
serviceCollection.set(ILocalizationsService, new SyncDescriptor(LocalizationsChannelClient, localizationsChannel));
return [instantiationService, serviceCollection];
}
@@ -458,8 +522,8 @@ export class WorkbenchShell {
this.logService.error(errorMsg);
// Show to user if friendly message provided
if (error && error.friendlyMessage && this.messageService) {
this.messageService.show(Severity.Error, error.friendlyMessage);
if (error && error.friendlyMessage && this.notificationService) {
this.notificationService.error(error.friendlyMessage);
}
}
@@ -473,20 +537,18 @@ export class WorkbenchShell {
this.workbench.layout();
}
public dispose(): void {
public dispose(reason = ShutdownReason.QUIT): void {
// Workbench
if (this.workbench) {
this.workbench.dispose();
}
this.contextViewService.dispose();
// Listeners
// Dispose bindings
this.toUnbind = dispose(this.toUnbind);
// Container
$(this.container).empty();
// Keep font info for next startup around
saveFontInfo(this.storageService);
// Dispose Workbench
if (this.workbench) {
this.workbench.dispose(reason);
}
}
}
@@ -523,17 +585,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
}
// We need to set the workbench background color so that on Windows we get subpixel-antialiasing.
let workbenchBackground: string;
switch (theme.type) {
case 'dark':
workbenchBackground = '#252526';
break;
case 'light':
workbenchBackground = '#F3F3F3';
break;
default:
workbenchBackground = '#000000';
}
const workbenchBackground = WORKBENCH_BACKGROUND(theme);
collector.addRule(`.monaco-workbench { background-color: ${workbenchBackground}; }`);
// Scrollbars
@@ -585,18 +637,19 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const focusOutline = theme.getColor(focusBorder);
if (focusOutline) {
collector.addRule(`
.monaco-shell [tabindex="0"]:focus,
.monaco-shell .synthetic-focus,
.monaco-shell select:focus,
.monaco-shell .monaco-tree.focused.no-focused-item:focus:before,
.monaco-shell input[type="button"]:focus,
.monaco-shell input[type="text"]:focus,
.monaco-shell button:focus,
.monaco-shell textarea:focus,
.monaco-shell input[type="search"]:focus,
.monaco-shell input[type="checkbox"]:focus {
outline-color: ${focusOutline};
}
.monaco-shell [tabindex="0"]:focus,
.monaco-shell .synthetic-focus,
.monaco-shell select:focus,
.monaco-shell .monaco-tree.focused.no-focused-item:focus:before,
.monaco-shell .monaco-list:not(.element-focused):focus:before,
.monaco-shell input[type="button"]:focus,
.monaco-shell input[type="text"]:focus,
.monaco-shell button:focus,
.monaco-shell textarea:focus,
.monaco-shell input[type="search"]:focus,
.monaco-shell input[type="checkbox"]:focus {
outline-color: ${focusOutline};
}
`);
}
});

View File

@@ -6,7 +6,6 @@
'use strict';
import nls = require('vs/nls');
import platform = require('vs/base/common/platform');
import URI from 'vs/base/common/uri';
import errors = require('vs/base/common/errors');
import types = require('vs/base/common/types');
@@ -14,14 +13,12 @@ import { TPromise } from 'vs/base/common/winjs.base';
import arrays = require('vs/base/common/arrays');
import objects = require('vs/base/common/objects');
import DOM = require('vs/base/browser/dom');
import Severity from 'vs/base/common/severity';
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { IAction, Action } from 'vs/base/common/actions';
import { AutoSaveConfiguration, IFileService } from 'vs/platform/files/common/files';
import { toResource } from 'vs/workbench/common/editor';
import { IWorkbenchEditorService, IResourceInputType } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
import { IMessageService } from 'vs/platform/message/common/message';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
import { IWindowsService, IWindowService, IWindowSettings, IPath, IOpenFileRequest, IWindowsConfiguration, IAddFoldersRequest, IRunActionInWindowRequest } from 'vs/platform/windows/common/windows';
@@ -33,7 +30,7 @@ import * as browser from 'vs/base/browser/browser';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { Position, IResourceInput, IUntitledResourceInput, IEditor } from 'vs/platform/editor/common/editor';
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/keybindingService';
import { Themable } from 'vs/workbench/common/theme';
import { ipcRenderer as ipc, webFrame } from 'electron';
@@ -46,6 +43,10 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { LifecyclePhase, ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces';
import { IIntegrityService } from 'vs/platform/integrity/common/integrity';
import { AccessibilitySupport, isRootUser, isWindows, isMacintosh } from 'vs/base/common/platform';
import product from 'vs/platform/node/product';
import { INotificationService } from 'vs/platform/notification/common/notification';
const TextInputActions: IAction[] = [
new Action('undo', nls.localize('undo', "Undo"), null, true, () => document.execCommand('undo') && TPromise.as(true)),
@@ -81,7 +82,7 @@ export class ElectronWindow extends Themable {
@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService,
@ITitleService private titleService: ITitleService,
@IWorkbenchThemeService protected themeService: IWorkbenchThemeService,
@IMessageService private messageService: IMessageService,
@INotificationService private notificationService: INotificationService,
@ICommandService private commandService: ICommandService,
@IExtensionService private extensionService: IExtensionService,
@IViewletService private viewletService: IViewletService,
@@ -91,7 +92,8 @@ export class ElectronWindow extends Themable {
@IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService,
@IFileService private fileService: IFileService,
@IMenuService private menuService: IMenuService,
@ILifecycleService private lifecycleService: ILifecycleService
@ILifecycleService private lifecycleService: ILifecycleService,
@IIntegrityService private integrityService: IIntegrityService
) {
super(themeService);
@@ -155,7 +157,7 @@ export class ElectronWindow extends Themable {
*/
this.telemetryService.publicLog('commandExecuted', { id: request.id, from: request.from });
}, err => {
this.messageService.show(Severity.Error, err);
this.notificationService.error(err);
});
});
@@ -192,7 +194,7 @@ export class ElectronWindow extends Themable {
// Message support
ipc.on('vscode:showInfoMessage', (_event: any, message: string) => {
this.messageService.show(Severity.Info, message);
this.notificationService.info(message);
});
// Support toggling auto save
@@ -239,7 +241,7 @@ export class ElectronWindow extends Themable {
// keyboard layout changed event
ipc.on('vscode:accessibilitySupportChanged', (_event: any, accessibilitySupportEnabled: boolean) => {
browser.setAccessibilitySupport(accessibilitySupportEnabled ? platform.AccessibilitySupport.Enabled : platform.AccessibilitySupport.Disabled);
browser.setAccessibilitySupport(accessibilitySupportEnabled ? AccessibilitySupport.Enabled : AccessibilitySupport.Disabled);
});
// Zoom level changes
@@ -270,7 +272,6 @@ export class ElectronWindow extends Themable {
}
private updateWindowZoomLevel(): void {
const windowConfig: IWindowsConfiguration = this.configurationService.getValue<IWindowsConfiguration>();
let newZoomLevel = 0;
@@ -317,13 +318,42 @@ export class ElectronWindow extends Themable {
// Touchbar Support
this.updateTouchbarMenu();
// Integrity warning
this.integrityService.isPure().then(res => this.titleService.updateProperties({ isPure: res.isPure }));
// Root warning
this.lifecycleService.when(LifecyclePhase.Running).then(() => {
let isAdminPromise: Promise<boolean>;
if (isWindows) {
isAdminPromise = import('native-is-elevated').then(isElevated => isElevated());
} else {
isAdminPromise = Promise.resolve(isRootUser());
}
return isAdminPromise.then(isAdmin => {
// Update title
this.titleService.updateProperties({ isAdmin });
// Show warning message (unix only)
if (isAdmin && !isWindows) {
this.notificationService.warn(nls.localize('runningAsRoot', "It is not recommended to run {0} as root user.", product.nameShort));
}
});
});
}
private updateTouchbarMenu(): void {
if (!platform.isMacintosh) {
if (!isMacintosh) {
return; // macOS only
}
const touchbarEnabled = this.configurationService.getValue<boolean>('keyboard.touchbar.enabled');
if (!touchbarEnabled) {
return; // disabled via setting
}
// Dispose old
this.touchBarDisposables = dispose(this.touchBarDisposables);
@@ -345,7 +375,7 @@ export class ElectronWindow extends Themable {
const actions: (MenuItemAction | Separator)[] = [];
// Fill actions into groups respecting order
fillInActions(this.touchBarMenu, void 0, actions);
fillInActions(this.touchBarMenu, void 0, actions, this.contextMenuService);
// Convert into command action multi array
const items: ICommandAction[][] = [];

View File

@@ -15,8 +15,7 @@ import DOM = require('vs/base/browser/dom');
import { Builder, $ } from 'vs/base/browser/builder';
import { Delayer, RunOnceScheduler } from 'vs/base/common/async';
import * as browser from 'vs/base/browser/browser';
import { StopWatch } from 'vs/base/common/stopwatch';
import { time } from 'vs/base/common/performance';
import * as perf from 'vs/base/common/performance';
import errors = require('vs/base/common/errors');
import { BackupFileService } from 'vs/workbench/services/backup/node/backupFileService';
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
@@ -59,7 +58,6 @@ import { IConfigurationResolverService } from 'vs/workbench/services/configurati
import { ConfigurationResolverService } from 'vs/workbench/services/configurationResolver/electron-browser/configurationResolverService';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { ITitleService } from 'vs/workbench/services/title/common/titleService';
import { WorkbenchMessageService } from 'vs/workbench/services/message/browser/messageService';
import { IWorkbenchEditorService, IResourceInputType, WorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
@@ -77,17 +75,16 @@ import { ProgressService2 } from 'vs/workbench/services/progress/browser/progres
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { ShutdownReason, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { LifecycleService } from 'vs/workbench/services/lifecycle/electron-browser/lifecycleService';
import { ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle';
import { LifecycleService } from 'vs/platform/lifecycle/electron-browser/lifecycleService';
import { IWindowService, IWindowConfiguration as IWindowSettings, IWindowConfiguration, IPath } from 'vs/platform/windows/common/windows';
import { IMessageService } from 'vs/platform/message/common/message';
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
import { IMenuService, SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { MenuService } from 'vs/platform/actions/common/menuService';
import { MenuService } from 'vs/workbench/services/actions/common/menuService';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
import { OpenRecentAction, ToggleDevToolsAction, ReloadWindowAction, ShowPreviousWindowTab, MoveWindowTabToNewWindow, MergeAllWindowTabs, ShowNextWindowTab, ToggleWindowTabsBar } from 'vs/workbench/electron-browser/actions';
import { OpenRecentAction, ToggleDevToolsAction, ReloadWindowAction, ShowPreviousWindowTab, MoveWindowTabToNewWindow, MergeAllWindowTabs, ShowNextWindowTab, ToggleWindowTabsBar, ReloadWindowWithExtensionsDisabledAction } from 'vs/workbench/electron-browser/actions';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
import { WorkspaceEditingService } from 'vs/workbench/services/workspace/node/workspaceEditingService';
@@ -98,6 +95,16 @@ import URI from 'vs/base/common/uri';
import { IListService, ListService } from 'vs/platform/list/browser/listService';
import { domEvent } from 'vs/base/browser/event';
import { InputFocusedContext } from 'vs/platform/workbench/common/contextkeys';
import { ICustomViewsService } from 'vs/workbench/common/views';
import { CustomViewsService } from 'vs/workbench/browser/parts/views/customView';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { NotificationService } from 'vs/workbench/services/notification/common/notificationService';
import { NotificationsCenter } from 'vs/workbench/browser/parts/notifications/notificationsCenter';
import { NotificationsAlerts } from 'vs/workbench/browser/parts/notifications/notificationsAlerts';
import { NotificationsStatus } from 'vs/workbench/browser/parts/notifications/notificationsStatus';
import { registerNotificationCommands } from 'vs/workbench/browser/parts/notifications/notificationsCommands';
import { NotificationsToasts } from 'vs/workbench/browser/parts/notifications/notificationsToasts';
// {{SQL CARBON EDIT}}
import { IConnectionManagementService, IConnectionDialogService, IErrorMessageService, IServerGroupController } from 'sql/parts/connection/common/connectionManagement';
@@ -152,7 +159,6 @@ import { DashboardWebviewService } from 'sql/services/dashboardWebview/common/da
import { IDashboardService } from 'sql/services/dashboard/common/dashboardService';
import { DashboardService } from 'sql/services/dashboard/common/dashboardServiceImpl';
export const MessagesVisibleContext = new RawContextKey<boolean>('globalMessageVisible', false);
export const EditorsVisibleContext = new RawContextKey<boolean>('editorIsOpen', false);
export const InZenModeContext = new RawContextKey<boolean>('inZenMode', false);
export const SidebarVisibleContext = new RawContextKey<boolean>('sidebarVisible', false);
@@ -165,6 +171,7 @@ interface WorkbenchParams {
interface IZenModeSettings {
fullScreen: boolean;
centerLayout: boolean;
hideTabs: boolean;
hideActivityBar: boolean;
hideStatusBar: boolean;
@@ -173,13 +180,13 @@ interface IZenModeSettings {
export interface IWorkbenchStartedInfo {
customKeybindingsCount: number;
restoreViewletDuration: number;
restoreEditorsDuration: number;
pinnedViewlets: string[];
restoredViewlet: string;
restoredEditors: string[];
}
type FontAliasingOption = 'default' | 'antialiased' | 'none' | 'auto';
const Identifiers = {
WORKBENCH_CONTAINER: 'workbench.main.container',
TITLEBAR_PART: 'workbench.parts.titlebar',
@@ -207,7 +214,9 @@ export class Workbench implements IPartService {
private static readonly sidebarRestoreStorageKey = 'workbench.sidebar.restore';
private static readonly panelHiddenStorageKey = 'workbench.panel.hidden';
private static readonly zenModeActiveStorageKey = 'workbench.zenmode.active';
private static readonly centeredEditorLayoutActiveStorageKey = 'workbench.centerededitorlayout.active';
private static readonly panelPositionStorageKey = 'workbench.panel.location';
private static readonly defaultPanelPositionStorageKey = 'workbench.panel.defaultLocation';
private static readonly sidebarPositionConfigurationKey = 'workbench.sideBar.location';
private static readonly statusbarVisibleConfigurationKey = 'workbench.statusBar.visible';
@@ -242,26 +251,28 @@ export class Workbench implements IPartService {
private editorPart: EditorPart;
private statusbarPart: StatusbarPart;
private quickOpen: QuickOpenController;
private notificationsCenter: NotificationsCenter;
private notificationsToasts: NotificationsToasts;
private workbenchLayout: WorkbenchLayout;
private toDispose: IDisposable[];
private toShutdown: { shutdown: () => void; }[];
private toUnbind: IDisposable[];
private sideBarHidden: boolean;
private statusBarHidden: boolean;
private activityBarHidden: boolean;
private sideBarPosition: Position;
private panelPosition: Position;
private panelHidden: boolean;
private editorBackgroundDelayer: Delayer<void>;
private editorBackgroundDelayer: Delayer<any>;
private closeEmptyWindowScheduler: RunOnceScheduler;
private messagesVisibleContext: IContextKey<boolean>;
private editorsVisibleContext: IContextKey<boolean>;
private inZenMode: IContextKey<boolean>;
private sideBarVisibleContext: IContextKey<boolean>;
private hasFilesToCreateOpenOrDiff: boolean;
private fontAliasing: string;
private fontAliasing: FontAliasingOption;
private centeredEditorLayoutActive: boolean;
private zenMode: {
active: boolean;
transitionedToFullScreen: boolean;
transitionedToCenteredEditorLayout: boolean;
wasSideBarVisible: boolean;
wasPanelVisible: boolean;
};
@@ -275,10 +286,10 @@ export class Workbench implements IPartService {
@IInstantiationService private instantiationService: IInstantiationService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IStorageService private storageService: IStorageService,
@IMessageService private messageService: IMessageService,
@IConfigurationService private configurationService: WorkspaceService,
@IEnvironmentService private environmentService: IEnvironmentService,
@IWindowService private windowService: IWindowService
@IWindowService private windowService: IWindowService,
@INotificationService private notificationService: NotificationService
) {
this.parent = parent;
this.container = container;
@@ -293,8 +304,7 @@ export class Workbench implements IPartService {
(configuration.filesToOpen && configuration.filesToOpen.length > 0) ||
(configuration.filesToDiff && configuration.filesToDiff.length > 0);
this.toDispose = [];
this.toShutdown = [];
this.toUnbind = [];
this.editorBackgroundDelayer = new Delayer<void>(50);
this.closeEmptyWindowScheduler = new RunOnceScheduler(() => this.onAllEditorsClosed(), 50);
@@ -327,14 +337,13 @@ export class Workbench implements IPartService {
this.initServices();
// Contexts
this.messagesVisibleContext = MessagesVisibleContext.bindTo(this.contextKeyService);
this.editorsVisibleContext = EditorsVisibleContext.bindTo(this.contextKeyService);
this.inZenMode = InZenModeContext.bindTo(this.contextKeyService);
this.sideBarVisibleContext = SidebarVisibleContext.bindTo(this.contextKeyService);
const inputFocused = InputFocusedContext.bindTo(this.contextKeyService);
const onWindowsFocusIn = domEvent(window, 'focusin', true);
onWindowsFocusIn(() => inputFocused.set(document.activeElement && (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA')), null, this.toDispose);
onWindowsFocusIn(() => inputFocused.set(document.activeElement && (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA')), null, this.toUnbind);
// Set workbench state context
const WorkbenchStateContext = new RawContextKey<string>('workbenchState', getWorkbenchStateString(this.configurationService.getWorkbenchState()));
@@ -343,8 +352,8 @@ export class Workbench implements IPartService {
const WorkspaceFolderCountContext = new RawContextKey<number>('workspaceFolderCount', this.configurationService.getWorkspace().folders.length);
const workspaceFolderCountContext = WorkspaceFolderCountContext.bindTo(this.contextKeyService);
this.toDispose.push(this.configurationService.onDidChangeWorkbenchState(() => workbenchStateContext.set(getWorkbenchStateString(this.configurationService.getWorkbenchState()))));
this.toDispose.push(this.configurationService.onDidChangeWorkspaceFolders(() => workspaceFolderCountContext.set(this.configurationService.getWorkspace().folders.length)));
this.toUnbind.push(this.configurationService.onDidChangeWorkbenchState(() => workbenchStateContext.set(getWorkbenchStateString(this.configurationService.getWorkbenchState()))));
this.toUnbind.push(this.configurationService.onDidChangeWorkspaceFolders(() => workspaceFolderCountContext.set(this.configurationService.getWorkspace().folders.length)));
// Register Listeners
this.registerListeners();
@@ -374,11 +383,9 @@ export class Workbench implements IPartService {
const restorePromises: TPromise<any>[] = [];
// Restore Editors
const editorRestoreStopWatch = StopWatch.create();
const editorRestoreClock = time('restore:editors');
perf.mark('willRestoreEditors');
const restoredEditors: string[] = [];
restorePromises.push(this.resolveEditorsToOpen().then(inputs => {
let editorOpenPromise: TPromise<IEditor[]>;
if (inputs.length) {
editorOpenPromise = this.editorService.openEditors(inputs.map(input => { return { input, position: EditorPosition.ONE }; }));
@@ -386,14 +393,10 @@ export class Workbench implements IPartService {
editorOpenPromise = this.editorPart.restoreEditors();
}
// update lifecycle *after* triggering the editor restore
this.lifecycleService.phase = LifecyclePhase.Restoring;
return editorOpenPromise.then(editors => {
this.handleEditorBackground(); // make sure we show the proper background in the editor area
editorRestoreClock.stop();
editorRestoreStopWatch.stop();
perf.mark('didRestoreEditors');
for (const editor of editors) {
if (editor) {
@@ -408,7 +411,6 @@ export class Workbench implements IPartService {
}));
// Restore Sidebar
let viewletRestoreStopWatch: StopWatch;
let viewletIdToRestore: string;
if (!this.sideBarHidden) {
this.sideBarVisibleContext.set(true);
@@ -421,11 +423,9 @@ export class Workbench implements IPartService {
viewletIdToRestore = this.viewletService.getDefaultViewletId();
}
viewletRestoreStopWatch = StopWatch.create();
const viewletRestoreClock = time('restore:viewlet');
perf.mark('willRestoreViewlet');
restorePromises.push(this.viewletService.openViewlet(viewletIdToRestore).then(() => {
viewletRestoreStopWatch.stop();
viewletRestoreClock.stop();
perf.mark('didRestoreViewlet');
}));
}
@@ -441,6 +441,11 @@ export class Workbench implements IPartService {
this.toggleZenMode(true);
}
// Restore Forced Editor Center Mode
if (this.storageService.getBoolean(Workbench.centeredEditorLayoutActiveStorageKey, StorageScope.GLOBAL, false)) {
this.centeredEditorLayoutActive = true;
}
const onRestored = (error?: Error): IWorkbenchStartedInfo => {
this.workbenchCreated = true;
@@ -450,8 +455,6 @@ export class Workbench implements IPartService {
return {
customKeybindingsCount: this.keybindingService.customKeybindingsCount(),
restoreViewletDuration: viewletRestoreStopWatch ? Math.round(viewletRestoreStopWatch.elapsed()) : 0,
restoreEditorsDuration: Math.round(editorRestoreStopWatch.elapsed()),
pinnedViewlets: this.activitybarPart.getPinned(),
restoredViewlet: viewletIdToRestore,
restoredEditors
@@ -469,7 +472,7 @@ export class Workbench implements IPartService {
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ReloadWindowAction, ReloadWindowAction.ID, ReloadWindowAction.LABEL, isDeveloping ? { primary: KeyMod.CtrlCmd | KeyCode.KEY_R } : void 0), 'Reload Window');
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleDevToolsAction, ToggleDevToolsAction.ID, ToggleDevToolsAction.LABEL, isDeveloping ? { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_I, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_I } } : void 0), 'Developer: Toggle Developer Tools', localize('developer', "Developer"));
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenRecentAction, OpenRecentAction.ID, OpenRecentAction.LABEL, { primary: isDeveloping ? null : KeyMod.CtrlCmd | KeyCode.KEY_R, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_R } }), 'File: Open Recent...', localize('file', "File"));
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ReloadWindowWithExtensionsDisabledAction, ReloadWindowWithExtensionsDisabledAction.ID, ReloadWindowWithExtensionsDisabledAction.LABEL), 'Reload Window Without Extensions');
// Actions for macOS native tabs management (only when enabled)
const windowConfig = this.configurationService.getValue<IWindowConfiguration>();
if (windowConfig && windowConfig.window && windowConfig.window.nativeTabs) {
@@ -564,8 +567,6 @@ export class Workbench implements IPartService {
private initServices(): void {
const { serviceCollection } = this.workbenchParams;
this.toDispose.push(this.lifecycleService.onShutdown(this.shutdownComponents, this));
// Services we contribute
serviceCollection.set(IPartService, this);
@@ -574,8 +575,7 @@ export class Workbench implements IPartService {
// Status bar
this.statusbarPart = this.instantiationService.createInstance(StatusbarPart, Identifiers.STATUSBAR_PART);
this.toDispose.push(this.statusbarPart);
this.toShutdown.push(this.statusbarPart);
this.toUnbind.push({ dispose: () => this.statusbarPart.shutdown() });
serviceCollection.set(IStatusbarService, this.statusbarPart);
// Progress 2
@@ -599,8 +599,7 @@ export class Workbench implements IPartService {
// Sidebar part
this.sidebarPart = this.instantiationService.createInstance(SidebarPart, Identifiers.SIDEBAR_PART);
this.toDispose.push(this.sidebarPart);
this.toShutdown.push(this.sidebarPart);
this.toUnbind.push({ dispose: () => this.sidebarPart.shutdown() });
// Viewlet service
this.viewletService = this.instantiationService.createInstance(ViewletService, this.sidebarPart);
@@ -608,34 +607,34 @@ export class Workbench implements IPartService {
// Panel service (panel part)
this.panelPart = this.instantiationService.createInstance(PanelPart, Identifiers.PANEL_PART);
this.toDispose.push(this.panelPart);
this.toShutdown.push(this.panelPart);
this.toUnbind.push({ dispose: () => this.panelPart.shutdown() });
serviceCollection.set(IPanelService, this.panelPart);
// Custom views service
const customViewsService = this.instantiationService.createInstance(CustomViewsService);
serviceCollection.set(ICustomViewsService, customViewsService);
// Activity service (activitybar part)
this.activitybarPart = this.instantiationService.createInstance(ActivitybarPart, Identifiers.ACTIVITYBAR_PART);
this.toDispose.push(this.activitybarPart);
this.toShutdown.push(this.activitybarPart);
this.toUnbind.push({ dispose: () => this.activitybarPart.shutdown() });
const activityService = this.instantiationService.createInstance(ActivityService, this.activitybarPart, this.panelPart);
serviceCollection.set(IActivityService, activityService);
// File Service
this.fileService = this.instantiationService.createInstance(RemoteFileService);
serviceCollection.set(IFileService, this.fileService);
this.toDispose.push(this.fileService.onFileChanges(e => this.configurationService.handleWorkspaceFileEvents(e)));
this.toUnbind.push(this.fileService.onFileChanges(e => this.configurationService.handleWorkspaceFileEvents(e)));
// Editor service (editor part)
this.editorPart = this.instantiationService.createInstance(EditorPart, Identifiers.EDITOR_PART, !this.hasFilesToCreateOpenOrDiff);
this.toDispose.push(this.editorPart);
this.toShutdown.push(this.editorPart);
this.toUnbind.push({ dispose: () => this.editorPart.shutdown() });
this.editorService = this.instantiationService.createInstance(WorkbenchEditorService, this.editorPart);
serviceCollection.set(IWorkbenchEditorService, this.editorService);
serviceCollection.set(IEditorGroupService, this.editorPart);
// Title bar
this.titlebarPart = this.instantiationService.createInstance(TitlebarPart, Identifiers.TITLEBAR_PART);
this.toDispose.push(this.titlebarPart);
this.toShutdown.push(this.titlebarPart);
this.toUnbind.push({ dispose: () => this.titlebarPart.shutdown() });
serviceCollection.set(ITitleService, this.titlebarPart);
// History
@@ -672,8 +671,7 @@ export class Workbench implements IPartService {
// Quick open service (quick open controller)
this.quickOpen = this.instantiationService.createInstance(QuickOpenController);
this.toDispose.push(this.quickOpen);
this.toShutdown.push(this.quickOpen);
this.toUnbind.push({ dispose: () => this.quickOpen.shutdown() });
serviceCollection.set(IQuickOpenService, this.quickOpen);
// {{SQL CARBON EDIT}}
@@ -717,10 +715,9 @@ export class Workbench implements IPartService {
serviceCollection.set(IBootstrapService, this.instantiationService.createInstance(BootstrapService));
serviceCollection.set(IProfilerService, this.instantiationService.createInstance(ProfilerService));
this.toDispose.push(connectionManagementService);
this.toShutdown.push(connectionManagementService);
this.toShutdown.push(accountManagementService);
this.toShutdown.push(capabilitiesService);
this.toUnbind.push({ dispose: () => connectionManagementService.shutdown() });
this.toUnbind.push({ dispose: () => accountManagementService.shutdown() });
this.toUnbind.push({ dispose: () => capabilitiesService.shutdown() });
// Contributed services
const contributedServices = getServices();
@@ -755,8 +752,7 @@ export class Workbench implements IPartService {
this.sideBarPosition = (sideBarPosition === 'right') ? Position.RIGHT : Position.LEFT;
// Panel position
const panelPosition = this.storageService.get(Workbench.panelPositionStorageKey, StorageScope.WORKSPACE, 'bottom');
this.panelPosition = (panelPosition === 'right') ? Position.RIGHT : Position.BOTTOM;
this.setPanelPositionFromStorageOrConfig();
// Statusbar visibility
const statusBarVisible = this.configurationService.getValue<string>(Workbench.statusbarVisibleConfigurationKey);
@@ -767,15 +763,25 @@ export class Workbench implements IPartService {
this.activityBarHidden = !activityBarVisible;
// Font aliasing
this.fontAliasing = this.configurationService.getValue<string>(Workbench.fontAliasingConfigurationKey);
this.fontAliasing = this.configurationService.getValue<FontAliasingOption>(Workbench.fontAliasingConfigurationKey);
// Zen mode
this.zenMode = {
active: false,
transitionedToFullScreen: false,
transitionedToCenteredEditorLayout: false,
wasSideBarVisible: false,
wasPanelVisible: false
};
// Centered Editor Layout
this.centeredEditorLayoutActive = false;
}
private setPanelPositionFromStorageOrConfig() {
const defaultPanelPosition = this.configurationService.getValue<string>(Workbench.defaultPanelPositionStorageKey);
const panelPosition = this.storageService.get(Workbench.panelPositionStorageKey, StorageScope.WORKSPACE, defaultPanelPosition);
this.panelPosition = (panelPosition === 'right') ? Position.RIGHT : Position.BOTTOM;
}
/**
@@ -886,6 +892,12 @@ export class Workbench implements IPartService {
private setStatusBarHidden(hidden: boolean, skipLayout?: boolean): void {
this.statusBarHidden = hidden;
// Adjust CSS
if (hidden) {
this.workbench.addClass('nostatusbar');
} else {
this.workbench.removeClass('nostatusbar');
}
// Layout
if (!skipLayout) {
@@ -896,7 +908,6 @@ export class Workbench implements IPartService {
public setActivityBarHidden(hidden: boolean, skipLayout?: boolean): void {
this.activityBarHidden = hidden;
// Layout
if (!skipLayout) {
this.workbenchLayout.layout();
@@ -1059,32 +1070,20 @@ export class Workbench implements IPartService {
});
}
private setFontAliasing(aliasing: string) {
private setFontAliasing(aliasing: FontAliasingOption) {
this.fontAliasing = aliasing;
document.body.style['-webkit-font-smoothing'] = (aliasing === 'default' ? '' : aliasing);
}
public dispose(): void {
if (this.isStarted()) {
this.shutdownComponents();
this.workbenchShutdown = true;
}
this.toDispose = dispose(this.toDispose);
}
/**
* Asks the workbench and all its UI components inside to lay out according to
* the containers dimension the workbench is living in.
*/
public layout(options?: ILayoutOptions): void {
if (this.isStarted()) {
this.workbenchLayout.layout(options);
const fontAliasingClassNames = [
'monaco-font-aliasing-antialiased',
'monaco-font-aliasing-none',
'monaco-font-aliasing-auto'
];
document.body.classList.remove(...fontAliasingClassNames);
if (aliasing !== 'default') {
document.body.classList.add(`monaco-font-aliasing-${aliasing}`);
}
}
private shutdownComponents(reason = ShutdownReason.QUIT): void {
public dispose(reason = ShutdownReason.QUIT): void {
// Restore sidebar if we are being shutdown as a matter of a reload
if (reason === ShutdownReason.RELOAD) {
@@ -1100,14 +1099,27 @@ export class Workbench implements IPartService {
this.storageService.remove(Workbench.zenModeActiveStorageKey, StorageScope.WORKSPACE);
}
// Dispose bindings
this.toUnbind = dispose(this.toUnbind);
// Pass shutdown on to each participant
this.toShutdown.forEach(s => s.shutdown());
this.workbenchShutdown = true;
}
/**
* Asks the workbench and all its UI components inside to lay out according to
* the containers dimension the workbench is living in.
*/
public layout(options?: ILayoutOptions): void {
if (this.isStarted()) {
this.workbenchLayout.layout(options);
}
}
private registerListeners(): void {
// Listen to editor changes
this.toDispose.push(this.editorPart.onEditorsChanged(() => this.onEditorsChanged()));
this.toUnbind.push(this.editorPart.onEditorsChanged(() => this.onEditorsChanged()));
// Listen to editor closing (if we run with --wait)
const filesToWait = this.workbenchParams.configuration.filesToWait;
@@ -1116,21 +1128,14 @@ export class Workbench implements IPartService {
const waitMarkerFile = URI.file(filesToWait.waitMarkerFilePath);
const listenerDispose = this.editorPart.getStacksModel().onEditorClosed(() => this.onEditorClosed(listenerDispose, resourcesToWaitFor, waitMarkerFile));
this.toDispose.push(listenerDispose);
this.toUnbind.push(listenerDispose);
}
// Handle message service and quick open events
this.toDispose.push((<WorkbenchMessageService>this.messageService).onMessagesShowing(() => this.messagesVisibleContext.set(true)));
this.toDispose.push((<WorkbenchMessageService>this.messageService).onMessagesCleared(() => this.messagesVisibleContext.reset()));
this.toDispose.push(this.quickOpen.onShow(() => (<WorkbenchMessageService>this.messageService).suspend())); // when quick open is open, don't show messages behind
this.toDispose.push(this.quickOpen.onHide(() => (<WorkbenchMessageService>this.messageService).resume())); // resume messages once quick open is closed again
// Configuration changes
this.toDispose.push(this.configurationService.onDidChangeConfiguration(() => this.onDidUpdateConfiguration()));
this.toUnbind.push(this.configurationService.onDidChangeConfiguration(() => this.onDidUpdateConfiguration()));
// Fullscreen changes
this.toDispose.push(browser.onDidChangeFullscreen(() => this.onFullscreenChanged()));
this.toUnbind.push(browser.onDidChangeFullscreen(() => this.onFullscreenChanged()));
}
private onFullscreenChanged(): void {
@@ -1214,7 +1219,9 @@ export class Workbench implements IPartService {
this.setSideBarPosition(newSidebarPosition);
}
const fontAliasing = this.configurationService.getValue<string>(Workbench.fontAliasingConfigurationKey);
this.setPanelPositionFromStorageOrConfig();
const fontAliasing = this.configurationService.getValue<FontAliasingOption>(Workbench.fontAliasingConfigurationKey);
if (fontAliasing !== this.fontAliasing) {
this.setFontAliasing(fontAliasing);
}
@@ -1233,7 +1240,8 @@ export class Workbench implements IPartService {
}
private createWorkbenchLayout(): void {
this.workbenchLayout = this.instantiationService.createInstance(WorkbenchLayout,
this.workbenchLayout = this.instantiationService.createInstance(
WorkbenchLayout,
$(this.container), // Parent
this.workbench, // Workbench Container
{
@@ -1244,10 +1252,10 @@ export class Workbench implements IPartService {
panel: this.panelPart, // Panel Part
statusbar: this.statusbarPart, // Statusbar
},
this.quickOpen // Quickopen
this.quickOpen, // Quickopen
this.notificationsCenter, // Notifications Center
this.notificationsToasts // Notifications Toasts
);
this.toDispose.push(this.workbenchLayout);
}
private renderWorkbench(): void {
@@ -1259,6 +1267,9 @@ export class Workbench implements IPartService {
if (this.panelHidden) {
this.workbench.addClass('nopanel');
}
if (this.statusBarHidden) {
this.workbench.addClass('nostatusbar');
}
// Apply font aliasing
this.setFontAliasing(this.fontAliasing);
@@ -1282,6 +1293,9 @@ export class Workbench implements IPartService {
this.createPanelPart();
this.createStatusbarPart();
// Notification Handlers
this.createNotificationsHandlers();
// Add Workbench to DOM
this.workbenchContainer.build(this.container);
}
@@ -1350,6 +1364,38 @@ export class Workbench implements IPartService {
this.statusbarPart.create(statusbarContainer);
}
private createNotificationsHandlers(): void {
// Notifications Center
this.notificationsCenter = this.instantiationService.createInstance(NotificationsCenter, this.workbench.getHTMLElement(), this.notificationService.model);
this.toUnbind.push(this.notificationsCenter);
// Notifications Toasts
this.notificationsToasts = this.instantiationService.createInstance(NotificationsToasts, this.workbench.getHTMLElement(), this.notificationService.model);
this.toUnbind.push(this.notificationsToasts);
// Notifications Alerts
const notificationsAlerts = this.instantiationService.createInstance(NotificationsAlerts, this.notificationService.model);
this.toUnbind.push(notificationsAlerts);
// Notifications Status
const notificationsStatus = this.instantiationService.createInstance(NotificationsStatus, this.notificationService.model);
this.toUnbind.push(notificationsStatus);
// Eventing
this.toUnbind.push(this.notificationsCenter.onDidChangeVisibility(() => {
// Update status
notificationsStatus.update(this.notificationsCenter.isVisible);
// Update toasts
this.notificationsToasts.update(this.notificationsCenter.isVisible);
}));
// Register Commands
registerNotificationCommands(this.notificationsCenter, this.notificationsToasts);
}
public getInstantiationService(): IInstantiationService {
return this.instantiationService;
}
@@ -1375,10 +1421,14 @@ export class Workbench implements IPartService {
// Check if zen mode transitioned to full screen and if now we are out of zen mode -> we need to go out of full screen
let toggleFullScreen = false;
// Same goes for the centered editor layout
let toggleCenteredEditorLayout = false;
if (this.zenMode.active) {
const config = this.configurationService.getValue<IZenModeSettings>('zenMode');
toggleFullScreen = !browser.isFullscreen() && config.fullScreen;
this.zenMode.transitionedToFullScreen = toggleFullScreen;
toggleCenteredEditorLayout = !this.isEditorLayoutCentered() && config.centerLayout;
this.zenMode.transitionedToCenteredEditorLayout = toggleCenteredEditorLayout;
this.zenMode.wasSideBarVisible = this.isVisible(Parts.SIDEBAR_PART);
this.zenMode.wasPanelVisible = this.isVisible(Parts.PANEL_PART);
this.setPanelHidden(true, true).done(void 0, errors.onUnexpectedError);
@@ -1413,10 +1463,15 @@ export class Workbench implements IPartService {
}
toggleFullScreen = this.zenMode.transitionedToFullScreen && browser.isFullscreen();
toggleCenteredEditorLayout = this.zenMode.transitionedToCenteredEditorLayout && this.isEditorLayoutCentered();
}
this.inZenMode.set(this.zenMode.active);
if (toggleCenteredEditorLayout) {
this.toggleCenteredEditorLayout(true);
}
if (!skipLayout) {
this.layout();
}
@@ -1426,6 +1481,19 @@ export class Workbench implements IPartService {
}
}
public isEditorLayoutCentered(): boolean {
return this.centeredEditorLayoutActive;
}
public toggleCenteredEditorLayout(skipLayout?: boolean): void {
this.centeredEditorLayoutActive = !this.centeredEditorLayoutActive;
this.storageService.store(Workbench.centeredEditorLayoutActiveStorageKey, this.centeredEditorLayoutActive, StorageScope.GLOBAL);
if (!skipLayout) {
this.layout();
}
}
// Resize requested part along the main axis
// layout will do all the math for us and adjusts the other Parts
public resizePart(part: Parts, sizeChange: number): void {