Merge VS Code 1.31.1 (#4283)

This commit is contained in:
Matt Irvine
2019-03-15 13:09:45 -07:00
committed by GitHub
parent 7d31575149
commit 86bac90001
1716 changed files with 53308 additions and 48375 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,210 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Action } from 'vs/base/common/actions';
import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows';
import * as nls from 'vs/nls';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { domEvent } from 'vs/base/browser/event';
import { Event } from 'vs/base/common/event';
import { IDisposable, toDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
import { getDomNodePagePosition, createStyleSheet, createCSSRule, append, $ } from 'vs/base/browser/dom';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { Context } from 'vs/platform/contextkey/browser/contextKeyService';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { timeout } from 'vs/base/common/async';
export class ToggleDevToolsAction extends Action {
static readonly ID = 'workbench.action.toggleDevTools';
static LABEL = nls.localize('toggleDevTools', "Toggle Developer Tools");
constructor(id: string, label: string, @IWindowService private readonly windowsService: IWindowService) {
super(id, label);
}
run(): Promise<void> {
return this.windowsService.toggleDevTools();
}
}
export class ToggleSharedProcessAction extends Action {
static readonly ID = 'workbench.action.toggleSharedProcess';
static LABEL = nls.localize('toggleSharedProcess', "Toggle Shared Process");
constructor(id: string, label: string, @IWindowsService private readonly windowsService: IWindowsService) {
super(id, label);
}
run(): Promise<void> {
return this.windowsService.toggleSharedProcess();
}
}
export class InspectContextKeysAction extends Action {
static readonly ID = 'workbench.action.inspectContextKeys';
static LABEL = nls.localize('inspect context keys', "Inspect Context Keys");
constructor(
id: string,
label: string,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IWindowService private readonly windowService: IWindowService,
) {
super(id, label);
}
run(): Promise<void> {
const disposables: IDisposable[] = [];
const stylesheet = createStyleSheet();
disposables.push(toDisposable(() => {
if (stylesheet.parentNode) {
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 = Event.once(domEvent(document.body, 'mousedown', true));
onMouseDown(e => { e.preventDefault(); e.stopPropagation(); }, null, disposables);
const onMouseUp = Event.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 Promise.resolve();
}
}
export class ToggleScreencastModeAction extends Action {
static readonly ID = 'workbench.action.toggleScreencastMode';
static LABEL = nls.localize('toggle mouse clicks', "Toggle Screencast Mode");
static disposable: IDisposable | undefined;
constructor(id: string, label: string, @IKeybindingService private readonly keybindingService: IKeybindingService) {
super(id, label);
}
async run(): Promise<void> {
if (ToggleScreencastModeAction.disposable) {
ToggleScreencastModeAction.disposable.dispose();
ToggleScreencastModeAction.disposable = undefined;
return;
}
const mouseMarker = append(document.body, $('div'));
mouseMarker.style.position = 'absolute';
mouseMarker.style.border = '2px solid red';
mouseMarker.style.borderRadius = '20px';
mouseMarker.style.width = '20px';
mouseMarker.style.height = '20px';
mouseMarker.style.top = '0';
mouseMarker.style.left = '0';
mouseMarker.style.zIndex = '100000';
mouseMarker.style.content = ' ';
mouseMarker.style.pointerEvents = 'none';
mouseMarker.style.display = 'none';
const onMouseDown = domEvent(document.body, 'mousedown', true);
const onMouseUp = domEvent(document.body, 'mouseup', true);
const onMouseMove = domEvent(document.body, 'mousemove', true);
const mouseListener = onMouseDown(e => {
mouseMarker.style.top = `${e.clientY - 10}px`;
mouseMarker.style.left = `${e.clientX - 10}px`;
mouseMarker.style.display = 'block';
const mouseMoveListener = onMouseMove(e => {
mouseMarker.style.top = `${e.clientY - 10}px`;
mouseMarker.style.left = `${e.clientX - 10}px`;
});
Event.once(onMouseUp)(() => {
mouseMarker.style.display = 'none';
mouseMoveListener.dispose();
});
});
const keyboardMarker = append(document.body, $('div'));
keyboardMarker.style.position = 'absolute';
keyboardMarker.style.backgroundColor = 'rgba(0, 0, 0 ,0.5)';
keyboardMarker.style.width = '100%';
keyboardMarker.style.height = '100px';
keyboardMarker.style.bottom = '20%';
keyboardMarker.style.left = '0';
keyboardMarker.style.zIndex = '100000';
keyboardMarker.style.pointerEvents = 'none';
keyboardMarker.style.color = 'white';
keyboardMarker.style.lineHeight = '100px';
keyboardMarker.style.textAlign = 'center';
keyboardMarker.style.fontSize = '56px';
keyboardMarker.style.display = 'none';
const onKeyDown = domEvent(document.body, 'keydown', true);
let keyboardTimeout: IDisposable = Disposable.None;
const keyboardListener = onKeyDown(e => {
keyboardTimeout.dispose();
const event = new StandardKeyboardEvent(e);
const keybinding = this.keybindingService.resolveKeyboardEvent(event);
const label = keybinding.getLabel();
if (!event.ctrlKey && !event.altKey && !event.metaKey && !event.shiftKey && this.keybindingService.mightProducePrintableCharacter(event) && label) {
keyboardMarker.textContent += ' ' + label;
} else {
keyboardMarker.textContent = label;
}
keyboardMarker.style.display = 'block';
const promise = timeout(800);
keyboardTimeout = toDisposable(() => promise.cancel());
promise.then(() => {
keyboardMarker.textContent = '';
keyboardMarker.style.display = 'none';
});
});
ToggleScreencastModeAction.disposable = toDisposable(() => {
mouseListener.dispose();
keyboardListener.dispose();
document.body.removeChild(mouseMarker);
});
}
}

View File

@@ -0,0 +1,244 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Action } from 'vs/base/common/actions';
import * as nls from 'vs/nls';
import product from 'vs/platform/node/product';
import { isMacintosh, isLinux, language } from 'vs/base/common/platform';
import { IssueType } from 'vs/platform/issue/common/issue';
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
export class OpenIssueReporterAction extends Action {
static readonly ID = 'workbench.action.openIssueReporter';
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,
@IWorkbenchIssueService private readonly issueService: IWorkbenchIssueService
) {
super(id, label);
}
run(): Promise<boolean> {
return this.issueService.openReporter().then(() => true);
}
}
export class OpenProcessExplorer extends Action {
static readonly ID = 'workbench.action.openProcessExplorer';
static readonly LABEL = nls.localize('openProcessExplorer', "Open Process Explorer");
constructor(
id: string,
label: string,
@IWorkbenchIssueService private readonly issueService: IWorkbenchIssueService
) {
super(id, label);
}
run(): Promise<boolean> {
return this.issueService.openProcessExplorer().then(() => true);
}
}
export class ReportPerformanceIssueUsingReporterAction extends Action {
static readonly ID = 'workbench.action.reportPerformanceIssueUsingReporter';
static readonly LABEL = nls.localize('reportPerformanceIssue', "Report Performance Issue");
constructor(
id: string,
label: string,
@IWorkbenchIssueService private readonly issueService: IWorkbenchIssueService
) {
super(id, label);
}
run(): Promise<boolean> {
return this.issueService.openReporter({ issueType: IssueType.PerformanceIssue }).then(() => true);
}
}
export class KeybindingsReferenceAction extends Action {
static readonly ID = 'workbench.action.keybindingsReference';
static readonly LABEL = nls.localize('keybindingsReference', "Keyboard Shortcuts Reference");
private static readonly URL = isLinux ? product.keyboardShortcutsUrlLinux : isMacintosh ? product.keyboardShortcutsUrlMac : product.keyboardShortcutsUrlWin;
static readonly AVAILABLE = !!KeybindingsReferenceAction.URL;
constructor(
id: string,
label: string
) {
super(id, label);
}
run(): Promise<void> {
window.open(KeybindingsReferenceAction.URL);
return Promise.resolve();
}
}
export class OpenDocumentationUrlAction extends Action {
static readonly ID = 'workbench.action.openDocumentationUrl';
static readonly LABEL = nls.localize('openDocumentationUrl', "Documentation");
private static readonly URL = product.documentationUrl;
static readonly AVAILABLE = !!OpenDocumentationUrlAction.URL;
constructor(
id: string,
label: string
) {
super(id, label);
}
run(): Promise<void> {
window.open(OpenDocumentationUrlAction.URL);
return Promise.resolve();
}
}
export class OpenIntroductoryVideosUrlAction extends Action {
static readonly ID = 'workbench.action.openIntroductoryVideosUrl';
static readonly LABEL = nls.localize('openIntroductoryVideosUrl', "Introductory Videos");
private static readonly URL = product.introductoryVideosUrl;
static readonly AVAILABLE = !!OpenIntroductoryVideosUrlAction.URL;
constructor(
id: string,
label: string
) {
super(id, label);
}
run(): Promise<void> {
window.open(OpenIntroductoryVideosUrlAction.URL);
return Promise.resolve();
}
}
export class OpenTipsAndTricksUrlAction extends Action {
static readonly ID = 'workbench.action.openTipsAndTricksUrl';
static readonly LABEL = nls.localize('openTipsAndTricksUrl', "Tips and Tricks");
private static readonly URL = product.tipsAndTricksUrl;
static readonly AVAILABLE = !!OpenTipsAndTricksUrlAction.URL;
constructor(
id: string,
label: string
) {
super(id, label);
}
run(): Promise<void> {
window.open(OpenTipsAndTricksUrlAction.URL);
return Promise.resolve();
}
}
export class OpenTwitterUrlAction extends Action {
static readonly ID = 'workbench.action.openTwitterUrl';
static LABEL = nls.localize('openTwitterUrl', "Join Us on Twitter", product.applicationName);
constructor(
id: string,
label: string
) {
super(id, label);
}
run(): Promise<boolean> {
if (product.twitterUrl) {
window.open(product.twitterUrl);
}
return Promise.resolve();
}
}
export class OpenRequestFeatureUrlAction extends Action {
static readonly ID = 'workbench.action.openRequestFeatureUrl';
static LABEL = nls.localize('openUserVoiceUrl', "Search Feature Requests");
constructor(
id: string,
label: string
) {
super(id, label);
}
run(): Promise<boolean> {
if (product.requestFeatureUrl) {
window.open(product.requestFeatureUrl);
}
return Promise.resolve();
}
}
export class OpenLicenseUrlAction extends Action {
static readonly ID = 'workbench.action.openLicenseUrl';
static LABEL = nls.localize('openLicenseUrl', "View License");
constructor(
id: string,
label: string
) {
super(id, label);
}
run(): Promise<boolean> {
if (product.licenseUrl) {
if (language) {
const queryArgChar = product.licenseUrl.indexOf('?') > 0 ? '&' : '?';
window.open(`${product.licenseUrl}${queryArgChar}lang=${language}`);
} else {
window.open(product.licenseUrl);
}
}
return Promise.resolve();
}
}
export class OpenPrivacyStatementUrlAction extends Action {
static readonly ID = 'workbench.action.openPrivacyStatementUrl';
static LABEL = nls.localize('openPrivacyStatement', "Privacy Statement");
constructor(
id: string,
label: string
) {
super(id, label);
}
run(): Promise<boolean> {
if (product.privacyStatementUrl) {
if (language) {
const queryArgChar = product.privacyStatementUrl.indexOf('?') > 0 ? '&' : '?';
window.open(`${product.privacyStatementUrl}${queryArgChar}lang=${language}`);
} else {
window.open(product.privacyStatementUrl);
}
}
return Promise.resolve();
}
}

View File

Before

Width:  |  Height:  |  Size: 307 B

After

Width:  |  Height:  |  Size: 307 B

View File

Before

Width:  |  Height:  |  Size: 307 B

After

Width:  |  Height:  |  Size: 307 B

View File

@@ -0,0 +1,577 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/actions';
import { URI } from 'vs/base/common/uri';
import { Action } from 'vs/base/common/actions';
import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows';
import * as nls from 'vs/nls';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
import { isMacintosh } from 'vs/base/common/platform';
import * as browser from 'vs/base/browser/browser';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { webFrame } from 'electron';
import { getBaseLabel } from 'vs/base/common/labels';
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { FileKind } from 'vs/platform/files/common/files';
import { ILabelService } from 'vs/platform/label/common/label';
import { dirname } from 'vs/base/common/resources';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IQuickInputService, IQuickPickItem, IQuickInputButton, IQuickPickSeparator, IKeyMods } from 'vs/platform/quickinput/common/quickInput';
import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
import product from 'vs/platform/node/product';
export class CloseCurrentWindowAction extends Action {
static readonly ID = 'workbench.action.closeWindow';
static readonly LABEL = nls.localize('closeWindow', "Close Window");
constructor(id: string, label: string, @IWindowService private readonly windowService: IWindowService) {
super(id, label);
}
run(): Promise<boolean> {
this.windowService.closeWindow();
return Promise.resolve(true);
}
}
export class NewWindowAction extends Action {
static readonly ID = 'workbench.action.newWindow';
static LABEL = nls.localize('newWindow', "New Window");
constructor(
id: string,
label: string,
@IWindowsService private readonly windowsService: IWindowsService
) {
super(id, label);
}
run(): Promise<void> {
return this.windowsService.openNewWindow();
}
}
export class ToggleFullScreenAction extends Action {
static readonly ID = 'workbench.action.toggleFullScreen';
static LABEL = nls.localize('toggleFullScreen', "Toggle Full Screen");
constructor(id: string, label: string, @IWindowService private readonly windowService: IWindowService) {
super(id, label);
}
run(): Promise<void> {
return this.windowService.toggleFullScreen();
}
}
export abstract class BaseZoomAction extends Action {
private static readonly SETTING_KEY = 'window.zoomLevel';
constructor(
id: string,
label: string,
@IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService
) {
super(id, label);
}
protected setConfiguredZoomLevel(level: number): void {
level = Math.round(level); // when reaching smallest zoom, prevent fractional zoom levels
const applyZoom = () => {
webFrame.setZoomLevel(level);
browser.setZoomFactor(webFrame.getZoomFactor());
// See https://github.com/Microsoft/vscode/issues/26151
// Cannot be trusted because the webFrame might take some time
// until it really applies the new zoom level
browser.setZoomLevel(webFrame.getZoomLevel(), /*isTrusted*/false);
};
this.configurationService.updateValue(BaseZoomAction.SETTING_KEY, level).then(() => applyZoom());
}
}
export class ZoomInAction extends BaseZoomAction {
static readonly ID = 'workbench.action.zoomIn';
static readonly LABEL = nls.localize('zoomIn', "Zoom In");
constructor(
id: string,
label: string,
@IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService
) {
super(id, label, configurationService);
}
run(): Promise<boolean> {
this.setConfiguredZoomLevel(webFrame.getZoomLevel() + 1);
return Promise.resolve(true);
}
}
export class ZoomOutAction extends BaseZoomAction {
static readonly ID = 'workbench.action.zoomOut';
static readonly LABEL = nls.localize('zoomOut', "Zoom Out");
constructor(
id: string,
label: string,
@IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService
) {
super(id, label, configurationService);
}
run(): Promise<boolean> {
this.setConfiguredZoomLevel(webFrame.getZoomLevel() - 1);
return Promise.resolve(true);
}
}
export class ZoomResetAction extends BaseZoomAction {
static readonly ID = 'workbench.action.zoomReset';
static readonly LABEL = nls.localize('zoomReset', "Reset Zoom");
constructor(
id: string,
label: string,
@IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService
) {
super(id, label, configurationService);
}
run(): Promise<boolean> {
this.setConfiguredZoomLevel(0);
return Promise.resolve(true);
}
}
export class ReloadWindowAction extends Action {
static readonly ID = 'workbench.action.reloadWindow';
static LABEL = nls.localize('reloadWindow', "Reload Window");
constructor(
id: string,
label: string,
@IWindowService private readonly windowService: IWindowService
) {
super(id, label);
}
run(): Promise<boolean> {
return this.windowService.reloadWindow().then(() => true);
}
}
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 readonly windowService: IWindowService
) {
super(id, label);
}
run(): Promise<boolean> {
return this.windowService.reloadWindow({ _: [], 'disable-extensions': true }).then(() => true);
}
}
export abstract class BaseSwitchWindow extends Action {
private closeWindowAction: IQuickInputButton = {
iconClass: 'action-remove-from-recently-opened',
tooltip: nls.localize('close', "Close Window")
};
constructor(
id: string,
label: string,
private windowsService: IWindowsService,
private windowService: IWindowService,
private quickInputService: IQuickInputService,
private keybindingService: IKeybindingService,
private modelService: IModelService,
private modeService: IModeService,
) {
super(id, label);
}
protected abstract isQuickNavigate(): boolean;
run(): Promise<void> {
const currentWindowId = this.windowService.getCurrentWindowId();
return this.windowsService.getWindows().then(windows => {
const placeHolder = nls.localize('switchWindowPlaceHolder', "Select a window to switch to");
const picks = windows.map(win => {
const resource = win.filename ? URI.file(win.filename) : win.folderUri ? win.folderUri : win.workspace ? URI.file(win.workspace.configPath) : undefined;
const fileKind = win.filename ? FileKind.FILE : win.workspace ? FileKind.ROOT_FOLDER : win.folderUri ? FileKind.FOLDER : FileKind.FILE;
return {
payload: win.id,
label: win.title,
iconClasses: getIconClasses(this.modelService, this.modeService, resource, fileKind),
description: (currentWindowId === win.id) ? nls.localize('current', "Current Window") : undefined,
buttons: (!this.isQuickNavigate() && currentWindowId !== win.id) ? [this.closeWindowAction] : undefined
} as (IQuickPickItem & { payload: number });
});
const autoFocusIndex = (picks.indexOf(picks.filter(pick => pick.payload === currentWindowId)[0]) + 1) % picks.length;
return this.quickInputService.pick(picks, {
contextKey: 'inWindowsPicker',
activeItem: picks[autoFocusIndex],
placeHolder,
quickNavigate: this.isQuickNavigate() ? { keybindings: this.keybindingService.lookupKeybindings(this.id) } : undefined,
onDidTriggerItemButton: context => {
this.windowsService.closeWindow(context.item.payload).then(() => {
context.removeItem();
});
}
});
}).then(pick => {
if (pick) {
this.windowsService.showWindow(pick.payload);
}
});
}
}
export class SwitchWindow extends BaseSwitchWindow {
static readonly ID = 'workbench.action.switchWindow';
static LABEL = nls.localize('switchWindow', "Switch Window...");
constructor(
id: string,
label: string,
@IWindowsService windowsService: IWindowsService,
@IWindowService windowService: IWindowService,
@IQuickInputService quickInputService: IQuickInputService,
@IKeybindingService keybindingService: IKeybindingService,
@IModelService modelService: IModelService,
@IModeService modeService: IModeService,
) {
super(id, label, windowsService, windowService, quickInputService, keybindingService, modelService, modeService);
}
protected isQuickNavigate(): boolean {
return false;
}
}
export class QuickSwitchWindow extends BaseSwitchWindow {
static readonly ID = 'workbench.action.quickSwitchWindow';
static LABEL = nls.localize('quickSwitchWindow', "Quick Switch Window...");
constructor(
id: string,
label: string,
@IWindowsService windowsService: IWindowsService,
@IWindowService windowService: IWindowService,
@IQuickInputService quickInputService: IQuickInputService,
@IKeybindingService keybindingService: IKeybindingService,
@IModelService modelService: IModelService,
@IModeService modeService: IModeService,
) {
super(id, label, windowsService, windowService, quickInputService, keybindingService, modelService, modeService);
}
protected isQuickNavigate(): boolean {
return true;
}
}
export const inRecentFilesPickerContextKey = 'inRecentFilesPicker';
export abstract class BaseOpenRecentAction extends Action {
private removeFromRecentlyOpened: IQuickInputButton = {
iconClass: 'action-remove-from-recently-opened',
tooltip: nls.localize('remove', "Remove from Recently Opened")
};
constructor(
id: string,
label: string,
private windowService: IWindowService,
private windowsService: IWindowsService,
private quickInputService: IQuickInputService,
private contextService: IWorkspaceContextService,
private labelService: ILabelService,
private keybindingService: IKeybindingService,
private modelService: IModelService,
private modeService: IModeService,
) {
super(id, label);
}
protected abstract isQuickNavigate(): boolean;
run(): Promise<void> {
return this.windowService.getRecentlyOpened()
.then(({ workspaces, files }) => this.openRecent(workspaces, files));
}
private openRecent(recentWorkspaces: Array<IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier>, recentFiles: URI[]): void {
const toPick = (workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI, fileKind: FileKind, labelService: ILabelService, buttons: IQuickInputButton[] | undefined) => {
let resource: URI;
let label: string;
let description: string;
if (isSingleFolderWorkspaceIdentifier(workspace) && fileKind !== FileKind.FILE) {
resource = workspace;
label = labelService.getWorkspaceLabel(workspace);
description = labelService.getUriLabel(dirname(resource)!);
} else if (isWorkspaceIdentifier(workspace)) {
resource = URI.file(workspace.configPath);
label = labelService.getWorkspaceLabel(workspace);
description = labelService.getUriLabel(dirname(resource)!);
} else {
resource = workspace;
label = getBaseLabel(workspace);
description = labelService.getUriLabel(dirname(resource)!);
}
return {
iconClasses: getIconClasses(this.modelService, this.modeService, resource, fileKind),
label,
description,
buttons,
workspace,
resource,
fileKind,
};
};
const runPick = (resource: URI, isFile: boolean, keyMods: IKeyMods) => {
const forceNewWindow = keyMods.ctrlCmd;
return this.windowService.openWindow([resource], { forceNewWindow, forceOpenWorkspaceAsFile: isFile });
};
const workspacePicks = recentWorkspaces.map(workspace => toPick(workspace, isSingleFolderWorkspaceIdentifier(workspace) ? FileKind.FOLDER : FileKind.ROOT_FOLDER, this.labelService, !this.isQuickNavigate() ? [this.removeFromRecentlyOpened] : undefined));
const filePicks = recentFiles.map(p => toPick(p, FileKind.FILE, this.labelService, !this.isQuickNavigate() ? [this.removeFromRecentlyOpened] : undefined));
// focus second entry if the first recent workspace is the current workspace
let autoFocusSecondEntry: boolean = recentWorkspaces[0] && this.contextService.isCurrentWorkspace(recentWorkspaces[0]);
let keyMods: IKeyMods;
const workspaceSeparator: IQuickPickSeparator = { type: 'separator', label: nls.localize('workspaces', "workspaces") };
const fileSeparator: IQuickPickSeparator = { type: 'separator', label: nls.localize('files', "files") };
const picks = [workspaceSeparator, ...workspacePicks, fileSeparator, ...filePicks];
this.quickInputService.pick(picks, {
contextKey: inRecentFilesPickerContextKey,
activeItem: [...workspacePicks, ...filePicks][autoFocusSecondEntry ? 1 : 0],
placeHolder: isMacintosh ? nls.localize('openRecentPlaceHolderMac', "Select to open (hold Cmd-key to open in new window)") : nls.localize('openRecentPlaceHolder', "Select to open (hold Ctrl-key to open in new window)"),
matchOnDescription: true,
onKeyMods: mods => keyMods = mods,
quickNavigate: this.isQuickNavigate() ? { keybindings: this.keybindingService.lookupKeybindings(this.id) } : undefined,
onDidTriggerItemButton: context => {
this.windowsService.removeFromRecentlyOpened([context.item.workspace]).then(() => context.removeItem());
}
})
.then((pick): Promise<void> | void => {
if (pick) {
return runPick(pick.resource, pick.fileKind === FileKind.FILE, keyMods);
}
});
}
}
export class OpenRecentAction extends BaseOpenRecentAction {
static readonly ID = 'workbench.action.openRecent';
static readonly LABEL = nls.localize('openRecent', "Open Recent...");
constructor(
id: string,
label: string,
@IWindowService windowService: IWindowService,
@IWindowsService windowsService: IWindowsService,
@IQuickInputService quickInputService: IQuickInputService,
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IKeybindingService keybindingService: IKeybindingService,
@IModelService modelService: IModelService,
@IModeService modeService: IModeService,
@ILabelService labelService: ILabelService
) {
super(id, label, windowService, windowsService, quickInputService, contextService, labelService, keybindingService, modelService, modeService);
}
protected isQuickNavigate(): boolean {
return false;
}
}
export class QuickOpenRecentAction extends BaseOpenRecentAction {
static readonly ID = 'workbench.action.quickOpenRecent';
static readonly LABEL = nls.localize('quickOpenRecent', "Quick Open Recent...");
constructor(
id: string,
label: string,
@IWindowService windowService: IWindowService,
@IWindowsService windowsService: IWindowsService,
@IQuickInputService quickInputService: IQuickInputService,
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IKeybindingService keybindingService: IKeybindingService,
@IModelService modelService: IModelService,
@IModeService modeService: IModeService,
@ILabelService labelService: ILabelService
) {
super(id, label, windowService, windowsService, quickInputService, contextService, labelService, keybindingService, modelService, modeService);
}
protected isQuickNavigate(): boolean {
return true;
}
}
export class ShowAboutDialogAction extends Action {
static readonly ID = 'workbench.action.showAboutDialog';
static LABEL = nls.localize('about', "About {0}", product.applicationName);
constructor(
id: string,
label: string,
@IWindowsService private readonly windowsService: IWindowsService
) {
super(id, label);
}
run(): Promise<void> {
return this.windowsService.openAboutDialog();
}
}
export class NewWindowTab extends Action {
static readonly ID = 'workbench.action.newWindowTab';
static readonly LABEL = nls.localize('newTab', "New Window Tab");
constructor(
_id: string,
_label: string,
@IWindowsService private readonly windowsService: IWindowsService
) {
super(NewWindowTab.ID, NewWindowTab.LABEL);
}
run(): Promise<boolean> {
return this.windowsService.newWindowTab().then(() => true);
}
}
export class ShowPreviousWindowTab extends Action {
static readonly ID = 'workbench.action.showPreviousWindowTab';
static readonly LABEL = nls.localize('showPreviousTab', "Show Previous Window Tab");
constructor(
_id: string,
_label: string,
@IWindowsService private readonly windowsService: IWindowsService
) {
super(ShowPreviousWindowTab.ID, ShowPreviousWindowTab.LABEL);
}
run(): Promise<boolean> {
return this.windowsService.showPreviousWindowTab().then(() => true);
}
}
export class ShowNextWindowTab extends Action {
static readonly ID = 'workbench.action.showNextWindowTab';
static readonly LABEL = nls.localize('showNextWindowTab', "Show Next Window Tab");
constructor(
_id: string,
_label: string,
@IWindowsService private readonly windowsService: IWindowsService
) {
super(ShowNextWindowTab.ID, ShowNextWindowTab.LABEL);
}
run(): Promise<boolean> {
return this.windowsService.showNextWindowTab().then(() => true);
}
}
export class MoveWindowTabToNewWindow extends Action {
static readonly ID = 'workbench.action.moveWindowTabToNewWindow';
static readonly LABEL = nls.localize('moveWindowTabToNewWindow', "Move Window Tab to New Window");
constructor(
_id: string,
_label: string,
@IWindowsService private readonly windowsService: IWindowsService
) {
super(MoveWindowTabToNewWindow.ID, MoveWindowTabToNewWindow.LABEL);
}
run(): Promise<boolean> {
return this.windowsService.moveWindowTabToNewWindow().then(() => true);
}
}
export class MergeAllWindowTabs extends Action {
static readonly ID = 'workbench.action.mergeAllWindowTabs';
static readonly LABEL = nls.localize('mergeAllWindowTabs', "Merge All Windows");
constructor(
_id: string,
_label: string,
@IWindowsService private readonly windowsService: IWindowsService
) {
super(MergeAllWindowTabs.ID, MergeAllWindowTabs.LABEL);
}
run(): Promise<boolean> {
return this.windowsService.mergeAllWindowTabs().then(() => true);
}
}
export class ToggleWindowTabsBar extends Action {
static readonly ID = 'workbench.action.toggleWindowTabsBar';
static readonly LABEL = nls.localize('toggleWindowTabsBar', "Toggle Window Tabs Bar");
constructor(
_id: string,
_label: string,
@IWindowsService private readonly windowsService: IWindowsService
) {
super(ToggleWindowTabsBar.ID, ToggleWindowTabsBar.LABEL);
}
run(): Promise<boolean> {
return this.windowsService.toggleWindowTabsBar().then(() => true);
}
}

View File

@@ -1,717 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { tmpdir } from 'os';
import { posix } from 'path';
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows';
import { List } from 'vs/base/browser/ui/list/listWidget';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { WorkbenchListFocusContextKey, IListService, WorkbenchListSupportsMultiSelectContextKey, ListWidget, WorkbenchListHasSelectionOrFocus } 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';
import { InEditorZenModeContext, NoEditorsVisibleContext, SingleEditorGroupsContext } from 'vs/workbench/common/editor';
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri';
import { IDownloadService } from 'vs/platform/download/common/download';
import { generateUuid } from 'vs/base/common/uuid';
import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree';
import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree';
// --- List Commands
function ensureDOMFocus(widget: ListWidget): void {
// it can happen that one of the commands is executed while
// DOM focus is within another focusable control within the
// list/tree item. therefor we should ensure that the
// list/tree has DOM focus again after the command ran.
if (widget && widget.getHTMLElement() !== document.activeElement) {
widget.domFocus();
}
}
export const QUIT_ID = 'workbench.action.quit';
export function registerCommands(): void {
function focusDown(accessor: ServicesAccessor, arg2?: number): void {
const focused = accessor.get(IListService).lastFocusedList;
const count = typeof arg2 === 'number' ? arg2 : 1;
// Ensure DOM Focus
ensureDOMFocus(focused);
// 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]);
}
}
// ObjectTree
else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
const list = focused;
const fakeKeyboardEvent = new KeyboardEvent('keydown');
list.focusNext(count, false, fakeKeyboardEvent);
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());
}
}
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.focusDown',
weight: KeybindingWeight.WorkbenchContrib,
when: WorkbenchListFocusContextKey,
primary: KeyCode.DownArrow,
mac: {
primary: KeyCode.DownArrow,
secondary: [KeyMod.WinCtrl | KeyCode.KEY_N]
},
handler: (accessor, arg2) => focusDown(accessor, arg2)
});
function expandMultiSelection(focused: List<any> | PagedList<any> | ITree | ObjectTree<any, any> | AsyncDataTree<any, any>, 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));
}
}
// ObjectTree
else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
const list = focused;
const focus = list.getFocus() ? list.getFocus()[0] : void 0;
const selection = list.getSelection();
const fakeKeyboardEvent = new KeyboardEvent('keydown');
if (selection && selection.indexOf(focus) >= 0) {
list.setSelection(selection.filter(s => s !== previousFocus), fakeKeyboardEvent);
} else {
list.setSelection(selection.concat(focus), fakeKeyboardEvent);
}
}
// 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: KeybindingWeight.WorkbenchContrib,
when: ContextKeyExpr.and(WorkbenchListFocusContextKey, WorkbenchListSupportsMultiSelectContextKey),
primary: KeyMod.Shift | KeyCode.DownArrow,
handler: (accessor, arg2) => {
const focused = accessor.get(IListService).lastFocusedList;
// List
if (focused instanceof List || focused instanceof PagedList || focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
const list = focused;
// 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;
// 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;
// Ensure DOM Focus
ensureDOMFocus(focused);
// 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]);
}
}
// ObjectTree
else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
const list = focused;
const fakeKeyboardEvent = new KeyboardEvent('keydown');
list.focusPrevious(count, false, fakeKeyboardEvent);
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());
}
}
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.focusUp',
weight: KeybindingWeight.WorkbenchContrib,
when: WorkbenchListFocusContextKey,
primary: KeyCode.UpArrow,
mac: {
primary: KeyCode.UpArrow,
secondary: [KeyMod.WinCtrl | KeyCode.KEY_P]
},
handler: (accessor, arg2) => focusUp(accessor, arg2)
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.expandSelectionUp',
weight: KeybindingWeight.WorkbenchContrib,
when: ContextKeyExpr.and(WorkbenchListFocusContextKey, WorkbenchListSupportsMultiSelectContextKey),
primary: KeyMod.Shift | KeyCode.UpArrow,
handler: (accessor, arg2) => {
const focused = accessor.get(IListService).lastFocusedList;
// List
if (focused instanceof List || focused instanceof PagedList) {
const list = focused;
// 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;
// Focus up first
const previousFocus = tree.getFocus();
focusUp(accessor, arg2);
// Then adjust selection
expandMultiSelection(focused, previousFocus);
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.collapse',
weight: KeybindingWeight.WorkbenchContrib,
when: WorkbenchListFocusContextKey,
primary: KeyCode.LeftArrow,
mac: {
primary: KeyCode.LeftArrow,
secondary: [KeyMod.CtrlCmd | KeyCode.UpArrow]
},
handler: (accessor) => {
const focused = accessor.get(IListService).lastFocusedList;
// Tree only
if (focused && !(focused instanceof List || focused instanceof PagedList)) {
if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
const tree = focused;
const focusedElements = tree.getFocus();
if (focusedElements.length === 0) {
return;
}
const focus = focusedElements[0];
if (!tree.collapse(focus)) {
const parent = tree.getParentElement(focus);
if (parent) {
const fakeKeyboardEvent = new KeyboardEvent('keydown');
tree.setFocus([parent], fakeKeyboardEvent);
tree.reveal(parent);
}
}
} else {
const tree = focused;
const focus = tree.getFocus();
tree.collapse(focus).then(didCollapse => {
if (focus && !didCollapse) {
tree.focusParent({ origin: 'keyboard' });
return tree.reveal(tree.getFocus());
}
return void 0;
});
}
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.expand',
weight: KeybindingWeight.WorkbenchContrib,
when: WorkbenchListFocusContextKey,
primary: KeyCode.RightArrow,
handler: (accessor) => {
const focused = accessor.get(IListService).lastFocusedList;
// Tree only
if (focused && !(focused instanceof List || focused instanceof PagedList)) {
if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
const tree = focused;
const focusedElements = tree.getFocus();
if (focusedElements.length === 0) {
return;
}
const focus = focusedElements[0];
if (!tree.expand(focus)) {
const child = tree.getFirstElementChild(focus);
if (child) {
const fakeKeyboardEvent = new KeyboardEvent('keydown');
tree.setFocus([child], fakeKeyboardEvent);
tree.reveal(child);
}
}
} else {
const tree = focused;
const focus = tree.getFocus();
tree.expand(focus).then(didExpand => {
if (focus && !didExpand) {
tree.focusFirstChild({ origin: 'keyboard' });
return tree.reveal(tree.getFocus());
}
return void 0;
});
}
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.focusPageUp',
weight: KeybindingWeight.WorkbenchContrib,
when: WorkbenchListFocusContextKey,
primary: KeyCode.PageUp,
handler: (accessor) => {
const focused = accessor.get(IListService).lastFocusedList;
// Ensure DOM Focus
ensureDOMFocus(focused);
// List
if (focused instanceof List || focused instanceof PagedList) {
const list = focused;
list.focusPreviousPage();
list.reveal(list.getFocus()[0]);
}
// ObjectTree
else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
const list = focused;
const fakeKeyboardEvent = new KeyboardEvent('keydown');
list.focusPreviousPage(fakeKeyboardEvent);
list.reveal(list.getFocus()[0]);
}
// Tree
else if (focused) {
const tree = focused;
tree.focusPreviousPage({ origin: 'keyboard' });
tree.reveal(tree.getFocus());
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.focusPageDown',
weight: KeybindingWeight.WorkbenchContrib,
when: WorkbenchListFocusContextKey,
primary: KeyCode.PageDown,
handler: (accessor) => {
const focused = accessor.get(IListService).lastFocusedList;
// Ensure DOM Focus
ensureDOMFocus(focused);
// List
if (focused instanceof List || focused instanceof PagedList) {
const list = focused;
list.focusNextPage();
list.reveal(list.getFocus()[0]);
}
// ObjectTree
else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
const list = focused;
const fakeKeyboardEvent = new KeyboardEvent('keydown');
list.focusNextPage(fakeKeyboardEvent);
list.reveal(list.getFocus()[0]);
}
// Tree
else if (focused) {
const tree = focused;
tree.focusNextPage({ origin: 'keyboard' });
tree.reveal(tree.getFocus());
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.focusFirst',
weight: KeybindingWeight.WorkbenchContrib,
when: WorkbenchListFocusContextKey,
primary: KeyCode.Home,
handler: accessor => listFocusFirst(accessor)
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.focusFirstChild',
weight: KeybindingWeight.WorkbenchContrib,
when: WorkbenchListFocusContextKey,
primary: 0,
handler: accessor => listFocusFirst(accessor, { fromFocused: true })
});
function listFocusFirst(accessor: ServicesAccessor, options?: { fromFocused: boolean }): void {
const focused = accessor.get(IListService).lastFocusedList;
// Ensure DOM Focus
ensureDOMFocus(focused);
// List
if (focused instanceof List || focused instanceof PagedList) {
const list = focused;
list.setFocus([0]);
list.reveal(0);
}
// ObjectTree
else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
const list = focused;
const first = list.getFirstElementChild(null);
if (!first) {
return;
}
const fakeKeyboardEvent = new KeyboardEvent('keydown');
list.setFocus([first], fakeKeyboardEvent);
list.reveal(first);
}
// Tree
else if (focused) {
const tree = focused;
tree.focusFirst({ origin: 'keyboard' }, options && options.fromFocused ? tree.getFocus() : void 0);
tree.reveal(tree.getFocus());
}
}
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.focusLast',
weight: KeybindingWeight.WorkbenchContrib,
when: WorkbenchListFocusContextKey,
primary: KeyCode.End,
handler: accessor => listFocusLast(accessor)
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.focusLastChild',
weight: KeybindingWeight.WorkbenchContrib,
when: WorkbenchListFocusContextKey,
primary: 0,
handler: accessor => listFocusLast(accessor, { fromFocused: true })
});
function listFocusLast(accessor: ServicesAccessor, options?: { fromFocused: boolean }): void {
const focused = accessor.get(IListService).lastFocusedList;
// Ensure DOM Focus
ensureDOMFocus(focused);
// List
if (focused instanceof List || focused instanceof PagedList) {
const list = focused;
list.setFocus([list.length - 1]);
list.reveal(list.length - 1);
}
// ObjectTree
else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
const list = focused;
const last = list.getLastElementAncestor();
if (!last) {
return;
}
const fakeKeyboardEvent = new KeyboardEvent('keydown');
list.setFocus([last], fakeKeyboardEvent);
list.reveal(last);
}
// Tree
else if (focused) {
const tree = focused;
tree.focusLast({ origin: 'keyboard' }, options && options.fromFocused ? tree.getFocus() : void 0);
tree.reveal(tree.getFocus());
}
}
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.select',
weight: KeybindingWeight.WorkbenchContrib,
when: WorkbenchListFocusContextKey,
primary: KeyCode.Enter,
mac: {
primary: KeyCode.Enter,
secondary: [KeyMod.CtrlCmd | KeyCode.DownArrow]
},
handler: (accessor) => {
const focused = accessor.get(IListService).lastFocusedList;
// List
if (focused instanceof List || focused instanceof PagedList) {
const list = focused;
list.setSelection(list.getFocus());
list.open(list.getFocus());
}
// ObjectTree
else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
const list = focused;
const fakeKeyboardEvent = new KeyboardEvent('keydown');
list.setSelection(list.getFocus(), fakeKeyboardEvent);
list.open(list.getFocus());
}
// Tree
else if (focused) {
const tree = focused;
const focus = tree.getFocus();
if (focus) {
tree.setSelection([focus], { origin: 'keyboard' });
}
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.selectAll',
weight: KeybindingWeight.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: KeybindingWeight.WorkbenchContrib,
when: WorkbenchListFocusContextKey,
primary: KeyCode.Space,
handler: (accessor) => {
const focused = accessor.get(IListService).lastFocusedList;
// Tree only
if (focused && !(focused instanceof List || focused instanceof PagedList)) {
if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
const tree = focused;
const focus = tree.getFocus();
if (focus.length === 0) {
return;
}
tree.toggleCollapsed(focus[0]);
} else {
const tree = focused;
const focus = tree.getFocus();
if (focus) {
tree.toggleExpansion(focus);
}
}
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.clear',
weight: KeybindingWeight.WorkbenchContrib,
when: ContextKeyExpr.and(WorkbenchListFocusContextKey, WorkbenchListHasSelectionOrFocus),
primary: KeyCode.Escape,
handler: (accessor) => {
const focused = accessor.get(IListService).lastFocusedList;
// List
if (focused instanceof List || focused instanceof PagedList) {
const list = focused;
if (list.getSelection().length > 0) {
list.setSelection([]);
} else if (list.getFocus().length > 0) {
list.setFocus([]);
}
}
// ObjectTree
else if (focused instanceof ObjectTree || focused instanceof AsyncDataTree) {
const list = focused;
const fakeKeyboardEvent = new KeyboardEvent('keydown');
if (list.getSelection().length > 0) {
list.setSelection([], fakeKeyboardEvent);
} else if (list.getFocus().length > 0) {
list.setFocus([], fakeKeyboardEvent);
}
}
// Tree
else if (focused) {
const tree = focused;
if (tree.getSelection().length) {
tree.clearSelection({ origin: 'keyboard' });
} else if (tree.getFocus()) {
tree.clearFocus({ origin: 'keyboard' });
}
}
}
});
// --- commands
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'workbench.action.closeWindow', // close the window when the last editor is closed by reusing the same keybinding
weight: KeybindingWeight.WorkbenchContrib,
when: ContextKeyExpr.and(NoEditorsVisibleContext, SingleEditorGroupsContext),
primary: KeyMod.CtrlCmd | KeyCode.KEY_W,
handler: accessor => {
const windowService = accessor.get(IWindowService);
windowService.closeWindow();
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'workbench.action.exitZenMode',
weight: KeybindingWeight.EditorContrib - 1000,
handler(accessor: ServicesAccessor, configurationOrName: any) {
const partService = accessor.get(IPartService);
partService.toggleZenMode();
},
when: InEditorZenModeContext,
primary: KeyChord(KeyCode.Escape, KeyCode.Escape)
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: QUIT_ID,
weight: KeybindingWeight.WorkbenchContrib,
handler(accessor: ServicesAccessor) {
const windowsService = accessor.get(IWindowsService);
windowsService.quit();
},
when: void 0,
primary: KeyMod.CtrlCmd | KeyCode.KEY_Q,
win: { primary: void 0 }
});
CommandsRegistry.registerCommand('_workbench.removeFromRecentlyOpened', function (accessor: ServicesAccessor, path: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI | string) {
const windowsService = accessor.get(IWindowsService);
return windowsService.removeFromRecentlyOpened([path]).then(() => void 0);
});
CommandsRegistry.registerCommand('_workbench.downloadResource', function (accessor: ServicesAccessor, resource: URI) {
const downloadService = accessor.get(IDownloadService);
const location = posix.join(tmpdir(), generateUuid());
return downloadService.download(resource, location).then(() => URI.file(location));
});
}

View File

@@ -5,14 +5,13 @@
import * as nls from 'vs/nls';
import * as perf from 'vs/base/common/performance';
import { WorkbenchShell } from 'vs/workbench/electron-browser/shell';
import { Shell } from 'vs/workbench/electron-browser/shell';
import * as browser from 'vs/base/browser/browser';
import { domContentLoaded } from 'vs/base/browser/dom';
import { onUnexpectedError } from 'vs/base/common/errors';
import * as comparer from 'vs/base/common/comparers';
import * as platform from 'vs/base/common/platform';
import { URI as uri } from 'vs/base/common/uri';
import { IWorkspaceContextService, Workspace, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
@@ -22,7 +21,6 @@ import * as gracefulFs from 'graceful-fs';
import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/keybindingService';
import { IWindowConfiguration, IWindowsService } from 'vs/platform/windows/common/windows';
import { WindowsChannelClient } from 'vs/platform/windows/node/windowsIpc';
import { IStorageLegacyService, StorageLegacyService, inMemoryLocalStorageInstance, IStorageLegacy } from 'vs/platform/storage/common/storageLegacyService';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
import { webFrame } from 'electron';
@@ -35,7 +33,7 @@ import { IWorkspacesService, ISingleFolderWorkspaceIdentifier, IWorkspaceInitial
import { createSpdLogService } from 'vs/platform/log/node/spdlogService';
import * as fs from 'fs';
import { ConsoleLogService, MultiplexLogService, ILogService } from 'vs/platform/log/common/log';
import { StorageService, DelegatingStorageService } from 'vs/platform/storage/node/storageService';
import { StorageService } from 'vs/platform/storage/node/storageService';
import { IssueChannelClient } from 'vs/platform/issue/node/issueIpc';
import { IIssueService } from 'vs/platform/issue/common/issue';
import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/node/logIpc';
@@ -61,8 +59,7 @@ export function startup(configuration: IWindowConfiguration): Promise<void> {
perf.importEntries(configuration.perfEntries);
// Configure emitter leak warning threshold
setGlobalLeakWarningThreshold(-1);
setGlobalLeakWarningThreshold(175);
// Browser config
browser.setZoomFactor(webFrame.getZoomFactor()); // Ensure others can listen to zoom level changes
@@ -124,13 +121,13 @@ function openWorkbench(configuration: IWindowConfiguration): Promise<void> {
createStorageService(payload, environmentService, logService, mainProcessClient)
]).then(services => {
const workspaceService = services[0];
const storageService = new DelegatingStorageService(services[1], createStorageLegacyService(workspaceService, environmentService), logService, workspaceService);
const storageService = services[1];
return domContentLoaded().then(() => {
perf.mark('willStartWorkbench');
// Create Shell
const shell = new WorkbenchShell(document.body, {
const shell = new Shell(document.body, {
contextService: workspaceService,
configurationService: workspaceService,
environmentService,
@@ -167,7 +164,7 @@ function createWorkspaceInitializationPayload(configuration: IWindowConfiguratio
}
// Single-folder workspace
let workspaceInitializationPayload: Promise<IWorkspaceInitializationPayload> = Promise.resolve(void 0);
let workspaceInitializationPayload: Promise<IWorkspaceInitializationPayload> = Promise.resolve();
if (configuration.folderUri) {
workspaceInitializationPayload = resolveSingleFolderWorkspaceInitializationPayload(configuration.folderUri);
}
@@ -240,7 +237,7 @@ function createWorkspaceService(payload: IWorkspaceInitializationPayload, enviro
});
}
function createStorageService(payload: IWorkspaceInitializationPayload, environmentService: IEnvironmentService, logService: ILogService, mainProcessClient: ElectronIPCClient): Thenable<StorageService> {
function createStorageService(payload: IWorkspaceInitializationPayload, environmentService: IEnvironmentService, logService: ILogService, mainProcessClient: ElectronIPCClient): Promise<StorageService> {
const globalStorageDatabase = new GlobalStorageDatabaseChannelClient(mainProcessClient.getChannel('storage'));
const storageService = new StorageService(globalStorageDatabase, logService, environmentService);
@@ -252,46 +249,6 @@ function createStorageService(payload: IWorkspaceInitializationPayload, environm
});
}
function createStorageLegacyService(workspaceService: IWorkspaceContextService, environmentService: IEnvironmentService): IStorageLegacyService {
let workspaceId: string;
switch (workspaceService.getWorkbenchState()) {
// in multi root workspace mode we use the provided ID as key for workspace storage
case WorkbenchState.WORKSPACE:
workspaceId = uri.from({ path: workspaceService.getWorkspace().id, scheme: 'root' }).toString();
break;
// in single folder mode we use the path of the opened folder as key for workspace storage
// the ctime is used as secondary workspace id to clean up stale UI state if necessary
case WorkbenchState.FOLDER:
const workspace: Workspace = <Workspace>workspaceService.getWorkspace();
workspaceId = workspace.folders[0].uri.toString();
break;
// finally, if we do not have a workspace open, we need to find another identifier for the window to store
// workspace UI state. if we have a backup path in the configuration we can use that because this
// will be a unique identifier per window that is stable between restarts as long as there are
// dirty files in the workspace.
// We use basename() to produce a short identifier, we do not need the full path. We use a custom
// scheme so that we can later distinguish these identifiers from the workspace one.
case WorkbenchState.EMPTY:
workspaceId = workspaceService.getWorkspace().id;
break;
}
const disableStorage = !!environmentService.extensionTestsPath; // never keep any state when running extension tests!
let storage: IStorageLegacy;
if (disableStorage) {
storage = inMemoryLocalStorageInstance;
} else {
storage = window.localStorage;
}
return new StorageLegacyService(storage, storage, workspaceId);
}
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);

View File

@@ -1 +0,0 @@
<svg width="13" height="13" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M6.5 0C2.91 0 0 2.91 0 6.5S2.91 13 6.5 13 13 10.09 13 6.5 10.09 0 6.5 0zm3.9 9.1l-1.3 1.3-2.6-2.6-2.6 2.6-1.3-1.3 2.6-2.635L2.6 3.9l1.3-1.3 2.6 2.6 2.6-2.6 1.3 1.3-2.6 2.565L10.4 9.1z" fill="#aaa"/></g></svg>

Before

Width:  |  Height:  |  Size: 335 B

View File

@@ -15,16 +15,39 @@
/* Font Families (with CJK support) */
.monaco-shell,
.monaco-shell .monaco-menu-container .monaco-menu { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", "Ubuntu", "Droid Sans", sans-serif; }
.monaco-shell:lang(zh-Hans),
.monaco-shell:lang(zh-Hans) .monaco-menu-container .monaco-menu { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", "Noto Sans", "Microsoft YaHei", "PingFang SC", "Hiragino Sans GB", "Source Han Sans SC", "Source Han Sans CN", "Source Han Sans", sans-serif; }
.monaco-shell:lang(zh-Hant),
.monaco-shell:lang(zh-Hant) .monaco-menu-container .monaco-menu { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", "Noto Sans", "Microsoft Jhenghei", "PingFang TC", "Source Han Sans TC", "Source Han Sans", "Source Han Sans TW", sans-serif; }
.monaco-shell:lang(ja),
.monaco-shell:lang(ja) .monaco-menu-container .monaco-menu { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", "Noto Sans", "Meiryo", "Hiragino Kaku Gothic Pro", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", "Sazanami Gothic", "IPA Gothic", sans-serif; }
.monaco-shell:lang(ko),
.monaco-shell:lang(ko) .monaco-menu-container .monaco-menu { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", "Noto Sans", "Malgun Gothic", "Nanum Gothic", "Dotom", "Apple SD Gothic Neo", "AppleGothic", "Source Han Sans K", "Source Han Sans JR", "Source Han Sans", "UnDotum", "FBaekmuk Gulim", sans-serif; }
/* mac */
.monaco-shell.mac,
.monaco-shell.mac .monaco-menu-container .monaco-menu { font-family: -apple-system, BlinkMacSystemFont, sans-serif; }
.monaco-shell.mac:lang(zh-Hans),
.monaco-shell.mac:lang(zh-Hans) .monaco-menu-container .monaco-menu { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", sans-serif; }
.monaco-shell.mac:lang(zh-Hant),
.monaco-shell.mac:lang(zh-Hant) .monaco-menu-container .monaco-menu { font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif; }
.monaco-shell.mac:lang(ja),
.monaco-shell.mac:lang(ja) .monaco-menu-container .monaco-menu { font-family: -apple-system, BlinkMacSystemFont, "Hiragino Kaku Gothic Pro", sans-serif; }
.monaco-shell.mac:lang(ko),
.monaco-shell.mac:lang(ko) .monaco-menu-container .monaco-menu { font-family: -apple-system, BlinkMacSystemFont, "Nanum Gothic", "Apple SD Gothic Neo", "AppleGothic", sans-serif; }
/* windows */
.monaco-shell.windows,
.monaco-shell.windows .monaco-menu-container .monaco-menu { font-family: "Segoe WPC", "Segoe UI", sans-serif; }
.monaco-shell.windows:lang(zh-Hans),
.monaco-shell.windows:lang(zh-Hans) .monaco-menu-container .monaco-menu { font-family: "Segoe WPC", "Segoe UI", "Microsoft YaHei", sans-serif; }
.monaco-shell.windows:lang(zh-Hant),
.monaco-shell.windows:lang(zh-Hant) .monaco-menu-container .monaco-menu { font-family: "Segoe WPC", "Segoe UI", "Microsoft Jhenghei", sans-serif; }
.monaco-shell.windows:lang(ja),
.monaco-shell.windows:lang(ja) .monaco-menu-container .monaco-menu { font-family: "Segoe WPC", "Segoe UI", "Meiryo", sans-serif; }
.monaco-shell.windows:lang(ko),
.monaco-shell.windows:lang(ko) .monaco-menu-container .monaco-menu { font-family: "Segoe WPC", "Segoe UI", "Malgun Gothic", "Dotom", sans-serif; }
/* linux */
.monaco-shell.linux,
.monaco-shell.linux .monaco-menu-container .monaco-menu { font-family: "Ubuntu", "Droid Sans", sans-serif; }
.monaco-shell.linux:lang(zh-Hans),
.monaco-shell.linux:lang(zh-Hans) .monaco-menu-container .monaco-menu { font-family: "Ubuntu", "Droid Sans", "Source Han Sans SC", "Source Han Sans CN", "Source Han Sans", sans-serif; }
.monaco-shell.linux:lang(zh-Hant),
.monaco-shell.linux:lang(zh-Hant) .monaco-menu-container .monaco-menu { font-family: "Ubuntu", "Droid Sans", "Source Han Sans TC", "Source Han Sans TW", "Source Han Sans", sans-serif; }
.monaco-shell.linux:lang(ja),
.monaco-shell.linux:lang(ja) .monaco-menu-container .monaco-menu { font-family: "Ubuntu", "Droid Sans", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", sans-serif; }
.monaco-shell.linux:lang(ko),
.monaco-shell.linux:lang(ko) .monaco-menu-container .monaco-menu { font-family: "Ubuntu", "Droid Sans", "Source Han Sans K", "Source Han Sans JR", "Source Han Sans", "UnDotum", "FBaekmuk Gulim", sans-serif; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@@ -99,12 +122,17 @@
margin-bottom: 0.2em;
}
.monaco-shell.linux .monaco-menu .monaco-action-bar.vertical .action-label.separator {
margin-left: 0;
margin-right: 0;
}
.monaco-shell .monaco-menu .monaco-action-bar.vertical .submenu-indicator {
font-size: 60%;
padding: 0 1.8em;
}
.monaco-shell .linux .monaco-menu .monaco-action-bar.vertical .submenu-indicator {
.monaco-shell.linux .monaco-menu .monaco-action-bar.vertical .submenu-indicator {
height: 100%;
-webkit-mask-size: 10px 10px;
mask-size: 10px 10px;
@@ -179,4 +207,4 @@
.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

@@ -11,7 +11,7 @@
overflow: hidden;
}
.monaco-workbench > .part {
.monaco-workbench .part {
position: absolute;
box-sizing: border-box;
}

View File

@@ -20,14 +20,14 @@ export class ResourceGlobMatcher extends Disposable {
private readonly _onExpressionChange: Emitter<void> = this._register(new Emitter<void>());
get onExpressionChange(): Event<void> { return this._onExpressionChange.event; }
private mapRootToParsedExpression: Map<string, ParsedExpression>;
private mapRootToExpressionConfig: Map<string, IExpression>;
private mapRootToParsedExpression: Map<string | null, ParsedExpression>;
private mapRootToExpressionConfig: Map<string | null, IExpression>;
constructor(
private globFn: (root?: URI) => IExpression,
private shouldUpdate: (event: IConfigurationChangeEvent) => boolean,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IConfigurationService private configurationService: IConfigurationService
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IConfigurationService private readonly configurationService: IConfigurationService
) {
super();
@@ -69,7 +69,7 @@ export class ResourceGlobMatcher extends Disposable {
return; // always keep this one
}
if (!this.contextService.getWorkspaceFolder(URI.parse(root))) {
if (root && !this.contextService.getWorkspaceFolder(URI.parse(root))) {
this.mapRootToParsedExpression.delete(root);
this.mapRootToExpressionConfig.delete(root);
@@ -96,9 +96,9 @@ export class ResourceGlobMatcher extends Disposable {
let expressionForRoot: ParsedExpression;
if (folder && this.mapRootToParsedExpression.has(folder.uri.toString())) {
expressionForRoot = this.mapRootToParsedExpression.get(folder.uri.toString());
expressionForRoot = this.mapRootToParsedExpression.get(folder.uri.toString())!;
} else {
expressionForRoot = this.mapRootToParsedExpression.get(ResourceGlobMatcher.NO_ROOT);
expressionForRoot = this.mapRootToParsedExpression.get(ResourceGlobMatcher.NO_ROOT)!;
}
// If the resource if from a workspace, convert its absolute path to a relative

View File

@@ -12,19 +12,47 @@ import { IConfigurationRegistry, Extensions as ConfigurationExtensions, Configur
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 { KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, OpenIssueReporterAction, ReportPerformanceIssueUsingReporterAction, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleFullScreenAction, ToggleMenuBarAction, CloseWorkspaceAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, NavigateUpAction, NavigateDownAction, NavigateLeftAction, NavigateRightAction, IncreaseViewSizeAction, DecreaseViewSizeAction, ToggleSharedProcessAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, ShowAboutDialogAction, InspectContextKeysAction, OpenProcessExplorer, OpenTwitterUrlAction, OpenRequestFeatureUrlAction, OpenPrivacyStatementUrlAction, OpenLicenseUrlAction, OpenRecentAction } from 'vs/workbench/electron-browser/actions';
import { registerCommands, QUIT_ID } from 'vs/workbench/electron-browser/commands';
import { AddRootFolderAction, GlobalRemoveRootFolderAction, OpenWorkspaceAction, SaveWorkspaceAsAction, OpenWorkspaceConfigFileAction, DuplicateWorkspaceInNewWindowAction, OpenFileFolderAction, OpenFileAction, OpenFolderAction } from 'vs/workbench/browser/actions/workspaceActions';
import { KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, OpenIssueReporterAction, ReportPerformanceIssueUsingReporterAction, OpenProcessExplorer, OpenTwitterUrlAction, OpenRequestFeatureUrlAction, OpenPrivacyStatementUrlAction, OpenLicenseUrlAction } from 'vs/workbench/electron-browser/actions/helpActions';
import { ToggleSharedProcessAction, InspectContextKeysAction, ToggleScreencastModeAction } from 'vs/workbench/electron-browser/actions/developerActions';
import { ShowAboutDialogAction, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleFullScreenAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, OpenRecentAction } from 'vs/workbench/electron-browser/actions/windowActions';
import { AddRootFolderAction, GlobalRemoveRootFolderAction, OpenWorkspaceAction, SaveWorkspaceAsAction, OpenWorkspaceConfigFileAction, DuplicateWorkspaceInNewWindowAction, OpenFileFolderAction, OpenFileAction, OpenFolderAction, CloseWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';
import { ContextKeyExpr, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { inQuickOpenContext, getQuickNavigateHandler } from 'vs/workbench/browser/parts/quickopen/quickopen';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ADD_ROOT_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands';
import { IsMacContext } from 'vs/platform/workbench/common/contextkeys';
import { NoEditorsVisibleContext, SingleEditorGroupsContext } from 'vs/workbench/common/editor';
import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows';
// {{SQL CARBON EDIT}}
import { InstallVSIXAction } from 'vs/workbench/parts/extensions/electron-browser/extensionsActions';
// {{SQL CARBON EDIT}} - End
// Contribute Commands
registerCommands();
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'workbench.action.closeWindow', // close the window when the last editor is closed by reusing the same keybinding
weight: KeybindingWeight.WorkbenchContrib,
when: ContextKeyExpr.and(NoEditorsVisibleContext, SingleEditorGroupsContext),
primary: KeyMod.CtrlCmd | KeyCode.KEY_W,
handler: accessor => {
const windowService = accessor.get(IWindowService);
windowService.closeWindow();
}
});
const QUIT_ID = 'workbench.action.quit';
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: QUIT_ID,
weight: KeybindingWeight.WorkbenchContrib,
handler(accessor: ServicesAccessor) {
const windowsService = accessor.get(IWindowsService);
windowsService.quit();
},
when: undefined,
primary: KeyMod.CtrlCmd | KeyCode.KEY_Q,
win: { primary: undefined }
});
// Contribute Global Actions
const viewCategory = nls.localize('view', "View");
@@ -93,16 +121,6 @@ workbenchActionsRegistry.registerWorkbenchAction(
);
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);
}
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(NavigateUpAction, NavigateUpAction.ID, NavigateUpAction.LABEL, null), 'View: Navigate to the View Above', viewCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(NavigateDownAction, NavigateDownAction.ID, NavigateDownAction.LABEL, null), 'View: Navigate to the View Below', viewCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(NavigateLeftAction, NavigateLeftAction.ID, NavigateLeftAction.LABEL, null), 'View: Navigate to the View on the Left', viewCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(NavigateRightAction, NavigateRightAction.ID, NavigateRightAction.LABEL, null), 'View: Navigate to the View on the Right', viewCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(IncreaseViewSizeAction, IncreaseViewSizeAction.ID, IncreaseViewSizeAction.LABEL, null), 'View: Increase Current View Size', viewCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(DecreaseViewSizeAction, DecreaseViewSizeAction.ID, DecreaseViewSizeAction.LABEL, null), 'View: Decrease Current View Size', viewCategory);
const workspacesCategory = nls.localize('workspaces', "Workspaces");
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(AddRootFolderAction, AddRootFolderAction.ID, AddRootFolderAction.LABEL), 'Workspaces: Add Folder to Workspace...', workspacesCategory);
@@ -126,6 +144,7 @@ MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
const developerCategory = nls.localize('developer', "Developer");
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);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleScreencastModeAction, ToggleScreencastModeAction.ID, ToggleScreencastModeAction.LABEL), 'Developer: Toggle Mouse Clicks', developerCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenProcessExplorer, OpenProcessExplorer.ID, OpenProcessExplorer.LABEL), 'Developer: Open Process Explorer', developerCategory);
const recentFilesPickerContext = ContextKeyExpr.and(inQuickOpenContext, ContextKeyExpr.has(inRecentFilesPickerContextKey));
@@ -207,6 +226,15 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
order: 4
});
// {{SQL CARBON EDIT}} - Add install VSIX menu item
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
group: '5.1_installExtension',
command: {
id: InstallVSIXAction.ID,
title: nls.localize({ key: 'miinstallVsix', comment: ['&& denotes a mnemonic'] }, "Install Extension from VSIX Package")
}
});
// {{SQL CARBON EDIT}} - End
// More
MenuRegistry.appendMenuItem(MenuId.MenubarRecentMenu, {
@@ -301,16 +329,6 @@ MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
group: '1_toggle_view',
command: {
id: ToggleMenuBarAction.ID,
title: nls.localize({ key: 'miToggleMenuBar', comment: ['&& denotes a mnemonic'] }, "Toggle Menu &&Bar")
},
when: IsMacContext.toNegated(),
order: 4
});
// Zoom
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
@@ -351,61 +369,67 @@ MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
order: 3
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '1_welcome',
command: {
id: 'update.showCurrentReleaseNotes',
title: nls.localize({ key: 'miReleaseNotes', comment: ['&& denotes a mnemonic'] }, "&&Release Notes")
},
order: 4
});
// {{SQL CARBON EDIT}} - Disable unused menu item
// MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
// group: '1_welcome',
// command: {
// id: 'update.showCurrentReleaseNotes',
// title: nls.localize({ key: 'miReleaseNotes', comment: ['&& denotes a mnemonic'] }, "&&Release Notes")
// },
// order: 4
// });
// {{SQL CARBON EDIT}} - End
// Reference
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '2_reference',
command: {
id: 'workbench.action.keybindingsReference',
title: nls.localize({ key: 'miKeyboardShortcuts', comment: ['&& denotes a mnemonic'] }, "&&Keyboard Shortcuts Reference")
},
order: 1
});
// {{SQL CARBON EDIT}} - Disable unused menu items
// MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
// group: '2_reference',
// command: {
// id: 'workbench.action.keybindingsReference',
// title: nls.localize({ key: 'miKeyboardShortcuts', comment: ['&& denotes a mnemonic'] }, "&&Keyboard Shortcuts Reference")
// },
// order: 1
// });
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '2_reference',
command: {
id: 'workbench.action.openIntroductoryVideosUrl',
title: nls.localize({ key: 'miIntroductoryVideos', comment: ['&& denotes a mnemonic'] }, "Introductory &&Videos")
},
order: 2
});
// MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
// group: '2_reference',
// command: {
// id: 'workbench.action.openIntroductoryVideosUrl',
// title: nls.localize({ key: 'miIntroductoryVideos', comment: ['&& denotes a mnemonic'] }, "Introductory &&Videos")
// },
// order: 2
// });
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '2_reference',
command: {
id: 'workbench.action.openTipsAndTricksUrl',
title: nls.localize({ key: 'miTipsAndTricks', comment: ['&& denotes a mnemonic'] }, "&&Tips and Tricks")
},
order: 3
});
// MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
// group: '2_reference',
// command: {
// id: 'workbench.action.openTipsAndTricksUrl',
// title: nls.localize({ key: 'miTipsAndTricks', comment: ['&& denotes a mnemonic'] }, "Tips and Tri&&cks")
// },
// order: 3
// });
// {{SQL CARBON EDIT}} - End
// Feedback
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '3_feedback',
command: {
id: 'workbench.action.openTwitterUrl',
title: nls.localize({ key: 'miTwitter', comment: ['&& denotes a mnemonic'] }, "&&Join Us on Twitter")
},
order: 1
});
// {{SQL CARBON EDIT}} - Disable unused menu items
// MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
// group: '3_feedback',
// command: {
// id: 'workbench.action.openTwitterUrl',
// title: nls.localize({ key: 'miTwitter', comment: ['&& denotes a mnemonic'] }, "&&Join Us on Twitter")
// },
// order: 1
// });
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '3_feedback',
command: {
id: 'workbench.action.openRequestFeatureUrl',
title: nls.localize({ key: 'miUserVoice', comment: ['&& denotes a mnemonic'] }, "&&Search Feature Requests")
},
order: 2
});
// MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
// group: '3_feedback',
// command: {
// id: 'workbench.action.openRequestFeatureUrl',
// title: nls.localize({ key: 'miUserVoice', comment: ['&& denotes a mnemonic'] }, "&&Search Feature Requests")
// },
// order: 2
// });
// {{SQL CARBON EDIT}} - End
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '3_feedback',
@@ -430,7 +454,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '4_legal',
command: {
id: 'workbench.action.openPrivacyStatementUrl',
title: nls.localize({ key: 'miPrivacyStatement', comment: ['&& denotes a mnemonic'] }, "&&Privacy Statement")
title: nls.localize({ key: 'miPrivacyStatement', comment: ['&& denotes a mnemonic'] }, "Privac&&y Statement")
},
order: 2
});
@@ -465,231 +489,8 @@ MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
when: IsMacContext.toNegated()
});
// Configuration: Workbench
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
configurationRegistry.registerConfiguration({
'id': 'workbench',
'order': 7,
'title': nls.localize('workbenchConfigurationTitle', "Workbench"),
'type': 'object',
'properties': {
'workbench.editor.showTabs': {
'type': 'boolean',
'description': nls.localize('showEditorTabs', "Controls whether opened editors should show in tabs or not."),
'default': true
},
'workbench.editor.highlightModifiedTabs': {
'type': 'boolean',
'description': nls.localize('highlightModifiedTabs', "Controls whether a top border is drawn on modified (dirty) editor tabs or not."),
'default': false
},
'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 distinguishing 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 its directory name."),
nls.localize('workbench.editor.labelFormat.medium', "Show the name of the file followed by its path relative to the workspace folder."),
nls.localize('workbench.editor.labelFormat.long', "Show the name of the file followed by its 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."),
},
'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',
'enumDescriptions': [
nls.localize('workbench.editor.tabSizing.fit', "Always keep tabs large enough to show the full editor label."),
nls.localize('workbench.editor.tabSizing.shrink', "Allow tabs to get smaller when the available space is not enough to show all tabs at once.")
],
'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.")
},
'workbench.editor.showIcons': {
'type': 'boolean',
'description': nls.localize('showIcons', "Controls whether 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 whether opened editors show as preview. Preview editors are reused until they are pinned (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 whether opened editors from Quick Open show as preview. Preview editors are reused until they are pinned (e.g. via double click or editing)."),
'default': true
},
'workbench.editor.closeOnFileDelete': {
'type': 'boolean',
'description': nls.localize('closeOnFileDelete', "Controls whether editors showing a file that was opened during the session should close automatically when getting deleted or renamed by some other process. Disabling this will keep the editor open 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': false
},
'workbench.editor.openPositioning': {
'type': 'string',
'enum': ['left', 'right', 'first', 'last'],
'default': 'right',
'markdownDescription': 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.openSideBySideDirection': {
'type': 'string',
'enum': ['right', 'down'],
'default': 'right',
'markdownDescription': nls.localize('sideBySideDirection', "Controls the default direction of editors that are opened side by side (e.g. from the explorer). By default, editors will open on the right hand side of the currently active one. If changed to `down`, the editors will open below the currently active one.")
},
'workbench.editor.closeEmptyGroups': {
'type': 'boolean',
'description': nls.localize('closeEmptyGroups', "Controls the behavior of empty editor groups when the last tab in the group is closed. When enabled, empty groups will automatically close. When disabled, empty groups will remain part of the grid."),
'default': true
},
'workbench.editor.revealIfOpen': {
'type': 'boolean',
'description': nls.localize('revealIfOpen', "Controls whether 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.editor.restoreViewState': {
'type': 'boolean',
'description': nls.localize('restoreViewState', "Restores the last view state (e.g. scroll position) when re-opening files after they have been closed."),
'default': true,
},
'workbench.editor.centeredLayoutAutoResize': {
'type': 'boolean',
'default': true,
'description': nls.localize('centeredLayoutAutoResize', "Controls if the centered layout should automatically resize to maximum width when more than one group is open. Once only one group is open it will resize back to the original centered width.")
},
'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 whether 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 whether Quick Open should close automatically once it loses focus."),
'default': true
},
'workbench.quickOpen.preserveInput': {
'type': 'boolean',
'description': nls.localize('workbench.quickOpen.preserveInput', "Controls whether the last typed input to Quick Open should be restored when opening it the next time."),
'default': false
},
'workbench.settings.openDefaultSettings': {
'type': 'boolean',
'description': nls.localize('openDefaultSettings', "Controls whether opening settings also opens an editor showing all default settings."),
'default': true
},
'workbench.settings.openDefaultKeybindings': {
'type': 'boolean',
'description': nls.localize('openDefaultKeybindings', "Controls whether opening keybinding settings also opens an editor showing all default keybindings."),
'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 (terminal, debug console, output, problems). 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."),
'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. The natural language search is provided by a Microsoft online service."),
'default': true,
'scope': ConfigurationScope.WINDOW,
'tags': ['usesOnlineServices']
},
'workbench.settings.settingsSearchTocBehavior': {
'type': 'string',
'enum': ['hide', 'filter'],
'enumDescriptions': [
nls.localize('settingsSearchTocBehavior.hide', "Hide the Table of Contents while searching."),
nls.localize('settingsSearchTocBehavior.filter', "Filter the Table of Contents to just categories that have matching settings. Clicking a category will filter the results to that category."),
],
'description': nls.localize('settingsSearchTocBehavior', "Controls the behavior of the settings editor Table of Contents while searching."),
'default': 'filter',
'scope': ConfigurationScope.WINDOW
},
'workbench.settings.editor': {
'type': 'string',
'enum': ['ui', 'json'],
'enumDescriptions': [
nls.localize('settings.editor.ui', "Use the settings UI editor."),
nls.localize('settings.editor.json', "Use the JSON file editor."),
],
'description': nls.localize('settings.editor.desc', "Determines which settings editor to use by default."),
'default': 'ui',
'scope': ConfigurationScope.WINDOW
},
'workbench.enableExperiments': {
'type': 'boolean',
'description': nls.localize('workbench.enableExperiments', "Fetches experiments to run from a Microsoft online service."),
'default': true,
'tags': ['usesOnlineServices']
},
//TODO@Ben remove ('enableLegacyStorage') after a while
'workbench.enableLegacyStorage': {
'type': 'boolean',
'description': nls.localize('workbench.enableLegacyStorage', "Switches back to the previous storage implementation. Only change this setting if advised to do so."),
'default': false
}
}
});
// Configuration: Window
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
configurationRegistry.registerConfiguration({
'id': 'window',
'order': 8,
@@ -764,7 +565,7 @@ configurationRegistry.registerConfiguration({
'type': 'string',
'default': isMacintosh ? '${activeEditorShort}${separator}${rootName}' : '${dirty}${activeEditorShort}${separator}${rootName}${separator}${appName}',
'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by parenthesis are not to be translated.'], key: 'title' },
"Controls the window title based on the active editor. Variables are substituted based on the context:\n- `\${activeEditorShort}`: the file name (e.g. myFile.txt).\n- `\${activeEditorMedium}`: the path of the file relative to the workspace folder (e.g. myFolder/myFile.txt).\n- `\${activeEditorLong}`: the full path of the file (e.g. /Users/Development/myProject/myFolder/myFile.txt).\n- `\${folderName}`: name of the workspace folder the file is contained in (e.g. myFolder).\n- `\${folderPath}`: file path of the workspace folder the file is contained in (e.g. /Users/Development/myFolder).\n- `\${rootName}`: name of the workspace (e.g. myFolder or myWorkspace).\n- `\${rootPath}`: file path of the workspace (e.g. /Users/Development/myWorkspace).\n- `\${appName}`: e.g. VS Code.\n- `\${dirty}`: a dirty indicator if the active editor is dirty.\n- `\${separator}`: a conditional separator (\" - \") that only shows when surrounded by variables with values or static text.")
"Controls the window title based on the active editor. Variables are substituted based on the context:\n- `\${activeEditorShort}`: the file name (e.g. myFile.txt).\n- `\${activeEditorMedium}`: the path of the file relative to the workspace folder (e.g. myFolder/myFileFolder/myFile.txt).\n- `\${activeEditorLong}`: the full path of the file (e.g. /Users/Development/myFolder/myFileFolder/myFile.txt).\n- `\${activeFolderShort}`: the name of the folder the file is contained in (e.g. myFileFolder).\n- `\${activeFolderMedium}`: the path of the folder the file is contained in, relative to the workspace folder (e.g. myFolder/myFileFolder).\n- `\${activeFolderLong}`: the full path of the folder the file is contained in (e.g. /Users/Development/myFolder/myFileFolder).\n- `\${folderName}`: name of the workspace folder the file is contained in (e.g. myFolder).\n- `\${folderPath}`: file path of the workspace folder the file is contained in (e.g. /Users/Development/myFolder).\n- `\${rootName}`: name of the workspace (e.g. myFolder or myWorkspace).\n- `\${rootPath}`: file path of the workspace (e.g. /Users/Development/myWorkspace).\n- `\${appName}`: e.g. VS Code.\n- `\${dirty}`: a dirty indicator if the active editor is dirty.\n- `\${separator}`: a conditional separator (\" - \") that only shows when surrounded by variables with values or static text.")
},
'window.newWindowDimensions': {
'type': 'string',
@@ -811,6 +612,12 @@ configurationRegistry.registerConfiguration({
'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
},
'window.doubleClickIconToClose': {
'type': 'boolean',
'default': false,
'scope': ConfigurationScope.APPLICATION,
'markdownDescription': nls.localize('window.doubleClickIconToClose', "If enabled, double clicking the application icon in the title bar will close the window and the window cannot be dragged by the icon. This setting only has an effect when `#window.titleBarStyle#` is set to `custom`.")
},
'window.titleBarStyle': {
'type': 'string',
'enum': ['native', 'custom'],
@@ -831,13 +638,6 @@ configurationRegistry.registerConfiguration({
'description': nls.localize('window.nativeFullScreen', "Controls if native full-screen should be used on macOS. Disable this option to prevent macOS from creating a new space when going full-screen."),
'included': isMacintosh
},
'window.smoothScrollingWorkaround': { // TODO@Ben remove once https://github.com/Microsoft/vscode/issues/61824 settles
'type': 'boolean',
'default': false,
'scope': ConfigurationScope.APPLICATION,
'markdownDescription': nls.localize('window.smoothScrollingWorkaround', "Enable this workaround if scrolling is no longer smooth after restoring a minimized VS Code window. This is a workaround for an issue (https://github.com/Microsoft/vscode/issues/13612) where scrolling starts to lag on devices with precision trackpads like the Surface devices from Microsoft. Enabling this workaround can result in a little bit of layout flickering after restoring the window from minimized state but is otherwise harmless."),
'included': isWindows
},
'window.clickThroughInactive': {
'type': 'boolean',
'default': true,
@@ -848,42 +648,3 @@ configurationRegistry.registerConfiguration({
}
});
// Configuration: Zen Mode
configurationRegistry.registerConfiguration({
'id': 'zenMode',
'order': 9,
'title': nls.localize('zenModeConfigurationTitle', "Zen Mode"),
'type': 'object',
'properties': {
'zenMode.fullScreen': {
'type': 'boolean',
'default': true,
'description': nls.localize('zenMode.fullScreen', "Controls whether turning on Zen Mode also puts the workbench into full screen mode.")
},
'zenMode.centerLayout': {
'type': 'boolean',
'default': true,
'description': nls.localize('zenMode.centerLayout', "Controls whether turning on Zen Mode also centers the layout.")
},
'zenMode.hideTabs': {
'type': 'boolean',
'default': true,
'description': nls.localize('zenMode.hideTabs', "Controls whether turning on Zen Mode also hides workbench tabs.")
},
'zenMode.hideStatusBar': {
'type': 'boolean',
'default': true,
'description': nls.localize('zenMode.hideStatusBar', "Controls whether turning on Zen Mode also hides the status bar at the bottom of the workbench.")
},
'zenMode.hideActivityBar': {
'type': 'boolean',
'default': true,
'description': nls.localize('zenMode.hideActivityBar', "Controls whether turning on Zen Mode also hides the activity bar at the left of the workbench.")
},
'zenMode.restore': {
'type': 'boolean',
'default': false,
'description': nls.localize('zenMode.restore', "Controls whether a window should restore to zen mode if it was exited in zen mode.")
}
}
});

View File

@@ -14,7 +14,6 @@ import { toErrorMessage } from 'vs/base/common/errorMessage';
import product from 'vs/platform/node/product';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import pkg from 'vs/platform/node/package';
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
import { Workbench, IWorkbenchStartedInfo } from 'vs/workbench/electron-browser/workbench';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService, configurationTelemetry, combinedAppender, LogAppender } from 'vs/platform/telemetry/common/telemetryUtils';
@@ -76,7 +75,7 @@ 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 { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { DelegatingStorageService } from 'vs/platform/storage/node/storageService';
import { StorageService } from 'vs/platform/storage/node/storageService';
import { Event, Emitter } from 'vs/base/common/event';
import { WORKBENCH_BACKGROUND } from 'vs/workbench/common/theme';
import { LocalizationsChannelClient } from 'vs/platform/localizations/node/localizationsIpc';
@@ -88,7 +87,7 @@ import { NotificationService } from 'vs/workbench/services/notification/common/n
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { DialogService } from 'vs/workbench/services/dialogs/electron-browser/dialogService';
import { DialogChannel } from 'vs/platform/dialogs/node/dialogIpc';
import { EventType, addDisposableListener, addClass, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
import { EventType, addDisposableListener, scheduleAtNextAnimationFrame, addClasses } from 'vs/base/browser/dom';
import { IRemoteAgentService } from 'vs/workbench/services/remote/node/remoteAgentService';
import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl';
import { IOpenerService } from 'vs/platform/opener/common/opener';
@@ -97,14 +96,17 @@ import { SearchHistoryService } from 'vs/workbench/services/search/node/searchHi
import { ExtensionManagementServerService } from 'vs/workbench/services/extensions/node/extensionManagementServerService';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService';
import { LogLevelSetterChannel } from 'vs/platform/log/node/logIpc';
import { ILabelService, LabelService } from 'vs/platform/label/common/label';
import { ILabelService } from 'vs/platform/label/common/label';
import { IDownloadService } from 'vs/platform/download/common/download';
import { DownloadService } from 'vs/platform/download/node/downloadService';
import { DownloadServiceChannel } from 'vs/platform/download/node/downloadIpc';
import { TextResourcePropertiesService } from 'vs/workbench/services/textfile/electron-browser/textResourcePropertiesService';
import { MulitExtensionManagementService } from 'vs/platform/extensionManagement/node/multiExtensionManagement';
import { MultiExtensionManagementService } from 'vs/platform/extensionManagement/node/multiExtensionManagement';
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { RemoteAuthorityResolverService } from 'vs/platform/remote/electron-browser/remoteAuthorityResolverService';
import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDecorationService';
import { MarkerDecorationsService } from 'vs/editor/common/services/markerDecorationsServiceImpl';
import { LabelService } from 'vs/workbench/services/label/common/labelService';
// {{SQL CARBON EDIT}}
import { FileTelemetryService } from 'sql/workbench/services/telemetry/node/fileTelemetryService';
@@ -117,19 +119,19 @@ export interface ICoreServices {
configurationService: IConfigurationService;
environmentService: IEnvironmentService;
logService: ILogService;
storageService: DelegatingStorageService;
storageService: StorageService;
}
/**
* 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 extends Disposable {
export class Shell extends Disposable {
private readonly _onWillShutdown = this._register(new Emitter<WillShutdownEvent>());
get onWillShutdown(): Event<WillShutdownEvent> { return this._onWillShutdown.event; }
private storageService: DelegatingStorageService;
private storageService: StorageService;
private environmentService: IEnvironmentService;
private logService: ILogService;
private configurationService: IConfigurationService;
@@ -227,7 +229,7 @@ export class WorkbenchShell extends Disposable {
} catch (error) {
handleStartupError(this.logService, error);
return void 0;
return undefined;
}
}
@@ -313,31 +315,41 @@ export class WorkbenchShell extends Disposable {
const globalStorageInitDurationMain = perf.getDuration('main:willInitGlobalStorage', 'main:didInitGlobalStorage');
const globalStorageInitDuratioRenderer = perf.getDuration('willInitGlobalStorage', 'didInitGlobalStorage');
const workspaceStorageInitDuration = perf.getDuration('willInitWorkspaceStorage', 'didInitWorkspaceStorage');
const workspaceStorageFileExistsDuration = perf.getDuration('willCheckWorkspaceStorageExists', 'didCheckWorkspaceStorageExists');
const workspaceStorageMigrationDuration = perf.getDuration('willMigrateWorkspaceStorageKeys', 'didMigrateWorkspaceStorageKeys');
const workbenchLoadDuration = perf.getDuration('willLoadWorkbenchMain', 'didLoadWorkbenchMain');
const localStorageDuration = perf.getDuration('willReadLocalStorage', 'didReadLocalStorage');
// Handle errors (avoid duplicates to reduce spam)
const loggedStorageErrors = new Set<string>();
this._register(this.storageService.storage.onWorkspaceStorageError(error => {
this._register(this.storageService.onWorkspaceStorageError(error => {
const errorStr = `${error}`;
if (!loggedStorageErrors.has(errorStr)) {
loggedStorageErrors.add(errorStr);
/* __GDPR__
"sqliteStorageError<NUMBER>" : {
"sqliteStorageError5" : {
"appReadyTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workbenchReadyTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceRequireTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceSchemaTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"globalReadTimeMain" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"globalReadTimeRenderer" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceReadTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workbenchRequireTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceKeys" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"startupKind": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"storageError": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
/* __GDPR__
"sqliteStorageError<NUMBER>" : {
"appReadyTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workbenchReadyTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceExistsTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceMigrationTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceRequireTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceSchemaTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"globalReadTimeMain" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"globalReadTimeRenderer" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceReadTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"localStorageTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workbenchRequireTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceKeys" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"startupKind": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
@@ -347,16 +359,13 @@ export class WorkbenchShell extends Disposable {
this.telemetryService.publicLog('sqliteStorageError5', {
'appReadyTime': appReadyDuration,
'workbenchReadyTime': workbenchReadyDuration,
'workspaceExistsTime': workspaceStorageFileExistsDuration,
'workspaceMigrationTime': workspaceStorageMigrationDuration,
'workspaceRequireTime': workspaceStorageRequireDuration,
'workspaceSchemaTime': workspaceStorageSchemaDuration,
'globalReadTimeMain': globalStorageInitDurationMain,
'globalReadTimeRenderer': globalStorageInitDuratioRenderer,
'workspaceReadTime': workspaceStorageInitDuration,
'localStorageTime': localStorageDuration,
'workbenchRequireTime': workbenchLoadDuration,
'workspaceKeys': this.storageService.storage.getSize(StorageScope.WORKSPACE),
'workspaceKeys': this.storageService.getSize(StorageScope.WORKSPACE),
'startupKind': this.lifecycleService.startupKind,
'storageError': errorStr
});
@@ -364,7 +373,7 @@ export class WorkbenchShell extends Disposable {
}));
if (this.storageService.storage.hasErrors) {
if (this.storageService.hasErrors) {
return; // do not log performance numbers when errors occured
}
@@ -373,17 +382,29 @@ export class WorkbenchShell extends Disposable {
}
/* __GDPR__
"sqliteStorageTimers<NUMBER>" : {
"sqliteStorageTimers5" : {
"appReadyTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workbenchReadyTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceRequireTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceSchemaTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"globalReadTimeMain" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"globalReadTimeRenderer" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceReadTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workbenchRequireTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceKeys" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"startupKind": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
}
*/
/* __GDPR__
"sqliteStorageTimers<NUMBER>" : {
"appReadyTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workbenchReadyTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceExistsTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceMigrationTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceRequireTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceSchemaTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"globalReadTimeMain" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"globalReadTimeRenderer" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceReadTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"localStorageTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workbenchRequireTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"workspaceKeys" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"startupKind": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
@@ -392,16 +413,13 @@ export class WorkbenchShell extends Disposable {
this.telemetryService.publicLog('sqliteStorageTimers5', {
'appReadyTime': appReadyDuration,
'workbenchReadyTime': workbenchReadyDuration,
'workspaceExistsTime': workspaceStorageFileExistsDuration,
'workspaceMigrationTime': workspaceStorageMigrationDuration,
'workspaceRequireTime': workspaceStorageRequireDuration,
'workspaceSchemaTime': workspaceStorageSchemaDuration,
'globalReadTimeMain': globalStorageInitDurationMain,
'globalReadTimeRenderer': globalStorageInitDuratioRenderer,
'workspaceReadTime': workspaceStorageInitDuration,
'localStorageTime': localStorageDuration,
'workbenchRequireTime': workbenchLoadDuration,
'workspaceKeys': this.storageService.storage.getSize(StorageScope.WORKSPACE),
'workspaceKeys': this.storageService.getSize(StorageScope.WORKSPACE),
'startupKind': this.lifecycleService.startupKind
});
}
@@ -411,7 +429,7 @@ export class WorkbenchShell extends Disposable {
serviceCollection.set(IWorkspaceContextService, this.contextService);
serviceCollection.set(IConfigurationService, this.configurationService);
serviceCollection.set(IEnvironmentService, this.environmentService);
serviceCollection.set(ILabelService, new SyncDescriptor(LabelService));
serviceCollection.set(ILabelService, new SyncDescriptor(LabelService, undefined, true));
serviceCollection.set(ILogService, this._register(this.logService));
serviceCollection.set(IStorageService, this.storageService);
@@ -430,14 +448,15 @@ export class WorkbenchShell extends Disposable {
serviceCollection.set(IWindowService, new SyncDescriptor(WindowService, [this.configuration.windowId, this.configuration]));
const sharedProcess = (<IWindowsService>serviceCollection.get(IWindowsService)).whenSharedProcessReady()
.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${this.configuration.windowId}`));
.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${this.configuration.windowId}`))
.then(client => {
client.registerChannel('dialog', instantiationService.createInstance(DialogChannel));
sharedProcess.then(client => {
client.registerChannel('dialog', instantiationService.createInstance(DialogChannel));
});
return client;
});
// Hash
serviceCollection.set(IHashService, new SyncDescriptor(HashService));
serviceCollection.set(IHashService, new SyncDescriptor(HashService, undefined, true));
// {{SQL CARBON EDIT}}
if (this.environmentService.args['perf-test']) {
@@ -478,9 +497,9 @@ export class WorkbenchShell extends Disposable {
serviceCollection.set(ILifecycleService, lifecycleService);
this.lifecycleService = lifecycleService;
serviceCollection.set(IRequestService, new SyncDescriptor(RequestService));
serviceCollection.set(IDownloadService, new SyncDescriptor(DownloadService));
serviceCollection.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService));
serviceCollection.set(IRequestService, new SyncDescriptor(RequestService, undefined, true));
serviceCollection.set(IDownloadService, new SyncDescriptor(DownloadService, undefined, true));
serviceCollection.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService, undefined, true));
const remoteAuthorityResolverService = new RemoteAuthorityResolverService();
serviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService);
@@ -498,7 +517,7 @@ export class WorkbenchShell extends Disposable {
const extensionManagementChannel = getDelayedChannel(sharedProcess.then(c => c.getChannel('extensions')));
const extensionManagementChannelClient = new ExtensionManagementChannelClient(extensionManagementChannel);
serviceCollection.set(IExtensionManagementServerService, new SyncDescriptor(ExtensionManagementServerService, [extensionManagementChannelClient]));
serviceCollection.set(IExtensionManagementService, new SyncDescriptor(MulitExtensionManagementService));
serviceCollection.set(IExtensionManagementService, new SyncDescriptor(MultiExtensionManagementService));
const extensionEnablementService = this._register(instantiationService.createInstance(ExtensionEnablementService));
serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
@@ -508,9 +527,10 @@ export class WorkbenchShell extends Disposable {
this.themeService = instantiationService.createInstance(WorkbenchThemeService, document.body);
serviceCollection.set(IWorkbenchThemeService, this.themeService);
serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
serviceCollection.set(ICommandService, new SyncDescriptor(CommandService, undefined, true));
serviceCollection.set(IMarkerService, new SyncDescriptor(MarkerService, undefined, true));
serviceCollection.set(IMarkerService, new SyncDescriptor(MarkerService));
serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
@@ -518,11 +538,13 @@ export class WorkbenchShell extends Disposable {
serviceCollection.set(ITextResourcePropertiesService, new SyncDescriptor(TextResourcePropertiesService));
serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl, undefined, true));
serviceCollection.set(IMarkerDecorationsService, new SyncDescriptor(MarkerDecorationsService));
serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService, undefined, true));
serviceCollection.set(ITextMateService, new SyncDescriptor(TextMateService));
@@ -534,7 +556,7 @@ export class WorkbenchShell extends Disposable {
serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorService));
serviceCollection.set(IOpenerService, new SyncDescriptor(OpenerService));
serviceCollection.set(IOpenerService, new SyncDescriptor(OpenerService, undefined, true));
serviceCollection.set(IIntegrityService, new SyncDescriptor(IntegrityServiceImpl));
@@ -562,7 +584,7 @@ export class WorkbenchShell extends Disposable {
});
// Shell Class for CSS Scoping
addClass(this.container, 'monaco-shell');
addClasses(this.container, 'monaco-shell', platform.isWindows ? 'windows' : platform.isLinux ? 'linux' : 'mac');
// Create Contents
this.renderContents();

View File

@@ -15,7 +15,7 @@ import { toResource, IUntitledResourceInput } from 'vs/workbench/common/editor';
import { IEditorService, IResourceEditor } from 'vs/workbench/services/editor/common/editorService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
import { IWindowsService, IWindowService, IWindowSettings, IOpenFileRequest, IWindowsConfiguration, IAddFoldersRequest, IRunActionInWindowRequest, IPathData } from 'vs/platform/windows/common/windows';
import { IWindowsService, IWindowService, IWindowSettings, IOpenFileRequest, IWindowsConfiguration, IAddFoldersRequest, IRunActionInWindowRequest, IPathData, IRunKeybindingInWindowRequest } from 'vs/platform/windows/common/windows';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { ITitleService } from 'vs/workbench/services/title/common/titleService';
import { IWorkbenchThemeService, VS_HC_THEME } from 'vs/workbench/services/themes/common/workbenchThemeService';
@@ -38,21 +38,22 @@ import { AccessibilitySupport, isRootUser, isWindows, isMacintosh } from 'vs/bas
import product from 'vs/platform/node/product';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
const TextInputActions: IAction[] = [
new Action('undo', nls.localize('undo', "Undo"), null, true, () => document.execCommand('undo') && Promise.resolve(true)),
new Action('redo', nls.localize('redo', "Redo"), null, true, () => document.execCommand('redo') && Promise.resolve(true)),
new Action('undo', nls.localize('undo', "Undo"), undefined, true, () => Promise.resolve(document.execCommand('undo'))),
new Action('redo', nls.localize('redo', "Redo"), undefined, true, () => Promise.resolve(document.execCommand('redo'))),
new Separator(),
new Action('editor.action.clipboardCutAction', nls.localize('cut', "Cut"), null, true, () => document.execCommand('cut') && Promise.resolve(true)),
new Action('editor.action.clipboardCopyAction', nls.localize('copy', "Copy"), null, true, () => document.execCommand('copy') && Promise.resolve(true)),
new Action('editor.action.clipboardPasteAction', nls.localize('paste', "Paste"), null, true, () => document.execCommand('paste') && Promise.resolve(true)),
new Action('editor.action.clipboardCutAction', nls.localize('cut', "Cut"), undefined, true, () => Promise.resolve(document.execCommand('cut'))),
new Action('editor.action.clipboardCopyAction', nls.localize('copy', "Copy"), undefined, true, () => Promise.resolve(document.execCommand('copy'))),
new Action('editor.action.clipboardPasteAction', nls.localize('paste', "Paste"), undefined, true, () => Promise.resolve(document.execCommand('paste'))),
new Separator(),
new Action('editor.action.selectAll', nls.localize('selectAll', "Select All"), null, true, () => document.execCommand('selectAll') && Promise.resolve(true))
new Action('editor.action.selectAll', nls.localize('selectAll', "Select All"), undefined, true, () => Promise.resolve(document.execCommand('selectAll')))
];
export class ElectronWindow extends Themable {
private touchBarMenu: IMenu;
private touchBarMenu?: IMenu;
private touchBarUpdater: RunOnceScheduler;
private touchBarDisposables: IDisposable[];
private lastInstalledTouchedBar: ICommandAction[][];
@@ -63,21 +64,22 @@ export class ElectronWindow extends Themable {
private pendingFoldersToAdd: URI[];
constructor(
@IEditorService private editorService: EditorServiceImpl,
@IWindowsService private windowsService: IWindowsService,
@IWindowService private windowService: IWindowService,
@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService,
@ITitleService private titleService: ITitleService,
@IEditorService private readonly editorService: EditorServiceImpl,
@IWindowsService private readonly windowsService: IWindowsService,
@IWindowService private readonly windowService: IWindowService,
@IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService,
@ITitleService private readonly titleService: ITitleService,
@IWorkbenchThemeService protected themeService: IWorkbenchThemeService,
@INotificationService private notificationService: INotificationService,
@ICommandService private commandService: ICommandService,
@IContextMenuService private contextMenuService: IContextMenuService,
@ITelemetryService private telemetryService: ITelemetryService,
@IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService,
@IFileService private fileService: IFileService,
@IMenuService private menuService: IMenuService,
@ILifecycleService private lifecycleService: ILifecycleService,
@IIntegrityService private integrityService: IIntegrityService
@INotificationService private readonly notificationService: INotificationService,
@ICommandService private readonly commandService: ICommandService,
@IKeybindingService private readonly keybindingService: IKeybindingService,
@IContextMenuService private readonly contextMenuService: IContextMenuService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IWorkspaceEditingService private readonly workspaceEditingService: IWorkspaceEditingService,
@IFileService private readonly fileService: IFileService,
@IMenuService private readonly menuService: IMenuService,
@ILifecycleService private readonly lifecycleService: ILifecycleService,
@IIntegrityService private readonly integrityService: IIntegrityService
) {
super(themeService);
@@ -133,6 +135,13 @@ export class ElectronWindow extends Themable {
});
});
// Support runKeybinding event
ipc.on('vscode:runKeybinding', (event: any, request: IRunKeybindingInWindowRequest) => {
if (document.activeElement) {
this.keybindingService.dispatchByUserSettingsLabel(request.userSettingsLabel, document.activeElement);
}
});
// Error reporting from main
ipc.on('vscode:reportError', (event: any, error: string) => {
if (error) {
@@ -171,7 +180,7 @@ export class ElectronWindow extends Themable {
const windowConfig = this.configurationService.getValue<IWindowSettings>('window');
if (windowConfig && windowConfig.autoDetectHighContrast) {
this.lifecycleService.when(LifecyclePhase.Ready).then(() => {
this.themeService.setColorTheme(VS_HC_THEME, null);
this.themeService.setColorTheme(VS_HC_THEME, undefined);
});
}
});
@@ -300,7 +309,7 @@ export class ElectronWindow extends Themable {
// Dispose old
this.touchBarDisposables = dispose(this.touchBarDisposables);
this.touchBarMenu = void 0;
this.touchBarMenu = undefined;
// Create new (delayed)
this.touchBarUpdater = new RunOnceScheduler(() => this.doUpdateTouchbarMenu(), 300);
@@ -315,16 +324,15 @@ export class ElectronWindow extends Themable {
this.touchBarDisposables.push(this.touchBarMenu.onDidChange(() => this.touchBarUpdater.schedule()));
}
const actions: (MenuItemAction | Separator)[] = [];
const actions: Array<MenuItemAction | Separator> = [];
// Fill actions into groups respecting order
fillInActionBarActions(this.touchBarMenu, void 0, actions);
fillInActionBarActions(this.touchBarMenu, undefined, actions);
// Convert into command action multi array
const items: ICommandAction[][] = [];
let group: ICommandAction[] = [];
for (let i = 0; i < actions.length; i++) {
const action = actions[i];
for (const action of actions) {
// Command
if (action instanceof MenuItemAction) {
@@ -377,7 +385,7 @@ export class ElectronWindow extends Themable {
private onOpenFiles(request: IOpenFileRequest): void {
const inputs: IResourceEditor[] = [];
const diffMode = request.filesToDiff && (request.filesToDiff.length === 2);
const diffMode = !!(request.filesToDiff && (request.filesToDiff.length === 2));
if (!diffMode && request.filesToOpen) {
inputs.push(...this.toInputs(request.filesToOpen, false));
@@ -387,7 +395,7 @@ export class ElectronWindow extends Themable {
inputs.push(...this.toInputs(request.filesToCreate, true));
}
if (diffMode) {
if (diffMode && request.filesToDiff) {
inputs.push(...this.toInputs(request.filesToDiff, false));
}
@@ -410,12 +418,12 @@ export class ElectronWindow extends Themable {
}
}
private openResources(resources: (IResourceInput | IUntitledResourceInput)[], diffMode: boolean): Thenable<any> {
return this.lifecycleService.when(LifecyclePhase.Ready).then(() => {
private openResources(resources: Array<IResourceInput | IUntitledResourceInput>, diffMode: boolean): void {
this.lifecycleService.when(LifecyclePhase.Ready).then((): Promise<any> => {
// In diffMode we open 2 resources as diff
if (diffMode && resources.length === 2) {
return this.editorService.openEditor({ leftResource: resources[0].resource, rightResource: resources[1].resource, options: { pinned: true } });
return this.editorService.openEditor({ leftResource: resources[0].resource!, rightResource: resources[1].resource!, options: { pinned: true } });
}
// For one file, just put it into the current active editor
@@ -438,8 +446,8 @@ export class ElectronWindow extends Themable {
input = { resource, options: { pinned: true } } as IResourceInput;
}
if (!isNew && p.lineNumber) {
input.options.selection = {
if (!isNew && typeof p.lineNumber === 'number' && typeof p.columnNumber === 'number') {
input.options!.selection = {
startLineNumber: p.lineNumber,
startColumn: p.columnNumber
};

View File

@@ -8,7 +8,7 @@ import 'vs/css!./media/workbench';
import { localize } from 'vs/nls';
// {{SQL CARBON EDIT}} - Import toDisposable
import { IDisposable, dispose, Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { Event, Emitter, once } from 'vs/base/common/event';
import { Event, Emitter } from 'vs/base/common/event';
import * as DOM from 'vs/base/browser/dom';
import { RunOnceScheduler, runWhenIdle } from 'vs/base/common/async';
import * as browser from 'vs/base/browser/browser';
@@ -20,8 +20,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform';
import { IResourceInput } from 'vs/platform/editor/common/editor';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
// {{SQL CARBON EDIT}} - Import IEditor
import { IEditorInputFactoryRegistry, Extensions as EditorExtensions, TextCompareEditorVisibleContext, TEXT_DIFF_EDITOR_ID, EditorsVisibleContext, InEditorZenModeContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, IUntitledResourceInput, IResourceDiffInput, SplitEditorsVertically, TextCompareEditorActiveContext, ActiveEditorContext, IEditor } from 'vs/workbench/common/editor';
import { IEditorInputFactoryRegistry, Extensions as EditorExtensions, TextCompareEditorVisibleContext, TEXT_DIFF_EDITOR_ID, EditorsVisibleContext, InEditorZenModeContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, IUntitledResourceInput, IResourceDiffInput, SplitEditorsVertically, TextCompareEditorActiveContext, ActiveEditorContext } from 'vs/workbench/common/editor';
import { HistoryService } from 'vs/workbench/services/history/electron-browser/history';
import { ActivitybarPart } from 'vs/workbench/browser/parts/activitybar/activitybarPart';
import { SidebarPart } from 'vs/workbench/browser/parts/sidebar/sidebarPart';
@@ -29,14 +28,13 @@ import { PanelPart } from 'vs/workbench/browser/parts/panel/panelPart';
import { StatusbarPart } from 'vs/workbench/browser/parts/statusbar/statusbarPart';
import { TitlebarPart } from 'vs/workbench/browser/parts/titlebar/titlebarPart';
import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart';
import { WorkbenchLayout } from 'vs/workbench/browser/layout';
import { IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbench/browser/actions';
import { PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel';
import { QuickOpenController } from 'vs/workbench/browser/parts/quickopen/quickOpenController';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { QuickInputService } from 'vs/workbench/browser/parts/quickinput/quickInput';
import { getServices } from 'vs/platform/instantiation/common/extensions';
import { Position, Parts, IPartService, ILayoutOptions, IDimension, PositionToString } from 'vs/workbench/services/part/common/partService';
import { Position, Parts, IPartService, IDimension, PositionToString, ILayoutOptions } from 'vs/workbench/services/part/common/partService';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IStorageService, StorageScope, IWillSaveStateEvent, WillSaveStateReason } from 'vs/platform/storage/common/storage';
import { ContextMenuService as NativeContextMenuService } from 'vs/workbench/services/contextview/electron-browser/contextmenuService';
@@ -52,7 +50,6 @@ import { IKeybindingEditingService, KeybindingsEditingService } from 'vs/workben
import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IActivityService } from 'vs/workbench/services/activity/common/activity';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { ViewletService } from 'vs/workbench/services/viewlet/browser/viewletService';
import { RemoteFileService } from 'vs/workbench/services/files/electron-browser/remoteFileService';
import { IFileService } from 'vs/platform/files/common/files';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
@@ -83,7 +80,8 @@ import { MenuService } from 'vs/platform/actions/common/menuService';
import { IContextMenuService, IContextViewService } 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, ReloadWindowWithExtensionsDisabledAction, NewWindowTab } from 'vs/workbench/electron-browser/actions';
import { ShowPreviousWindowTab, MoveWindowTabToNewWindow, MergeAllWindowTabs, ShowNextWindowTab, ToggleWindowTabsBar, NewWindowTab, OpenRecentAction, ReloadWindowAction, ReloadWindowWithExtensionsDisabledAction } from 'vs/workbench/electron-browser/actions/windowActions';
import { ToggleDevToolsAction } from 'vs/workbench/electron-browser/actions/developerActions';
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';
@@ -183,6 +181,9 @@ import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/work
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { FileDialogService } from 'vs/workbench/services/dialogs/electron-browser/dialogService';
import { LogStorageAction } from 'vs/platform/storage/node/storageService';
import { Sizing, Direction, Grid, View } from 'vs/base/browser/ui/grid/grid';
import { IEditor } from 'vs/editor/common/editorCommon';
import { WorkbenchLayout } from 'vs/workbench/browser/layout';
interface WorkbenchParams {
configuration: IWindowConfiguration;
@@ -195,6 +196,7 @@ interface IZenModeSettings {
hideTabs: boolean;
hideActivityBar: boolean;
hideStatusBar: boolean;
hideLineNumbers: boolean;
restore: boolean;
}
@@ -236,6 +238,12 @@ interface IZenMode {
wasPanelVisible: boolean;
}
interface IWorkbenchUIState {
lastPanelHeight?: number;
lastPanelWidth?: number;
lastSidebarDimension?: number;
}
export class Workbench extends Disposable implements IPartService {
private static readonly sidebarHiddenStorageKey = 'workbench.sidebar.hidden';
@@ -261,7 +269,6 @@ export class Workbench extends Disposable implements IPartService {
private editorService: EditorService;
private editorGroupService: IEditorGroupsService;
private viewletService: IViewletService;
private contextViewService: ContextViewService;
private contextKeyService: IContextKeyService;
private keybindingService: IKeybindingService;
@@ -269,7 +276,7 @@ export class Workbench extends Disposable implements IPartService {
private fileService: IFileService;
private quickInput: QuickInputService;
private workbenchLayout: WorkbenchLayout;
private workbenchGrid: Grid<View> | WorkbenchLayout;
private titlebarPart: TitlebarPart;
private activitybarPart: ActivitybarPart;
@@ -277,10 +284,19 @@ export class Workbench extends Disposable implements IPartService {
private panelPart: PanelPart;
private editorPart: EditorPart;
private statusbarPart: StatusbarPart;
private titlebarPartView: View;
private activitybarPartView: View;
private sidebarPartView: View;
private panelPartView: View;
private editorPartView: View;
private statusbarPartView: View;
private quickOpen: QuickOpenController;
private notificationsCenter: NotificationsCenter;
private notificationsToasts: NotificationsToasts;
private editorHidden: boolean;
private sideBarHidden: boolean;
private statusBarHidden: boolean;
private activityBarHidden: boolean;
@@ -293,6 +309,11 @@ export class Workbench extends Disposable implements IPartService {
private fontAliasing: FontAliasingOption;
private hasInitialFilesToOpen: boolean;
private shouldCenterLayout = false;
private uiState: IWorkbenchUIState = {
lastPanelHeight: 350,
lastPanelWidth: 350,
lastSidebarDimension: 300,
};
private inZenMode: IContextKey<boolean>;
private sideBarVisibleContext: IContextKey<boolean>;
@@ -305,14 +326,14 @@ export class Workbench extends Disposable implements IPartService {
serviceCollection: ServiceCollection,
private lifecycleService: LifecycleService,
private mainProcessClient: IPCClient,
@IInstantiationService private instantiationService: IInstantiationService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IStorageService private storageService: IStorageService,
@IConfigurationService private configurationService: WorkspaceService,
@IWorkbenchThemeService private themeService: WorkbenchThemeService,
@IEnvironmentService private environmentService: IEnvironmentService,
@IWindowService private windowService: IWindowService,
@INotificationService private notificationService: NotificationService
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IStorageService private readonly storageService: IStorageService,
@IConfigurationService private readonly configurationService: WorkspaceService,
@IWorkbenchThemeService private readonly themeService: WorkbenchThemeService,
@IEnvironmentService private readonly environmentService: IEnvironmentService,
@IWindowService private readonly windowService: IWindowService,
@INotificationService private readonly notificationService: NotificationService
) {
super();
@@ -324,7 +345,7 @@ export class Workbench extends Disposable implements IPartService {
(configuration.filesToDiff && configuration.filesToDiff.length > 0);
}
startup(): Thenable<IWorkbenchStartedInfo> {
startup(): Promise<IWorkbenchStartedInfo> {
this.workbenchStarted = true;
// Create Workbench Container
@@ -363,7 +384,7 @@ export class Workbench extends Disposable implements IPartService {
private createWorkbench(): void {
this.workbench = document.createElement('div');
this.workbench.id = Identifiers.WORKBENCH_CONTAINER;
DOM.addClasses(this.workbench, 'monaco-workbench', isWindows ? 'windows' : isLinux ? 'linux' : 'mac');
DOM.addClass(this.workbench, 'monaco-workbench');
this._register(DOM.addDisposableListener(this.workbench, DOM.EventType.SCROLL, () => {
this.workbench.scrollTop = 0; // Prevent workbench from scrolling #55456
@@ -375,8 +396,8 @@ export class Workbench extends Disposable implements IPartService {
// Actions registered here to adjust for developing vs built workbench
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
registry.registerWorkbenchAction(new SyncActionDescriptor(ReloadWindowAction, ReloadWindowAction.ID, ReloadWindowAction.LABEL, isDeveloping ? { primary: KeyMod.CtrlCmd | KeyCode.KEY_R } : void 0), 'Reload Window');
registry.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"));
registry.registerWorkbenchAction(new SyncActionDescriptor(ReloadWindowAction, ReloadWindowAction.ID, ReloadWindowAction.LABEL, isDeveloping ? { primary: KeyMod.CtrlCmd | KeyCode.KEY_R } : undefined), 'Reload Window');
registry.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 } } : undefined), 'Developer: Toggle Developer Tools', localize('developer', "Developer"));
registry.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"));
registry.registerWorkbenchAction(new SyncActionDescriptor(ReloadWindowWithExtensionsDisabledAction, ReloadWindowWithExtensionsDisabledAction.ID, ReloadWindowWithExtensionsDisabledAction.LABEL), 'Reload Window Without Extensions');
registry.registerWorkbenchAction(new SyncActionDescriptor(LogStorageAction, LogStorageAction.ID, LogStorageAction.LABEL), 'Developer: Log Storage', localize('developer', "Developer"));
@@ -437,8 +458,7 @@ export class Workbench extends Disposable implements IPartService {
this.sidebarPart = this.instantiationService.createInstance(SidebarPart, Identifiers.SIDEBAR_PART);
// Viewlet service
this.viewletService = this.instantiationService.createInstance(ViewletService, this.sidebarPart);
serviceCollection.set(IViewletService, this.viewletService);
serviceCollection.set(IViewletService, this.sidebarPart);
// Panel service (panel part)
this.panelPart = this.instantiationService.createInstance(PanelPart, Identifiers.PANEL_PART);
@@ -598,6 +618,9 @@ export class Workbench extends Disposable implements IPartService {
// Listen to visible editor changes
this._register(this.editorService.onDidVisibleEditorsChange(() => this.onDidVisibleEditorsChange()));
// Listen to editor group activations when editor is hidden
this._register(this.editorPart.onDidActivateGroup(() => { if (this.editorHidden) { this.setEditorHidden(false); } }));
// Listen to editor closing (if we run with --wait)
const filesToWait = this.workbenchParams.configuration.filesToWait;
if (filesToWait) {
@@ -674,6 +697,10 @@ export class Workbench extends Disposable implements IPartService {
this.closeEmptyWindowScheduler.schedule();
}
}
if (this.editorHidden) {
this.setEditorHidden(false);
}
}
private onAllEditorsClosed(): void {
@@ -782,7 +809,7 @@ export class Workbench extends Disposable implements IPartService {
if (isInputFocused) {
const tracker = DOM.trackFocus(document.activeElement as HTMLElement);
once(tracker.onDidBlur)(() => {
Event.once(tracker.onDidBlur)(() => {
inputFocused.set(activeElementIsInput());
tracker.dispose();
@@ -820,8 +847,8 @@ export class Workbench extends Disposable implements IPartService {
updateSplitEditorsVerticallyContext();
}
private restoreParts(): Thenable<IWorkbenchStartedInfo> {
const restorePromises: Thenable<any>[] = [];
private restoreParts(): Promise<IWorkbenchStartedInfo> {
const restorePromises: Promise<any>[] = [];
// Restore Editorpart
perf.mark('willRestoreEditors');
@@ -854,12 +881,12 @@ export class Workbench extends Disposable implements IPartService {
}
if (!viewletIdToRestore) {
viewletIdToRestore = this.viewletService.getDefaultViewletId();
viewletIdToRestore = this.sidebarPart.getDefaultViewletId();
}
perf.mark('willRestoreViewlet');
restorePromises.push(this.viewletService.openViewlet(viewletIdToRestore)
.then(viewlet => viewlet || this.viewletService.openViewlet(this.viewletService.getDefaultViewletId()))
restorePromises.push(this.sidebarPart.openViewlet(viewletIdToRestore)
.then(viewlet => viewlet || this.sidebarPart.openViewlet(this.sidebarPart.getDefaultViewletId()))
.then(() => perf.mark('didRestoreViewlet')));
}
@@ -892,13 +919,13 @@ export class Workbench extends Disposable implements IPartService {
// Set lifecycle phase to `Restored`
this.lifecycleService.phase = LifecyclePhase.Restored;
// Set lifecycle phase to `Runnning For A Bit` after a short delay
let eventuallPhaseTimeoutHandle = runWhenIdle(() => {
eventuallPhaseTimeoutHandle = void 0;
this.lifecycleService.phase = LifecyclePhase.Eventually;
}, 5000);
this._register(eventuallPhaseTimeoutHandle);
// Set lifecycle phase to `Eventually` after a short delay and when
// idle (min 2.5sec, max 5sec)
setTimeout(() => {
this._register(runWhenIdle(() => {
this.lifecycleService.phase = LifecyclePhase.Eventually;
}, 2500));
}, 2500);
if (error) {
errors.onUnexpectedError(error);
@@ -924,7 +951,7 @@ export class Workbench extends Disposable implements IPartService {
return this.lifecycleService.startupKind === StartupKind.ReloadedWindow;
}
private resolveEditorsToOpen(): Thenable<IResourceEditor[]> | IResourceEditor[] {
private resolveEditorsToOpen(): Promise<IResourceEditor[]> | IResourceEditor[] {
const config = this.workbenchParams.configuration;
// Files to open, diff or create
@@ -967,7 +994,7 @@ export class Workbench extends Disposable implements IPartService {
return [];
}
private toInputs(paths: IPath[], isNew: boolean): (IResourceInput | IUntitledResourceInput)[] {
private toInputs(paths: IPath[], isNew: boolean): Array<IResourceInput | IUntitledResourceInput> {
if (!paths || !paths.length) {
return [];
}
@@ -1008,6 +1035,9 @@ export class Workbench extends Disposable implements IPartService {
private initSettings(): void {
// Editor visiblity
this.editorHidden = false;
// Sidebar visibility
this.sideBarHidden = this.storageService.getBoolean(Workbench.sidebarHiddenStorageKey, StorageScope.WORKSPACE, this.contextService.getWorkbenchState() === WorkbenchState.EMPTY);
@@ -1062,6 +1092,22 @@ export class Workbench extends Disposable implements IPartService {
return getTitleBarStyle(this.configurationService, this.environmentService) === 'custom';
}
private saveLastPanelDimension(): void {
if (!(this.workbenchGrid instanceof Grid)) {
return;
}
if (this.panelPosition === Position.BOTTOM) {
this.uiState.lastPanelHeight = this.workbenchGrid.getViewSize(this.panelPartView);
} else {
this.uiState.lastPanelWidth = this.workbenchGrid.getViewSize(this.panelPartView);
}
}
private getLastPanelDimension(position: Position): number | undefined {
return position === Position.BOTTOM ? this.uiState.lastPanelHeight : this.uiState.lastPanelWidth;
}
private setStatusBarHidden(hidden: boolean, skipLayout?: boolean): void {
this.statusBarHidden = hidden;
@@ -1074,7 +1120,11 @@ export class Workbench extends Disposable implements IPartService {
// Layout
if (!skipLayout) {
this.workbenchLayout.layout();
if (this.workbenchGrid instanceof Grid) {
this.layout();
} else {
this.workbenchGrid.layout();
}
}
}
@@ -1091,23 +1141,38 @@ export class Workbench extends Disposable implements IPartService {
}
private createWorkbenchLayout(): void {
this.workbenchLayout = this.instantiationService.createInstance(
WorkbenchLayout,
this.container,
this.workbench,
{
titlebar: this.titlebarPart,
activitybar: this.activitybarPart,
editor: this.editorPart,
sidebar: this.sidebarPart,
panel: this.panelPart,
statusbar: this.statusbarPart,
},
this.quickOpen,
this.quickInput,
this.notificationsCenter,
this.notificationsToasts
);
if (this.configurationService.getValue('workbench.useExperimentalGridLayout')) {
// Create view wrappers for all parts
this.titlebarPartView = new View(this.titlebarPart);
this.sidebarPartView = new View(this.sidebarPart);
this.activitybarPartView = new View(this.activitybarPart);
this.editorPartView = new View(this.editorPart);
this.panelPartView = new View(this.panelPart);
this.statusbarPartView = new View(this.statusbarPart);
this.workbenchGrid = new Grid(this.editorPartView, { proportionalLayout: false });
this.workbench.prepend(this.workbenchGrid.element);
this.layout();
} else {
this.workbenchGrid = this.instantiationService.createInstance(
WorkbenchLayout,
this.container,
this.workbench,
{
titlebar: this.titlebarPart,
activitybar: this.activitybarPart,
editor: this.editorPart,
sidebar: this.sidebarPart,
panel: this.panelPart,
statusbar: this.statusbarPart,
},
this.quickOpen,
this.quickInput,
this.notificationsCenter,
this.notificationsToasts
);
}
}
private renderWorkbench(): void {
@@ -1196,9 +1261,11 @@ export class Workbench extends Disposable implements IPartService {
part.id = id;
part.setAttribute('role', role);
// Insert all workbench parts at the beginning. Issue #52531
// This is primarily for the title bar to allow overriding -webkit-app-region
this.workbench.insertBefore(part, this.workbench.lastChild);
if (!this.configurationService.getValue('workbench.useExperimentalGridLayout')) {
// Insert all workbench parts at the beginning. Issue #52531
// This is primarily for the title bar to allow overriding -webkit-app-region
this.workbench.insertBefore(part, this.workbench.lastChild);
}
return part;
}
@@ -1328,6 +1395,8 @@ export class Workbench extends Disposable implements IPartService {
return !this.statusBarHidden;
case Parts.ACTIVITYBAR_PART:
return !this.activityBarHidden;
case Parts.EDITOR_PART:
return this.workbenchGrid instanceof Grid ? !this.editorHidden : true;
}
return true; // any other part cannot be hidden
@@ -1336,7 +1405,12 @@ export class Workbench extends Disposable implements IPartService {
getTitleBarOffset(): number {
let offset = 0;
if (this.isVisible(Parts.TITLEBAR_PART)) {
offset = this.workbenchLayout.partLayoutInfo.titlebar.height;
if (this.workbenchGrid instanceof Grid) {
offset = this.gridHasView(this.titlebarPartView) ? this.workbenchGrid.getViewSize2(this.titlebarPartView).height : 0;
} else {
offset = this.workbenchGrid.partLayoutInfo.titlebar.height;
}
if (isMacintosh || this.menubarVisibility === 'hidden') {
offset /= browser.getZoomFactor();
}
@@ -1356,6 +1430,14 @@ export class Workbench extends Disposable 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 (same goes for the centered editor layout)
let toggleFullScreen = false;
const setLineNumbers = (lineNumbers: any) => {
this.editorService.visibleControls.forEach(editor => {
const control = <IEditor>editor.getControl();
if (control) {
control.updateOptions({ lineNumbers });
}
});
};
// Zen Mode Active
if (this.zenMode.active) {
@@ -1378,6 +1460,11 @@ export class Workbench extends Disposable implements IPartService {
this.setStatusBarHidden(true, true);
}
if (config.hideLineNumbers) {
setLineNumbers('off');
this.zenMode.transitionDisposeables.push(this.editorService.onDidVisibleEditorsChange(() => setLineNumbers('off')));
}
if (config.hideTabs && this.editorPart.partOptions.showTabs) {
this.zenMode.transitionDisposeables.push(this.editorPart.enforcePartOptions({ showTabs: false }));
}
@@ -1400,6 +1487,7 @@ export class Workbench extends Disposable implements IPartService {
if (this.zenMode.transitionedToCenteredEditorLayout) {
this.centerEditorLayout(false, true);
}
setLineNumbers(this.configurationService.getValue('editor.lineNumbers'));
// Status bar and activity bar visibility come from settings -> update their visibility.
this.onDidUpdateConfiguration(true);
@@ -1420,11 +1508,130 @@ export class Workbench extends Disposable implements IPartService {
}
}
private gridHasView(view: View): boolean {
if (!(this.workbenchGrid instanceof Grid)) {
return false;
}
try {
this.workbenchGrid.getViewSize(view);
return true;
} catch {
return false;
}
}
private updateGrid(): void {
if (!(this.workbenchGrid instanceof Grid)) {
return;
}
let panelInGrid = this.gridHasView(this.panelPartView);
let sidebarInGrid = this.gridHasView(this.sidebarPartView);
let activityBarInGrid = this.gridHasView(this.activitybarPartView);
let statusBarInGrid = this.gridHasView(this.statusbarPartView);
let titlebarInGrid = this.gridHasView(this.titlebarPartView);
// Add parts to grid
if (!statusBarInGrid) {
this.workbenchGrid.addView(this.statusbarPartView, Sizing.Split, this.editorPartView, Direction.Down);
statusBarInGrid = true;
}
if (!titlebarInGrid && this.useCustomTitleBarStyle()) {
this.workbenchGrid.addView(this.titlebarPartView, Sizing.Split, this.editorPartView, Direction.Up);
titlebarInGrid = true;
}
if (!activityBarInGrid) {
this.workbenchGrid.addView(this.activitybarPartView, Sizing.Split, panelInGrid && this.sideBarPosition === this.panelPosition ? this.panelPartView : this.editorPartView, this.sideBarPosition === Position.RIGHT ? Direction.Right : Direction.Left);
activityBarInGrid = true;
}
if (!sidebarInGrid) {
this.workbenchGrid.addView(this.sidebarPartView, this.uiState.lastSidebarDimension !== undefined ? this.uiState.lastSidebarDimension : Sizing.Split, this.activitybarPartView, this.sideBarPosition === Position.LEFT ? Direction.Right : Direction.Left);
sidebarInGrid = true;
}
if (!panelInGrid) {
this.workbenchGrid.addView(this.panelPartView, this.getLastPanelDimension(this.panelPosition) !== undefined ? this.getLastPanelDimension(this.panelPosition) : Sizing.Split, this.editorPartView, this.panelPosition === Position.BOTTOM ? Direction.Down : Direction.Right);
panelInGrid = true;
}
// Hide parts
if (this.panelHidden) {
this.panelPartView.hide();
}
if (this.statusBarHidden) {
this.statusbarPartView.hide();
}
if (!this.isVisible(Parts.TITLEBAR_PART)) {
this.titlebarPartView.hide();
}
if (this.activityBarHidden) {
this.activitybarPartView.hide();
}
if (this.sideBarHidden) {
this.sidebarPartView.hide();
}
if (this.editorHidden) {
this.editorPartView.hide();
}
// Show visible parts
if (!this.editorHidden) {
this.editorPartView.show();
}
if (!this.statusBarHidden) {
this.statusbarPartView.show();
}
if (this.isVisible(Parts.TITLEBAR_PART)) {
this.titlebarPartView.show();
}
if (!this.activityBarHidden) {
this.activitybarPartView.show();
}
if (!this.sideBarHidden) {
this.sidebarPartView.show();
}
if (!this.panelHidden) {
this.panelPartView.show();
}
}
layout(options?: ILayoutOptions): void {
this.contextViewService.layout();
if (this.workbenchStarted && !this.workbenchShutdown) {
this.workbenchLayout.layout(options);
if (this.workbenchGrid instanceof Grid) {
const dimensions = DOM.getClientArea(this.container);
DOM.position(this.workbench, 0, 0, 0, 0, 'relative');
DOM.size(this.workbench, dimensions.width, dimensions.height);
// Layout the grid
this.workbenchGrid.layout(dimensions.width, dimensions.height);
// Layout non-view ui components
this.quickInput.layout(dimensions);
this.quickOpen.layout(dimensions);
this.notificationsCenter.layout(dimensions);
this.notificationsToasts.layout(dimensions);
// Update grid view membership
this.updateGrid();
} else {
this.workbenchGrid.layout(options);
}
}
}
@@ -1451,11 +1658,19 @@ export class Workbench extends Disposable implements IPartService {
}
resizePart(part: Parts, sizeChange: number): void {
let view: View;
switch (part) {
case Parts.SIDEBAR_PART:
view = this.sidebarPartView;
case Parts.PANEL_PART:
view = this.panelPartView;
case Parts.EDITOR_PART:
this.workbenchLayout.resizePart(part, sizeChange);
view = this.editorPartView;
if (this.workbenchGrid instanceof Grid) {
this.workbenchGrid.resizeView(view, this.workbenchGrid.getViewSize(view) + sizeChange);
} else {
this.workbenchGrid.resizePart(part, sizeChange);
}
break;
default:
return; // Cannot resize other parts
@@ -1467,7 +1682,28 @@ export class Workbench extends Disposable implements IPartService {
// Layout
if (!skipLayout) {
this.workbenchLayout.layout();
if (this.workbenchGrid instanceof Grid) {
this.layout();
} else {
this.workbenchGrid.layout();
}
}
}
setEditorHidden(hidden: boolean, skipLayout?: boolean): void {
if (!(this.workbenchGrid instanceof Grid)) {
return;
}
this.editorHidden = hidden;
// The editor and the panel cannot be hidden at the same time
if (this.editorHidden && this.panelHidden) {
this.setPanelHidden(false, true);
}
if (!skipLayout) {
this.layout();
}
}
@@ -1499,9 +1735,9 @@ export class Workbench extends Disposable implements IPartService {
else if (!hidden && !this.sidebarPart.getActiveViewlet()) {
const viewletToOpen = this.sidebarPart.getLastActiveViewletId();
if (viewletToOpen) {
const viewlet = this.viewletService.openViewlet(viewletToOpen, true);
const viewlet = this.sidebarPart.openViewlet(viewletToOpen, true);
if (!viewlet) {
this.viewletService.openViewlet(this.viewletService.getDefaultViewletId(), true);
this.sidebarPart.openViewlet(this.sidebarPart.getDefaultViewletId(), true);
}
}
}
@@ -1517,7 +1753,11 @@ export class Workbench extends Disposable implements IPartService {
// Layout
if (!skipLayout) {
this.workbenchLayout.layout();
if (this.workbenchGrid instanceof Grid) {
this.layout();
} else {
this.workbenchGrid.layout();
}
}
}
@@ -1553,18 +1793,39 @@ export class Workbench extends Disposable implements IPartService {
this.storageService.remove(Workbench.panelHiddenStorageKey, StorageScope.WORKSPACE);
}
// The editor and panel cannot be hiddne at the same time
if (hidden && this.editorHidden) {
this.setEditorHidden(false, true);
}
// Layout
if (!skipLayout) {
this.workbenchLayout.layout();
if (this.workbenchGrid instanceof Grid) {
this.layout();
} else {
this.workbenchGrid.layout();
}
}
}
toggleMaximizedPanel(): void {
this.workbenchLayout.layout({ toggleMaximizedPanel: true, source: Parts.PANEL_PART });
if (this.workbenchGrid instanceof Grid) {
this.workbenchGrid.maximizeViewSize(this.panelPartView);
} else {
this.workbenchGrid.layout({ toggleMaximizedPanel: true, source: Parts.PANEL_PART });
}
}
isPanelMaximized(): boolean {
return this.workbenchLayout.isPanelMaximized();
if (this.workbenchGrid instanceof Grid) {
try {
return this.workbenchGrid.getViewSize2(this.panelPartView).height === this.panelPart.maximumHeight;
} catch (e) {
return false;
}
} else {
return this.workbenchGrid.isPanelMaximized();
}
}
getSideBarPosition(): Position {
@@ -1572,6 +1833,8 @@ export class Workbench extends Disposable implements IPartService {
}
setSideBarPosition(position: Position): void {
const wasHidden = this.sideBarHidden;
if (this.sideBarHidden) {
this.setSideBarHidden(false, true /* Skip Layout */);
}
@@ -1591,15 +1854,37 @@ export class Workbench extends Disposable implements IPartService {
this.sidebarPart.updateStyles();
// Layout
this.workbenchLayout.layout();
if (this.workbenchGrid instanceof Grid) {
if (!wasHidden) {
this.uiState.lastSidebarDimension = this.workbenchGrid.getViewSize(this.sidebarPartView);
}
this.workbenchGrid.removeView(this.sidebarPartView);
this.workbenchGrid.removeView(this.activitybarPartView);
if (!this.panelHidden && this.panelPosition === Position.BOTTOM) {
this.workbenchGrid.removeView(this.panelPartView);
}
this.layout();
} else {
this.workbenchGrid.layout();
}
}
setMenubarVisibility(visibility: MenuBarVisibility, skipLayout: boolean): void {
if (this.menubarVisibility !== visibility) {
this.menubarVisibility = visibility;
// Layout
if (!skipLayout) {
this.workbenchLayout.layout();
if (this.workbenchGrid instanceof Grid) {
const dimensions = DOM.getClientArea(this.container);
this.workbenchGrid.layout(dimensions.width, dimensions.height);
} else {
this.workbenchGrid.layout();
}
}
}
}
@@ -1613,8 +1898,12 @@ export class Workbench extends Disposable implements IPartService {
}
setPanelPosition(position: Position): void {
const wasHidden = this.panelHidden;
if (this.panelHidden) {
this.setPanelHidden(false, true /* Skip Layout */);
} else {
this.saveLastPanelDimension();
}
const newPositionValue = (position === Position.BOTTOM) ? 'bottom' : 'right';
@@ -1630,8 +1919,15 @@ export class Workbench extends Disposable implements IPartService {
this.panelPart.updateStyles();
// Layout
this.workbenchLayout.layout();
}
if (this.workbenchGrid instanceof Grid) {
if (!wasHidden) {
this.saveLastPanelDimension();
}
//#endregion
}
this.workbenchGrid.removeView(this.panelPartView);
this.layout();
} else {
this.workbenchGrid.layout();
}
}
}