mirror of
https://github.com/coder/code-server.git
synced 2026-05-10 06:17:27 +02:00
chore(vscode): update to 1.53.2
These conflicts will be resolved in the following commits. We do it this way so that PR review is possible.
This commit is contained in:
@@ -3,48 +3,97 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import * as nls from 'vs/nls';
|
||||
import { localize } from 'vs/nls';
|
||||
import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { Action2, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { CATEGORIES } from 'vs/workbench/common/actions';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { IsDevelopmentContext } from 'vs/platform/contextkey/common/contextkeys';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
|
||||
export class ToggleDevToolsAction extends Action {
|
||||
export class ToggleDevToolsAction extends Action2 {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleDevTools';
|
||||
static readonly LABEL = nls.localize('toggleDevTools', "Toggle Developer Tools");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@INativeHostService private readonly nativeHostService: INativeHostService
|
||||
) {
|
||||
super(id, label);
|
||||
constructor() {
|
||||
super({
|
||||
id: 'workbench.action.toggleDevTools',
|
||||
title: { value: localize('toggleDevTools', "Toggle Developer Tools"), original: 'Toggle Developer Tools' },
|
||||
category: CATEGORIES.Developer,
|
||||
f1: true,
|
||||
keybinding: {
|
||||
weight: KeybindingWeight.WorkbenchContrib + 50,
|
||||
when: IsDevelopmentContext,
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_I,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_I }
|
||||
},
|
||||
menu: {
|
||||
id: MenuId.MenubarHelpMenu,
|
||||
group: '5_tools',
|
||||
order: 1
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
run(): Promise<void> {
|
||||
return this.nativeHostService.toggleDevTools();
|
||||
async run(accessor: ServicesAccessor): Promise<void> {
|
||||
const nativeHostService = accessor.get(INativeHostService);
|
||||
|
||||
return nativeHostService.toggleDevTools();
|
||||
}
|
||||
}
|
||||
|
||||
export class ConfigureRuntimeArgumentsAction extends Action {
|
||||
export class ConfigureRuntimeArgumentsAction extends Action2 {
|
||||
|
||||
static readonly ID = 'workbench.action.configureRuntimeArguments';
|
||||
static readonly LABEL = nls.localize('configureRuntimeArguments', "Configure Runtime Arguments");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IEditorService private readonly editorService: IEditorService
|
||||
) {
|
||||
super(id, label);
|
||||
constructor() {
|
||||
super({
|
||||
id: 'workbench.action.configureRuntimeArguments',
|
||||
title: { value: localize('configureRuntimeArguments', "Configure Runtime Arguments"), original: 'Configure Runtime Arguments' },
|
||||
category: CATEGORIES.Preferences,
|
||||
f1: true
|
||||
});
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
await this.editorService.openEditor({
|
||||
resource: this.environmentService.argvResource,
|
||||
async run(accessor: ServicesAccessor): Promise<void> {
|
||||
const editorService = accessor.get(IEditorService);
|
||||
const environmentService = accessor.get(IWorkbenchEnvironmentService);
|
||||
|
||||
await editorService.openEditor({
|
||||
resource: environmentService.argvResource,
|
||||
options: { pinned: true }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ToggleSharedProcessAction extends Action2 {
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
id: 'workbench.action.toggleSharedProcess',
|
||||
title: { value: localize('toggleSharedProcess', "Toggle Shared Process"), original: 'Toggle Shared Process' },
|
||||
category: CATEGORIES.Developer,
|
||||
f1: true
|
||||
});
|
||||
}
|
||||
|
||||
async run(accessor: ServicesAccessor): Promise<void> {
|
||||
return accessor.get(INativeHostService).toggleSharedProcessWindow();
|
||||
}
|
||||
}
|
||||
|
||||
export class ReloadWindowWithExtensionsDisabledAction extends Action2 {
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
id: 'workbench.action.reloadWindowWithExtensionsDisabled',
|
||||
title: { value: localize('reloadWindowWithExtensionsDisabled', "Reload With Extensions Disabled"), original: 'Reload With Extensions Disabled' },
|
||||
category: CATEGORIES.Developer,
|
||||
f1: true
|
||||
});
|
||||
}
|
||||
|
||||
async run(accessor: ServicesAccessor): Promise<void> {
|
||||
return accessor.get(INativeHostService).reload({ disableExtensions: true });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/actions';
|
||||
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import * as nls from 'vs/nls';
|
||||
@@ -21,6 +20,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
|
||||
|
||||
export class CloseCurrentWindowAction extends Action {
|
||||
|
||||
@@ -122,26 +122,6 @@ export class ZoomResetAction extends BaseZoomAction {
|
||||
}
|
||||
}
|
||||
|
||||
export class ReloadWindowWithExtensionsDisabledAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.reloadWindowWithExtensionsDisabled';
|
||||
static readonly LABEL = nls.localize('reloadWindowWithExtensionsDisabled', "Reload With Extensions Disabled");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@INativeHostService private readonly nativeHostService: INativeHostService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
async run(): Promise<boolean> {
|
||||
await this.nativeHostService.reload({ disableExtensions: true });
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class BaseSwitchWindow extends Action {
|
||||
|
||||
private readonly closeWindowAction: IQuickInputButton = {
|
||||
@@ -174,16 +154,16 @@ export abstract class BaseSwitchWindow extends Action {
|
||||
|
||||
const windows = await this.nativeHostService.getWindows();
|
||||
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 ? win.workspace.configPath : undefined;
|
||||
const fileKind = win.filename ? FileKind.FILE : win.workspace ? FileKind.ROOT_FOLDER : win.folderUri ? FileKind.FOLDER : FileKind.FILE;
|
||||
const picks = windows.map(window => {
|
||||
const resource = window.filename ? URI.file(window.filename) : isSingleFolderWorkspaceIdentifier(window.workspace) ? window.workspace.uri : isWorkspaceIdentifier(window.workspace) ? window.workspace.configPath : undefined;
|
||||
const fileKind = window.filename ? FileKind.FILE : isSingleFolderWorkspaceIdentifier(window.workspace) ? FileKind.FOLDER : isWorkspaceIdentifier(window.workspace) ? FileKind.ROOT_FOLDER : FileKind.FILE;
|
||||
return {
|
||||
payload: win.id,
|
||||
label: win.title,
|
||||
ariaLabel: win.dirty ? nls.localize('windowDirtyAriaLabel', "{0}, dirty window", win.title) : win.title,
|
||||
payload: window.id,
|
||||
label: window.title,
|
||||
ariaLabel: window.dirty ? nls.localize('windowDirtyAriaLabel', "{0}, dirty window", window.title) : window.title,
|
||||
iconClasses: getIconClasses(this.modelService, this.modeService, resource, fileKind),
|
||||
description: (currentWindowId === win.id) ? nls.localize('current', "Current Window") : undefined,
|
||||
buttons: currentWindowId !== win.id ? win.dirty ? [this.closeDirtyWindowAction] : [this.closeWindowAction] : undefined
|
||||
description: (currentWindowId === window.id) ? nls.localize('current', "Current Window") : undefined,
|
||||
buttons: currentWindowId !== window.id ? window.dirty ? [this.closeDirtyWindowAction] : [this.closeWindowAction] : undefined
|
||||
};
|
||||
});
|
||||
const autoFocusIndex = (picks.indexOf(picks.filter(pick => pick.payload === currentWindowId)[0]) + 1) % picks.length;
|
||||
|
||||
@@ -4,23 +4,23 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import * as nls from 'vs/nls';
|
||||
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { localize } from 'vs/nls';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { SyncActionDescriptor, MenuRegistry, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IWorkbenchActionRegistry, Extensions, CATEGORIES } from 'vs/workbench/common/actions';
|
||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { isLinux, isMacintosh } from 'vs/base/common/platform';
|
||||
import { ToggleDevToolsAction, ConfigureRuntimeArgumentsAction } from 'vs/workbench/electron-sandbox/actions/developerActions';
|
||||
import { ZoomResetAction, ZoomOutAction, ZoomInAction, CloseCurrentWindowAction, SwitchWindow, QuickSwitchWindow, ReloadWindowWithExtensionsDisabledAction, NewWindowTabHandler, ShowPreviousWindowTabHandler, ShowNextWindowTabHandler, MoveWindowTabToNewWindowHandler, MergeWindowTabsHandlerHandler, ToggleWindowTabsBarHandler } from 'vs/workbench/electron-sandbox/actions/windowActions';
|
||||
import { ConfigureRuntimeArgumentsAction, ToggleDevToolsAction, ToggleSharedProcessAction, ReloadWindowWithExtensionsDisabledAction } from 'vs/workbench/electron-sandbox/actions/developerActions';
|
||||
import { ZoomResetAction, ZoomOutAction, ZoomInAction, CloseCurrentWindowAction, SwitchWindow, QuickSwitchWindow, NewWindowTabHandler, ShowPreviousWindowTabHandler, ShowNextWindowTabHandler, MoveWindowTabToNewWindowHandler, MergeWindowTabsHandlerHandler, ToggleWindowTabsBarHandler } from 'vs/workbench/electron-sandbox/actions/windowActions';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IsDevelopmentContext, IsMacContext } from 'vs/platform/contextkey/common/contextkeys';
|
||||
import { IsMacContext } from 'vs/platform/contextkey/common/contextkeys';
|
||||
import { EditorsVisibleContext, SingleEditorGroupsContext } from 'vs/workbench/common/editor';
|
||||
import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
||||
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
|
||||
// Actions
|
||||
@@ -68,12 +68,12 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
(function registerMacOSNativeTabsActions(): void {
|
||||
if (isMacintosh) {
|
||||
[
|
||||
{ handler: NewWindowTabHandler, id: 'workbench.action.newWindowTab', title: { value: nls.localize('newTab', "New Window Tab"), original: 'New Window Tab' } },
|
||||
{ handler: ShowPreviousWindowTabHandler, id: 'workbench.action.showPreviousWindowTab', title: { value: nls.localize('showPreviousTab', "Show Previous Window Tab"), original: 'Show Previous Window Tab' } },
|
||||
{ handler: ShowNextWindowTabHandler, id: 'workbench.action.showNextWindowTab', title: { value: nls.localize('showNextWindowTab', "Show Next Window Tab"), original: 'Show Next Window Tab' } },
|
||||
{ handler: MoveWindowTabToNewWindowHandler, id: 'workbench.action.moveWindowTabToNewWindow', title: { value: nls.localize('moveWindowTabToNewWindow', "Move Window Tab to New Window"), original: 'Move Window Tab to New Window' } },
|
||||
{ handler: MergeWindowTabsHandlerHandler, id: 'workbench.action.mergeAllWindowTabs', title: { value: nls.localize('mergeAllWindowTabs', "Merge All Windows"), original: 'Merge All Windows' } },
|
||||
{ handler: ToggleWindowTabsBarHandler, id: 'workbench.action.toggleWindowTabsBar', title: { value: nls.localize('toggleWindowTabsBar', "Toggle Window Tabs Bar"), original: 'Toggle Window Tabs Bar' } }
|
||||
{ handler: NewWindowTabHandler, id: 'workbench.action.newWindowTab', title: { value: localize('newTab', "New Window Tab"), original: 'New Window Tab' } },
|
||||
{ handler: ShowPreviousWindowTabHandler, id: 'workbench.action.showPreviousWindowTab', title: { value: localize('showPreviousTab', "Show Previous Window Tab"), original: 'Show Previous Window Tab' } },
|
||||
{ handler: ShowNextWindowTabHandler, id: 'workbench.action.showNextWindowTab', title: { value: localize('showNextWindowTab', "Show Next Window Tab"), original: 'Show Next Window Tab' } },
|
||||
{ handler: MoveWindowTabToNewWindowHandler, id: 'workbench.action.moveWindowTabToNewWindow', title: { value: localize('moveWindowTabToNewWindow', "Move Window Tab to New Window"), original: 'Move Window Tab to New Window' } },
|
||||
{ handler: MergeWindowTabsHandlerHandler, id: 'workbench.action.mergeAllWindowTabs', title: { value: localize('mergeAllWindowTabs', "Merge All Windows"), original: 'Merge All Windows' } },
|
||||
{ handler: ToggleWindowTabsBarHandler, id: 'workbench.action.toggleWindowTabsBar', title: { value: localize('toggleWindowTabsBar', "Toggle Window Tabs Bar"), original: 'Toggle Window Tabs Bar' } }
|
||||
].forEach(command => {
|
||||
CommandsRegistry.registerCommand(command.id, command.handler);
|
||||
|
||||
@@ -87,22 +87,10 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
|
||||
// Actions: Developer
|
||||
(function registerDeveloperActions(): void {
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(ReloadWindowWithExtensionsDisabledAction), 'Developer: Reload With Extensions Disabled', CATEGORIES.Developer.value);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleDevToolsAction), 'Developer: Toggle Developer Tools', CATEGORIES.Developer.value);
|
||||
|
||||
KeybindingsRegistry.registerKeybindingRule({
|
||||
id: ToggleDevToolsAction.ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib + 50,
|
||||
when: IsDevelopmentContext,
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_I,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_I }
|
||||
});
|
||||
})();
|
||||
|
||||
// Actions: Runtime Arguments
|
||||
(function registerRuntimeArgumentsAction(): void {
|
||||
const preferencesCategory = nls.localize('preferences', "Preferences");
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(ConfigureRuntimeArgumentsAction), 'Preferences: Configure Runtime Arguments', preferencesCategory);
|
||||
registerAction2(ReloadWindowWithExtensionsDisabledAction);
|
||||
registerAction2(ConfigureRuntimeArgumentsAction);
|
||||
registerAction2(ToggleSharedProcessAction);
|
||||
registerAction2(ToggleDevToolsAction);
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -112,7 +100,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
group: '6_close',
|
||||
command: {
|
||||
id: CloseCurrentWindowAction.ID,
|
||||
title: nls.localize({ key: 'miCloseWindow', comment: ['&& denotes a mnemonic'] }, "Clos&&e Window")
|
||||
title: localize({ key: 'miCloseWindow', comment: ['&& denotes a mnemonic'] }, "Clos&&e Window")
|
||||
},
|
||||
order: 4
|
||||
});
|
||||
@@ -121,7 +109,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
group: 'z_Exit',
|
||||
command: {
|
||||
id: 'workbench.action.quit',
|
||||
title: nls.localize({ key: 'miExit', comment: ['&& denotes a mnemonic'] }, "E&&xit")
|
||||
title: localize({ key: 'miExit', comment: ['&& denotes a mnemonic'] }, "E&&xit")
|
||||
},
|
||||
order: 1,
|
||||
when: IsMacContext.toNegated()
|
||||
@@ -133,7 +121,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
group: '3_zoom',
|
||||
command: {
|
||||
id: ZoomInAction.ID,
|
||||
title: nls.localize({ key: 'miZoomIn', comment: ['&& denotes a mnemonic'] }, "&&Zoom In")
|
||||
title: localize({ key: 'miZoomIn', comment: ['&& denotes a mnemonic'] }, "&&Zoom In")
|
||||
},
|
||||
order: 1
|
||||
});
|
||||
@@ -142,7 +130,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
group: '3_zoom',
|
||||
command: {
|
||||
id: ZoomOutAction.ID,
|
||||
title: nls.localize({ key: 'miZoomOut', comment: ['&& denotes a mnemonic'] }, "&&Zoom Out")
|
||||
title: localize({ key: 'miZoomOut', comment: ['&& denotes a mnemonic'] }, "&&Zoom Out")
|
||||
},
|
||||
order: 2
|
||||
});
|
||||
@@ -151,7 +139,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
group: '3_zoom',
|
||||
command: {
|
||||
id: ZoomResetAction.ID,
|
||||
title: nls.localize({ key: 'miZoomReset', comment: ['&& denotes a mnemonic'] }, "&&Reset Zoom")
|
||||
title: localize({ key: 'miZoomReset', comment: ['&& denotes a mnemonic'] }, "&&Reset Zoom")
|
||||
},
|
||||
order: 3
|
||||
});
|
||||
@@ -161,27 +149,18 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
group: '3_feedback',
|
||||
command: {
|
||||
id: 'workbench.action.openIssueReporter',
|
||||
title: nls.localize({ key: 'miReportIssue', comment: ['&& denotes a mnemonic', 'Translate this to "Report Issue in English" in all languages please!'] }, "Report &&Issue")
|
||||
title: localize({ key: 'miReportIssue', comment: ['&& denotes a mnemonic', 'Translate this to "Report Issue in English" in all languages please!'] }, "Report &&Issue")
|
||||
},
|
||||
order: 3
|
||||
});
|
||||
}
|
||||
|
||||
// Tools
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
|
||||
group: '5_tools',
|
||||
command: {
|
||||
id: ToggleDevToolsAction.ID,
|
||||
title: nls.localize({ key: 'miToggleDevTools', comment: ['&& denotes a mnemonic'] }, "&&Toggle Developer Tools")
|
||||
},
|
||||
order: 1
|
||||
});
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
|
||||
group: '5_tools',
|
||||
command: {
|
||||
id: 'workbench.action.openProcessExplorer',
|
||||
title: nls.localize({ key: 'miOpenProcessExplorerer', comment: ['&& denotes a mnemonic'] }, "Open &&Process Explorer")
|
||||
title: localize({ key: 'miOpenProcessExplorerer', comment: ['&& denotes a mnemonic'] }, "Open &&Process Explorer")
|
||||
},
|
||||
order: 2
|
||||
});
|
||||
@@ -195,95 +174,96 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
registry.registerConfiguration({
|
||||
'id': 'window',
|
||||
'order': 8,
|
||||
'title': nls.localize('windowConfigurationTitle', "Window"),
|
||||
'title': localize('windowConfigurationTitle', "Window"),
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'window.openWithoutArgumentsInNewWindow': {
|
||||
'type': 'string',
|
||||
'enum': ['on', 'off'],
|
||||
'enumDescriptions': [
|
||||
nls.localize('window.openWithoutArgumentsInNewWindow.on', "Open a new empty window."),
|
||||
nls.localize('window.openWithoutArgumentsInNewWindow.off', "Focus the last active running instance.")
|
||||
localize('window.openWithoutArgumentsInNewWindow.on', "Open a new empty window."),
|
||||
localize('window.openWithoutArgumentsInNewWindow.off', "Focus the last active running instance.")
|
||||
],
|
||||
'default': isMacintosh ? 'off' : 'on',
|
||||
'scope': ConfigurationScope.APPLICATION,
|
||||
'markdownDescription': nls.localize('openWithoutArgumentsInNewWindow', "Controls whether a new empty window should open when starting a second instance without arguments or if the last running instance should get focus.\nNote that there can still be cases where this setting is ignored (e.g. when using the `--new-window` or `--reuse-window` command line option).")
|
||||
'markdownDescription': localize('openWithoutArgumentsInNewWindow', "Controls whether a new empty window should open when starting a second instance without arguments or if the last running instance should get focus.\nNote that there can still be cases where this setting is ignored (e.g. when using the `--new-window` or `--reuse-window` command line option).")
|
||||
},
|
||||
'window.restoreWindows': {
|
||||
'type': 'string',
|
||||
'enum': ['preserve', 'all', 'folders', 'one', 'none'],
|
||||
'enumDescriptions': [
|
||||
nls.localize('window.reopenFolders.preserve', "Always reopen all windows. If a folder or workspace is opened (e.g. from the command line) it opens as a new window unless it was opened before. If files are opened they will open in one of the restored windows."),
|
||||
nls.localize('window.reopenFolders.all', "Reopen all windows unless a folder, workspace or file is opened (e.g. from the command line)."),
|
||||
nls.localize('window.reopenFolders.folders', "Reopen all windows that had folders or workspaces opened unless a folder, workspace or file is opened (e.g. from the command line)."),
|
||||
nls.localize('window.reopenFolders.one', "Reopen the last active window unless a folder, workspace or file is opened (e.g. from the command line)."),
|
||||
nls.localize('window.reopenFolders.none', "Never reopen a window. Unless a folder or workspace is opened (e.g. from the command line), an empty window will appear.")
|
||||
localize('window.reopenFolders.preserve', "Always reopen all windows. If a folder or workspace is opened (e.g. from the command line) it opens as a new window unless it was opened before. If files are opened they will open in one of the restored windows."),
|
||||
localize('window.reopenFolders.all', "Reopen all windows unless a folder, workspace or file is opened (e.g. from the command line)."),
|
||||
localize('window.reopenFolders.folders', "Reopen all windows that had folders or workspaces opened unless a folder, workspace or file is opened (e.g. from the command line)."),
|
||||
localize('window.reopenFolders.one', "Reopen the last active window unless a folder, workspace or file is opened (e.g. from the command line)."),
|
||||
localize('window.reopenFolders.none', "Never reopen a window. Unless a folder or workspace is opened (e.g. from the command line), an empty window will appear.")
|
||||
],
|
||||
'default': 'all',
|
||||
'scope': ConfigurationScope.APPLICATION,
|
||||
'description': nls.localize('restoreWindows', "Controls how windows are being reopened after starting for the first time. This setting has no effect when the application is already running.")
|
||||
'description': localize('restoreWindows', "Controls how windows are being reopened after starting for the first time. This setting has no effect when the application is already running.")
|
||||
},
|
||||
'window.restoreFullscreen': {
|
||||
'type': 'boolean',
|
||||
'default': false,
|
||||
'scope': ConfigurationScope.APPLICATION,
|
||||
'description': nls.localize('restoreFullscreen', "Controls whether a window should restore to full screen mode if it was exited in full screen mode.")
|
||||
'description': localize('restoreFullscreen', "Controls whether a window should restore to full screen mode if it was exited in full screen mode.")
|
||||
},
|
||||
'window.zoomLevel': {
|
||||
'type': 'number',
|
||||
'default': 0,
|
||||
'description': nls.localize('zoomLevel', "Adjust the zoom level of the window. The original size is 0 and each increment above (e.g. 1) or below (e.g. -1) represents zooming 20% larger or smaller. You can also enter decimals to adjust the zoom level with a finer granularity.")
|
||||
'description': localize('zoomLevel', "Adjust the zoom level of the window. The original size is 0 and each increment above (e.g. 1) or below (e.g. -1) represents zooming 20% larger or smaller. You can also enter decimals to adjust the zoom level with a finer granularity."),
|
||||
ignoreSync: true
|
||||
},
|
||||
'window.newWindowDimensions': {
|
||||
'type': 'string',
|
||||
'enum': ['default', 'inherit', 'offset', 'maximized', 'fullscreen'],
|
||||
'enumDescriptions': [
|
||||
nls.localize('window.newWindowDimensions.default', "Open new windows in the center of the screen."),
|
||||
nls.localize('window.newWindowDimensions.inherit', "Open new windows with same dimension as last active one."),
|
||||
nls.localize('window.newWindowDimensions.offset', "Open new windows with same dimension as last active one with an offset position."),
|
||||
nls.localize('window.newWindowDimensions.maximized', "Open new windows maximized."),
|
||||
nls.localize('window.newWindowDimensions.fullscreen', "Open new windows in full screen mode.")
|
||||
localize('window.newWindowDimensions.default', "Open new windows in the center of the screen."),
|
||||
localize('window.newWindowDimensions.inherit', "Open new windows with same dimension as last active one."),
|
||||
localize('window.newWindowDimensions.offset', "Open new windows with same dimension as last active one with an offset position."),
|
||||
localize('window.newWindowDimensions.maximized', "Open new windows maximized."),
|
||||
localize('window.newWindowDimensions.fullscreen', "Open new windows in full screen mode.")
|
||||
],
|
||||
'default': 'default',
|
||||
'scope': ConfigurationScope.APPLICATION,
|
||||
'description': nls.localize('newWindowDimensions', "Controls the dimensions of opening a new window when at least one window is already opened. Note that this setting does not have an impact on the first window that is opened. The first window will always restore the size and location as you left it before closing.")
|
||||
'description': localize('newWindowDimensions', "Controls the dimensions of opening a new window when at least one window is already opened. Note that this setting does not have an impact on the first window that is opened. The first window will always restore the size and location as you left it before closing.")
|
||||
},
|
||||
'window.closeWhenEmpty': {
|
||||
'type': 'boolean',
|
||||
'default': false,
|
||||
'description': nls.localize('closeWhenEmpty', "Controls whether closing the last editor should also close the window. This setting only applies for windows that do not show folders.")
|
||||
'description': localize('closeWhenEmpty', "Controls whether closing the last editor should also close the window. This setting only applies for windows that do not show folders.")
|
||||
},
|
||||
'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`.")
|
||||
'markdownDescription': 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'],
|
||||
'default': isLinux ? 'native' : 'custom',
|
||||
'scope': ConfigurationScope.APPLICATION,
|
||||
'description': nls.localize('titleBarStyle', "Adjust the appearance of the window title bar. On Linux and Windows, this setting also affects the application and context menu appearances. Changes require a full restart to apply.")
|
||||
'description': localize('titleBarStyle', "Adjust the appearance of the window title bar. On Linux and Windows, this setting also affects the application and context menu appearances. Changes require a full restart to apply.")
|
||||
},
|
||||
'window.dialogStyle': {
|
||||
'type': 'string',
|
||||
'enum': ['native', 'custom'],
|
||||
'default': 'native',
|
||||
'scope': ConfigurationScope.APPLICATION,
|
||||
'description': nls.localize('dialogStyle', "Adjust the appearance of dialog windows.")
|
||||
'description': localize('dialogStyle', "Adjust the appearance of dialog windows.")
|
||||
},
|
||||
'window.nativeTabs': {
|
||||
'type': 'boolean',
|
||||
'default': false,
|
||||
'scope': ConfigurationScope.APPLICATION,
|
||||
'description': nls.localize('window.nativeTabs', "Enables macOS Sierra window tabs. Note that changes require a full restart to apply and that native tabs will disable a custom title bar style if configured."),
|
||||
'description': localize('window.nativeTabs', "Enables macOS Sierra window tabs. Note that changes require a full restart to apply and that native tabs will disable a custom title bar style if configured."),
|
||||
'included': isMacintosh
|
||||
},
|
||||
'window.nativeFullScreen': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'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."),
|
||||
'description': 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."),
|
||||
'scope': ConfigurationScope.APPLICATION,
|
||||
'included': isMacintosh
|
||||
},
|
||||
@@ -291,14 +271,8 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'scope': ConfigurationScope.APPLICATION,
|
||||
'description': nls.localize('window.clickThroughInactive', "If enabled, clicking on an inactive window will both activate the window and trigger the element under the mouse if it is clickable. If disabled, clicking anywhere on an inactive window will activate it only and a second click is required on the element."),
|
||||
'description': localize('window.clickThroughInactive', "If enabled, clicking on an inactive window will both activate the window and trigger the element under the mouse if it is clickable. If disabled, clicking anywhere on an inactive window will activate it only and a second click is required on the element."),
|
||||
'included': isMacintosh
|
||||
},
|
||||
'window.enableExperimentalProxyLoginDialog': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'scope': ConfigurationScope.APPLICATION,
|
||||
'description': nls.localize('window.enableExperimentalProxyLoginDialog', "Enables a new login dialog for proxy authentication. Requires a restart to take effect."),
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -307,12 +281,12 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
registry.registerConfiguration({
|
||||
'id': 'telemetry',
|
||||
'order': 110,
|
||||
title: nls.localize('telemetryConfigurationTitle', "Telemetry"),
|
||||
title: localize('telemetryConfigurationTitle', "Telemetry"),
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'telemetry.enableCrashReporter': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('telemetry.enableCrashReporting', "Enable crash reports to be sent to a Microsoft online service. \nThis option requires restart to take effect."),
|
||||
'description': localize('telemetry.enableCrashReporting', "Enable crash reports to be sent to a Microsoft online service. \nThis option requires restart to take effect."),
|
||||
'default': true,
|
||||
'tags': ['usesOnlineServices']
|
||||
}
|
||||
@@ -324,12 +298,12 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
'id': 'keyboard',
|
||||
'order': 15,
|
||||
'type': 'object',
|
||||
'title': nls.localize('keyboardConfigurationTitle', "Keyboard"),
|
||||
'title': localize('keyboardConfigurationTitle', "Keyboard"),
|
||||
'properties': {
|
||||
'keyboard.touchbar.enabled': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'description': nls.localize('touchbar.enabled', "Enables the macOS touchbar buttons on the keyboard if available."),
|
||||
'description': localize('touchbar.enabled', "Enables the macOS touchbar buttons on the keyboard if available."),
|
||||
'included': isMacintosh
|
||||
},
|
||||
'keyboard.touchbar.ignored': {
|
||||
@@ -338,7 +312,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
'type': 'string'
|
||||
},
|
||||
'default': [],
|
||||
'markdownDescription': nls.localize('touchbar.ignored', 'A set of identifiers for entries in the touchbar that should not show up (for example `workbench.action.navigateBack`.'),
|
||||
'markdownDescription': localize('touchbar.ignored', 'A set of identifiers for entries in the touchbar that should not show up (for example `workbench.action.navigateBack`.'),
|
||||
'included': isMacintosh
|
||||
}
|
||||
}
|
||||
@@ -359,31 +333,31 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
properties: {
|
||||
locale: {
|
||||
type: 'string',
|
||||
description: nls.localize('argv.locale', 'The display Language to use. Picking a different language requires the associated language pack to be installed.')
|
||||
description: localize('argv.locale', 'The display Language to use. Picking a different language requires the associated language pack to be installed.')
|
||||
},
|
||||
'disable-hardware-acceleration': {
|
||||
type: 'boolean',
|
||||
description: nls.localize('argv.disableHardwareAcceleration', 'Disables hardware acceleration. ONLY change this option if you encounter graphic issues.')
|
||||
description: localize('argv.disableHardwareAcceleration', 'Disables hardware acceleration. ONLY change this option if you encounter graphic issues.')
|
||||
},
|
||||
'disable-color-correct-rendering': {
|
||||
type: 'boolean',
|
||||
description: nls.localize('argv.disableColorCorrectRendering', 'Resolves issues around color profile selection. ONLY change this option if you encounter graphic issues.')
|
||||
description: localize('argv.disableColorCorrectRendering', 'Resolves issues around color profile selection. ONLY change this option if you encounter graphic issues.')
|
||||
},
|
||||
'force-color-profile': {
|
||||
type: 'string',
|
||||
markdownDescription: nls.localize('argv.forceColorProfile', 'Allows to override the color profile to use. If you experience colors appear badly, try to set this to `srgb` and restart.')
|
||||
markdownDescription: localize('argv.forceColorProfile', 'Allows to override the color profile to use. If you experience colors appear badly, try to set this to `srgb` and restart.')
|
||||
},
|
||||
'enable-crash-reporter': {
|
||||
type: 'boolean',
|
||||
markdownDescription: nls.localize('argv.enableCrashReporter', 'Allows to disable crash reporting, should restart the app if the value is changed.')
|
||||
markdownDescription: localize('argv.enableCrashReporter', 'Allows to disable crash reporting, should restart the app if the value is changed.')
|
||||
},
|
||||
'crash-reporter-id': {
|
||||
type: 'string',
|
||||
markdownDescription: nls.localize('argv.crashReporterId', 'Unique id used for correlating crash reports sent from this app instance.')
|
||||
markdownDescription: localize('argv.crashReporterId', 'Unique id used for correlating crash reports sent from this app instance.')
|
||||
},
|
||||
'enable-proposed-api': {
|
||||
type: 'array',
|
||||
description: nls.localize('argv.enebleProposedApi', "Enable proposed APIs for a list of extension ids (such as \`vscode.git\`). Proposed APIs are unstable and subject to breaking without warning at any time. This should only be set for extension development and testing purposes."),
|
||||
description: localize('argv.enebleProposedApi', "Enable proposed APIs for a list of extension ids (such as \`vscode.git\`). Proposed APIs are unstable and subject to breaking without warning at any time. This should only be set for extension development and testing purposes."),
|
||||
items: {
|
||||
type: 'string'
|
||||
}
|
||||
@@ -393,7 +367,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
if (isLinux) {
|
||||
schema.properties!['force-renderer-accessibility'] = {
|
||||
type: 'boolean',
|
||||
description: nls.localize('argv.force-renderer-accessibility', 'Forces the renderer to be accessible. ONLY change this if you are using a screen reader on Linux. On other platforms the renderer will automatically be accessible. This flag is automatically set if you have editor.accessibilitySupport: on.'),
|
||||
description: localize('argv.force-renderer-accessibility', 'Forces the renderer to be accessible. ONLY change this if you are using a screen reader on Linux. On other platforms the renderer will automatically be accessible. This flag is automatically set if you have editor.accessibilitySupport: on.'),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,24 +4,25 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { zoomLevelToZoomFactor } from 'vs/platform/windows/common/windows';
|
||||
import { importEntries, mark } from 'vs/base/common/performance';
|
||||
import { mark } from 'vs/base/common/performance';
|
||||
import { Workbench } from 'vs/workbench/browser/workbench';
|
||||
import { NativeWindow } from 'vs/workbench/electron-sandbox/window';
|
||||
import { setZoomLevel, setZoomFactor, setFullscreen } from 'vs/base/browser/browser';
|
||||
import { domContentLoaded, addDisposableListener, EventType, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
|
||||
import { domContentLoaded } from 'vs/base/browser/dom';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { reviveWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { reviveIdentifier } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IWorkbenchConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IMainProcessService, MainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
|
||||
import { IMainProcessService, ElectronIPCMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
|
||||
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { RemoteAgentService } from 'vs/workbench/services/remote/electron-sandbox/remoteAgentServiceImpl';
|
||||
import { FileService } from 'vs/platform/files/common/fileService';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { RemoteFileSystemProvider } from 'vs/workbench/services/remote/common/remoteAgentFileSystemChannel';
|
||||
@@ -31,7 +32,7 @@ import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
||||
import { NativeHostService } from 'vs/platform/native/electron-sandbox/nativeHostService';
|
||||
import { SimpleConfigurationService, simpleFileSystemProvider, SimpleLogService, SimpleRemoteAgentService, SimpleSignService, SimpleStorageService, SimpleNativeWorkbenchEnvironmentService, SimpleWorkspaceService } from 'vs/workbench/electron-sandbox/sandbox.simpleservices';
|
||||
import { SimpleConfigurationService, simpleFileSystemProvider, SimpleLogService, SimpleSignService, SimpleStorageService, SimpleNativeWorkbenchEnvironmentService, SimpleWorkspaceService } from 'vs/workbench/electron-sandbox/sandbox.simpleservices';
|
||||
import { INativeWorkbenchConfiguration, INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService';
|
||||
import { RemoteAuthorityResolverService } from 'vs/platform/remote/electron-sandbox/remoteAuthorityResolverService';
|
||||
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
|
||||
@@ -39,6 +40,7 @@ import { UriIdentityService } from 'vs/workbench/services/uriIdentity/common/uri
|
||||
|
||||
class DesktopMain extends Disposable {
|
||||
|
||||
private readonly productService: IProductService = { _serviceBrand: undefined, ...product };
|
||||
private readonly environmentService = new SimpleNativeWorkbenchEnvironmentService(this.configuration);
|
||||
|
||||
constructor(private configuration: INativeWorkbenchConfiguration) {
|
||||
@@ -52,9 +54,6 @@ class DesktopMain extends Disposable {
|
||||
// Massage configuration file URIs
|
||||
this.reviveUris();
|
||||
|
||||
// Setup perf
|
||||
importEntries(this.configuration.perfEntries);
|
||||
|
||||
// Browser config
|
||||
const zoomLevel = this.configuration.zoomLevel || 0;
|
||||
setZoomFactor(zoomLevelToZoomFactor(zoomLevel));
|
||||
@@ -63,14 +62,11 @@ class DesktopMain extends Disposable {
|
||||
}
|
||||
|
||||
private reviveUris() {
|
||||
if (this.configuration.folderUri) {
|
||||
this.configuration.folderUri = URI.revive(this.configuration.folderUri);
|
||||
}
|
||||
|
||||
if (this.configuration.workspace) {
|
||||
this.configuration.workspace = reviveWorkspaceIdentifier(this.configuration.workspace);
|
||||
}
|
||||
// Workspace
|
||||
this.configuration.workspace = reviveIdentifier(this.configuration.workspace);
|
||||
|
||||
// Files
|
||||
const filesToWait = this.configuration.filesToWait;
|
||||
const filesToWaitPaths = filesToWait?.paths;
|
||||
[filesToWaitPaths, this.configuration.filesToOpenOrCreate, this.configuration.filesToDiff].forEach(paths => {
|
||||
@@ -92,7 +88,7 @@ class DesktopMain extends Disposable {
|
||||
const services = await this.initServices();
|
||||
|
||||
await domContentLoaded();
|
||||
mark('willStartWorkbench');
|
||||
mark('code/willStartWorkbench');
|
||||
|
||||
// Create Workbench
|
||||
const workbench = new Workbench(document.body, services.serviceCollection, services.logService);
|
||||
@@ -112,35 +108,15 @@ class DesktopMain extends Disposable {
|
||||
|
||||
private registerListeners(workbench: Workbench, storageService: SimpleStorageService): void {
|
||||
|
||||
// Layout
|
||||
this._register(addDisposableListener(window, EventType.RESIZE, e => this.onWindowResize(e, true, workbench)));
|
||||
|
||||
// Workbench Lifecycle
|
||||
this._register(workbench.onShutdown(() => this.dispose()));
|
||||
this._register(workbench.onWillShutdown(event => event.join(storageService.close())));
|
||||
}
|
||||
|
||||
private onWindowResize(e: Event, retry: boolean, workbench: Workbench): void {
|
||||
if (e.target === window) {
|
||||
if (window.document && window.document.body && window.document.body.clientWidth === 0) {
|
||||
// TODO@Ben this is an electron issue on macOS when simple fullscreen is enabled
|
||||
// where for some reason the window clientWidth is reported as 0 when switching
|
||||
// between simple fullscreen and normal screen. In that case we schedule the layout
|
||||
// call at the next animation frame once, in the hope that the dimensions are
|
||||
// proper then.
|
||||
if (retry) {
|
||||
scheduleAtNextAnimationFrame(() => this.onWindowResize(e, false, workbench));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
workbench.layout();
|
||||
}
|
||||
this._register(workbench.onWillShutdown(event => event.join(storageService.close(), 'join.closeStorage')));
|
||||
}
|
||||
|
||||
private async initServices(): Promise<{ serviceCollection: ServiceCollection, logService: ILogService, storageService: SimpleStorageService }> {
|
||||
const serviceCollection = new ServiceCollection();
|
||||
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
//
|
||||
// NOTE: Please do NOT register services here. Use `registerSingleton()`
|
||||
@@ -155,7 +131,7 @@ class DesktopMain extends Disposable {
|
||||
|
||||
|
||||
// Main Process
|
||||
const mainProcessService = this._register(new MainProcessService(this.configuration.windowId));
|
||||
const mainProcessService = this._register(new ElectronIPCMainProcessService(this.configuration.windowId));
|
||||
serviceCollection.set(IMainProcessService, mainProcessService);
|
||||
|
||||
// Environment
|
||||
@@ -163,8 +139,7 @@ class DesktopMain extends Disposable {
|
||||
serviceCollection.set(INativeWorkbenchEnvironmentService, this.environmentService);
|
||||
|
||||
// Product
|
||||
const productService: IProductService = { _serviceBrand: undefined, ...product };
|
||||
serviceCollection.set(IProductService, productService);
|
||||
serviceCollection.set(IProductService, this.productService);
|
||||
|
||||
// Log
|
||||
const logService = new SimpleLogService();
|
||||
@@ -174,14 +149,6 @@ class DesktopMain extends Disposable {
|
||||
const remoteAuthorityResolverService = new RemoteAuthorityResolverService();
|
||||
serviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService);
|
||||
|
||||
// Sign
|
||||
const signService = new SimpleSignService();
|
||||
serviceCollection.set(ISignService, signService);
|
||||
|
||||
// Remote Agent
|
||||
const remoteAgentService = new SimpleRemoteAgentService();
|
||||
serviceCollection.set(IRemoteAgentService, remoteAgentService);
|
||||
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
//
|
||||
@@ -196,6 +163,14 @@ class DesktopMain extends Disposable {
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
|
||||
// Sign
|
||||
const signService = new SimpleSignService();
|
||||
serviceCollection.set(ISignService, signService);
|
||||
|
||||
// Remote Agent
|
||||
const remoteAgentService = this._register(new RemoteAgentService(this.environmentService, this.productService, remoteAuthorityResolverService, signService, logService));
|
||||
serviceCollection.set(IRemoteAgentService, remoteAgentService);
|
||||
|
||||
// Native Host
|
||||
const nativeHostService = new NativeHostService(this.configuration.windowId, mainProcessService) as INativeHostService;
|
||||
serviceCollection.set(INativeHostService, nativeHostService);
|
||||
@@ -213,11 +188,6 @@ class DesktopMain extends Disposable {
|
||||
const uriIdentityService = new UriIdentityService(fileService);
|
||||
serviceCollection.set(IUriIdentityService, uriIdentityService);
|
||||
|
||||
const connection = remoteAgentService.getConnection();
|
||||
if (connection) {
|
||||
const remoteFileSystemProvider = this._register(new RemoteFileSystemProvider(remoteAgentService));
|
||||
fileService.registerProvider(Schemas.vscodeRemote, remoteFileSystemProvider);
|
||||
}
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
//
|
||||
@@ -232,6 +202,12 @@ class DesktopMain extends Disposable {
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
|
||||
const connection = remoteAgentService.getConnection();
|
||||
if (connection) {
|
||||
const remoteFileSystemProvider = this._register(new RemoteFileSystemProvider(remoteAgentService));
|
||||
fileService.registerProvider(Schemas.vscodeRemote, remoteFileSystemProvider);
|
||||
}
|
||||
|
||||
const services = await Promise.all([
|
||||
this.createWorkspaceService().then(service => {
|
||||
|
||||
@@ -239,7 +215,7 @@ class DesktopMain extends Disposable {
|
||||
serviceCollection.set(IWorkspaceContextService, service);
|
||||
|
||||
// Configuration
|
||||
serviceCollection.set(IConfigurationService, new SimpleConfigurationService());
|
||||
serviceCollection.set(IWorkbenchConfigurationService, new SimpleConfigurationService());
|
||||
|
||||
return service;
|
||||
}),
|
||||
|
||||
@@ -76,7 +76,7 @@ export class DialogHandlerContribution extends Disposable implements IWorkbenchC
|
||||
// Message
|
||||
else if (this.currentDialog.args.showArgs) {
|
||||
const args = this.currentDialog.args.showArgs;
|
||||
result = this.useCustomDialog ?
|
||||
result = this.useCustomDialog || args.options?.useCustom ?
|
||||
await this.browserImpl.show(args.severity, args.message, args.buttons, args.options) :
|
||||
await this.nativeImpl.show(args.severity, args.message, args.buttons, args.options);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as nls from 'vs/nls';
|
||||
import { fromNow } from 'vs/base/common/date';
|
||||
import { mnemonicButtonLabel } from 'vs/base/common/labels';
|
||||
import { isLinux, isWindows } from 'vs/base/common/platform';
|
||||
import { isLinux, isLinuxSnap, isWindows } from 'vs/base/common/platform';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { MessageBoxOptions } from 'vs/base/parts/sandbox/common/electronTypes';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
@@ -159,9 +159,10 @@ export class NativeDialogHandler implements IDialogHandler {
|
||||
let version = this.productService.version;
|
||||
if (this.productService.target) {
|
||||
version = `${version} (${this.productService.target} setup)`;
|
||||
} else if (this.productService.darwinUniversalAssetId) {
|
||||
version = `${version} (Universal)`;
|
||||
}
|
||||
|
||||
const isSnap = process.platform === 'linux' && process.env.SNAP && process.env.SNAP_REVISION;
|
||||
const osProps = await this.nativeHostService.getOSProperties();
|
||||
|
||||
const detailString = (useAgo: boolean): string => {
|
||||
@@ -174,7 +175,7 @@ export class NativeDialogHandler implements IDialogHandler {
|
||||
process.versions['chrome'],
|
||||
process.versions['node'],
|
||||
process.versions['v8'],
|
||||
`${osProps.type} ${osProps.arch} ${osProps.release}${isSnap ? ' snap' : ''}`
|
||||
`${osProps.type} ${osProps.arch} ${osProps.release}${isLinuxSnap ? ' snap' : ''}`
|
||||
);
|
||||
};
|
||||
|
||||
@@ -206,4 +207,3 @@ export class NativeDialogHandler implements IDialogHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IAction, Separator } from 'vs/base/common/actions';
|
||||
import { IMenuService, MenuId, IMenu, SubmenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService';
|
||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { IUpdateService } from 'vs/platform/update/common/update';
|
||||
import { MenubarControl } from 'vs/workbench/browser/parts/titlebar/menubarControl';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { IMenubarData, IMenubarMenu, IMenubarKeybinding, IMenubarMenuItemSubmenu, IMenubarMenuItemAction, MenubarMenuItem } from 'vs/platform/menubar/common/menubar';
|
||||
import { IMenubarService } from 'vs/platform/menubar/electron-sandbox/menubar';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
|
||||
export class NativeMenubarControl extends MenubarControl {
|
||||
|
||||
constructor(
|
||||
@IMenuService menuService: IMenuService,
|
||||
@IWorkspacesService workspacesService: IWorkspacesService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IKeybindingService keybindingService: IKeybindingService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@ILabelService labelService: ILabelService,
|
||||
@IUpdateService updateService: IUpdateService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@INotificationService notificationService: INotificationService,
|
||||
@IPreferencesService preferencesService: IPreferencesService,
|
||||
@INativeWorkbenchEnvironmentService protected readonly environmentService: INativeWorkbenchEnvironmentService,
|
||||
@IAccessibilityService accessibilityService: IAccessibilityService,
|
||||
@IMenubarService private readonly menubarService: IMenubarService,
|
||||
@IHostService hostService: IHostService,
|
||||
@INativeHostService private readonly nativeHostService: INativeHostService,
|
||||
@ICommandService commandService: ICommandService,
|
||||
) {
|
||||
super(menuService, workspacesService, contextKeyService, keybindingService, configurationService, labelService, updateService, storageService, notificationService, preferencesService, environmentService, accessibilityService, hostService, commandService);
|
||||
|
||||
if (isMacintosh) {
|
||||
this.menus['Preferences'] = this._register(this.menuService.createMenu(MenuId.MenubarPreferencesMenu, this.contextKeyService));
|
||||
this.topLevelTitles['Preferences'] = localize('mPreferences', "Preferences");
|
||||
}
|
||||
|
||||
for (const topLevelMenuName of Object.keys(this.topLevelTitles)) {
|
||||
const menu = this.menus[topLevelMenuName];
|
||||
if (menu) {
|
||||
this._register(menu.onDidChange(() => this.updateMenubar()));
|
||||
}
|
||||
}
|
||||
|
||||
(async () => {
|
||||
this.recentlyOpened = await this.workspacesService.getRecentlyOpened();
|
||||
|
||||
this.doUpdateMenubar();
|
||||
})();
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
protected doUpdateMenubar(): void {
|
||||
// Since the native menubar is shared between windows (main process)
|
||||
// only allow the focused window to update the menubar
|
||||
if (!this.hostService.hasFocus) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send menus to main process to be rendered by Electron
|
||||
const menubarData = { menus: {}, keybindings: {} };
|
||||
if (this.getMenubarMenus(menubarData)) {
|
||||
this.menubarService.updateMenubar(this.nativeHostService.windowId, menubarData);
|
||||
}
|
||||
}
|
||||
|
||||
private getMenubarMenus(menubarData: IMenubarData): boolean {
|
||||
if (!menubarData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
menubarData.keybindings = this.getAdditionalKeybindings();
|
||||
for (const topLevelMenuName of Object.keys(this.topLevelTitles)) {
|
||||
const menu = this.menus[topLevelMenuName];
|
||||
if (menu) {
|
||||
const menubarMenu: IMenubarMenu = { items: [] };
|
||||
this.populateMenuItems(menu, menubarMenu, menubarData.keybindings);
|
||||
if (menubarMenu.items.length === 0) {
|
||||
return false; // Menus are incomplete
|
||||
}
|
||||
menubarData.menus[topLevelMenuName] = menubarMenu;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private populateMenuItems(menu: IMenu, menuToPopulate: IMenubarMenu, keybindings: { [id: string]: IMenubarKeybinding | undefined }) {
|
||||
let groups = menu.getActions();
|
||||
for (let group of groups) {
|
||||
const [, actions] = group;
|
||||
|
||||
actions.forEach(menuItem => {
|
||||
|
||||
// use mnemonicTitle whenever possible
|
||||
const title = typeof menuItem.item.title === 'string'
|
||||
? menuItem.item.title
|
||||
: menuItem.item.title.mnemonicTitle ?? menuItem.item.title.value;
|
||||
|
||||
if (menuItem instanceof SubmenuItemAction) {
|
||||
const submenu = { items: [] };
|
||||
|
||||
if (!this.menus[menuItem.item.submenu.id]) {
|
||||
const menu = this.menus[menuItem.item.submenu.id] = this.menuService.createMenu(menuItem.item.submenu, this.contextKeyService);
|
||||
this._register(menu.onDidChange(() => this.updateMenubar()));
|
||||
}
|
||||
|
||||
const menuToDispose = this.menuService.createMenu(menuItem.item.submenu, this.contextKeyService);
|
||||
this.populateMenuItems(menuToDispose, submenu, keybindings);
|
||||
|
||||
let menubarSubmenuItem: IMenubarMenuItemSubmenu = {
|
||||
id: menuItem.id,
|
||||
label: title,
|
||||
submenu: submenu
|
||||
};
|
||||
|
||||
menuToPopulate.items.push(menubarSubmenuItem);
|
||||
menuToDispose.dispose();
|
||||
} else {
|
||||
if (menuItem.id === 'workbench.action.openRecent') {
|
||||
const actions = this.getOpenRecentActions().map(this.transformOpenRecentAction);
|
||||
menuToPopulate.items.push(...actions);
|
||||
}
|
||||
|
||||
let menubarMenuItem: IMenubarMenuItemAction = {
|
||||
id: menuItem.id,
|
||||
label: title
|
||||
};
|
||||
|
||||
if (menuItem.checked) {
|
||||
menubarMenuItem.checked = true;
|
||||
}
|
||||
|
||||
if (!menuItem.enabled) {
|
||||
menubarMenuItem.enabled = false;
|
||||
}
|
||||
|
||||
keybindings[menuItem.id] = this.getMenubarKeybinding(menuItem.id);
|
||||
menuToPopulate.items.push(menubarMenuItem);
|
||||
}
|
||||
});
|
||||
|
||||
menuToPopulate.items.push({ id: 'vscode.menubar.separator' });
|
||||
}
|
||||
|
||||
if (menuToPopulate.items.length > 0) {
|
||||
menuToPopulate.items.pop();
|
||||
}
|
||||
}
|
||||
|
||||
private transformOpenRecentAction(action: Separator | (IAction & { uri: URI })): MenubarMenuItem {
|
||||
if (action instanceof Separator) {
|
||||
return { id: 'vscode.menubar.separator' };
|
||||
}
|
||||
|
||||
return {
|
||||
id: action.id,
|
||||
uri: action.uri,
|
||||
enabled: action.enabled,
|
||||
label: action.label
|
||||
};
|
||||
}
|
||||
|
||||
private getAdditionalKeybindings(): { [id: string]: IMenubarKeybinding } {
|
||||
const keybindings: { [id: string]: IMenubarKeybinding } = {};
|
||||
if (isMacintosh) {
|
||||
const keybinding = this.getMenubarKeybinding('workbench.action.quit');
|
||||
if (keybinding) {
|
||||
keybindings['workbench.action.quit'] = keybinding;
|
||||
}
|
||||
}
|
||||
|
||||
return keybindings;
|
||||
}
|
||||
|
||||
private getMenubarKeybinding(id: string): IMenubarKeybinding | undefined {
|
||||
const binding = this.keybindingService.lookupKeybinding(id);
|
||||
if (!binding) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// first try to resolve a native accelerator
|
||||
const electronAccelerator = binding.getElectronAccelerator();
|
||||
if (electronAccelerator) {
|
||||
return { label: electronAccelerator, userSettingsLabel: withNullAsUndefined(binding.getUserSettingsLabel()) };
|
||||
}
|
||||
|
||||
// we need this fallback to support keybindings that cannot show in electron menus (e.g. chords)
|
||||
const acceleratorLabel = binding.getLabel();
|
||||
if (acceleratorLabel) {
|
||||
return { label: acceleratorLabel, isNative: false, userSettingsLabel: withNullAsUndefined(binding.getUserSettingsLabel()) };
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -24,9 +24,9 @@ import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
||||
import { getTitleBarStyle } from 'vs/platform/windows/common/windows';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { NativeMenubarControl } from 'vs/workbench/electron-sandbox/parts/titlebar/menubarControl';
|
||||
|
||||
export class TitlebarPart extends BrowserTitleBarPart {
|
||||
private appIcon: HTMLElement | undefined;
|
||||
private windowControls: HTMLElement | undefined;
|
||||
private maxRestoreControl: HTMLElement | undefined;
|
||||
private dragRegion: HTMLElement | undefined;
|
||||
@@ -119,7 +119,6 @@ export class TitlebarPart extends BrowserTitleBarPart {
|
||||
}
|
||||
|
||||
protected onConfigurationChanged(event: IConfigurationChangeEvent): void {
|
||||
|
||||
super.onConfigurationChanged(event);
|
||||
|
||||
if (event.affectsConfiguration('window.doubleClickIconToClose')) {
|
||||
@@ -165,9 +164,13 @@ export class TitlebarPart extends BrowserTitleBarPart {
|
||||
createContentArea(parent: HTMLElement): HTMLElement {
|
||||
const ret = super.createContentArea(parent);
|
||||
|
||||
// Native menu controller
|
||||
if (isMacintosh || getTitleBarStyle(this.configurationService) === 'native') {
|
||||
this._register(this.instantiationService.createInstance(NativeMenubarControl));
|
||||
}
|
||||
|
||||
// App Icon (Native Windows/Linux)
|
||||
if (!isMacintosh) {
|
||||
this.appIcon = DOM.prepend(this.element, DOM.$('div.window-appicon'));
|
||||
if (this.appIcon) {
|
||||
this.onUpdateAppIconDragBehavior();
|
||||
|
||||
this._register(DOM.addDisposableListener(this.appIcon, DOM.EventType.DBLCLICK, (e => {
|
||||
|
||||
@@ -11,13 +11,9 @@ import { ISignService } from 'vs/platform/sign/common/sign';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IRemoteAgentConnection, IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { IDiagnosticInfoOptions, IDiagnosticInfo } from 'vs/platform/diagnostics/common/diagnostics';
|
||||
import { IAddressProvider, ISocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment';
|
||||
import { IAddressProvider } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
import { ITelemetryData, ITelemetryInfo, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { BrowserSocketFactory } from 'vs/platform/remote/browser/browserSocketFactory';
|
||||
import { ExtensionIdentifier, IExtension, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtension } from 'vs/platform/extensions/common/extensions';
|
||||
import { SimpleConfigurationService as BaseSimpleConfigurationService } from 'vs/editor/standalone/browser/simpleServices';
|
||||
import { InMemoryStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
@@ -31,7 +27,7 @@ import { IWebviewService, WebviewContentOptions, WebviewElement, WebviewExtensio
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { AbstractTextFileService } from 'vs/workbench/services/textfile/browser/textFileService';
|
||||
import { IExtensionManagementServer, IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ITunnelProvider, ITunnelService, RemoteTunnel } from 'vs/platform/remote/common/tunnel';
|
||||
import { ITunnelProvider, ITunnelService, RemoteTunnel, TunnelProviderFeatures } from 'vs/platform/remote/common/tunnel';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IManualSyncTask, IResourcePreview, ISyncResourceHandle, ISyncTask, IUserDataAutoSyncService, IUserDataSyncService, IUserDataSyncStore, IUserDataSyncStoreManagementService, SyncResource, SyncStatus, UserDataSyncStoreType } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IUserDataSyncAccount, IUserDataSyncAccountService } from 'vs/platform/userDataSync/common/userDataSyncAccount';
|
||||
@@ -56,6 +52,7 @@ import { Schemas } from 'vs/base/common/network';
|
||||
import { BrowserKeyboardLayoutService } from 'vs/workbench/services/keybinding/browser/keyboardLayoutService';
|
||||
import { TerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminalInstanceService';
|
||||
import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { IWorkbenchConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
|
||||
|
||||
//#region Environment
|
||||
@@ -178,7 +175,7 @@ export class SimpleWorkspaceService implements IWorkspaceContextService {
|
||||
|
||||
getWorkspaceFolder(resource: URI): IWorkspaceFolder | null { return resource && resource.scheme === workspaceResource.scheme ? this.workspace.folders[0] : null; }
|
||||
isInsideWorkspace(resource: URI): boolean { return resource && resource.scheme === workspaceResource.scheme; }
|
||||
isCurrentWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): boolean { return true; }
|
||||
isCurrentWorkspace(workspaceIdOrFolder: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI): boolean { return true; }
|
||||
}
|
||||
|
||||
//#endregion
|
||||
@@ -193,7 +190,9 @@ export class SimpleStorageService extends InMemoryStorageService { }
|
||||
|
||||
//#region Configuration
|
||||
|
||||
export class SimpleConfigurationService extends BaseSimpleConfigurationService { }
|
||||
export class SimpleConfigurationService extends BaseSimpleConfigurationService implements IWorkbenchConfigurationService {
|
||||
async whenRemoteConfigurationLoaded() { }
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
@@ -412,28 +411,6 @@ module.exports = testRunner;`);
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Remote
|
||||
|
||||
export class SimpleRemoteAgentService implements IRemoteAgentService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
socketFactory: ISocketFactory = new BrowserSocketFactory(null);
|
||||
|
||||
getConnection(): IRemoteAgentConnection | null { return null; }
|
||||
async getEnvironment(bail?: boolean): Promise<IRemoteAgentEnvironment | null> { return null; }
|
||||
async getDiagnosticInfo(options: IDiagnosticInfoOptions): Promise<IDiagnosticInfo | undefined> { return undefined; }
|
||||
async disableTelemetry(): Promise<void> { }
|
||||
async logTelemetry(eventName: string, data?: ITelemetryData): Promise<void> { }
|
||||
async flushTelemetry(): Promise<void> { }
|
||||
async getRawEnvironment(): Promise<IRemoteAgentEnvironment | null> { return null; }
|
||||
async scanExtensions(skipExtensions?: ExtensionIdentifier[]): Promise<IExtensionDescription[]> { return []; }
|
||||
async scanSingleExtension(extensionLocation: URI, isBuiltin: boolean): Promise<IExtensionDescription | null> { return null; }
|
||||
async whenExtensionsReady(): Promise<void> { }
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
//#region Backup File
|
||||
|
||||
@@ -558,13 +535,16 @@ class SimpleTunnelService implements ITunnelService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
tunnels: Promise<readonly RemoteTunnel[]> = Promise.resolve([]);
|
||||
|
||||
canElevate: boolean = false;
|
||||
canMakePublic = false;
|
||||
onTunnelOpened = Event.None;
|
||||
onTunnelClosed = Event.None;
|
||||
|
||||
canTunnel(uri: URI): boolean { return false; }
|
||||
openTunnel(addressProvider: IAddressProvider | undefined, remoteHost: string | undefined, remotePort: number, localPort?: number): Promise<RemoteTunnel> | undefined { return undefined; }
|
||||
async changeTunnelPrivacy(remoteHost: string, remotePort: number, isPublic: boolean): Promise<RemoteTunnel | undefined> { return undefined; }
|
||||
async closeTunnel(remoteHost: string, remotePort: number): Promise<void> { }
|
||||
setTunnelProvider(provider: ITunnelProvider | undefined): IDisposable { return Disposable.None; }
|
||||
setTunnelProvider(provider: ITunnelProvider | undefined, features: TunnelProviderFeatures): IDisposable { return Disposable.None; }
|
||||
}
|
||||
|
||||
registerSingleton(ITunnelService, SimpleTunnelService);
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { localize } from 'vs/nls';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { equals } from 'vs/base/common/objects';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { IAction, Separator } from 'vs/base/common/actions';
|
||||
import { EventType, EventHelper, addDisposableListener, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
|
||||
import { Separator } from 'vs/base/common/actions';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { EditorResourceAccessor, IUntitledTextResourceEditorInput, SideBySideEditor, pathsToEditors } from 'vs/workbench/common/editor';
|
||||
import { IEditorService, IResourceEditorInputType } from 'vs/workbench/services/editor/common/editorService';
|
||||
@@ -22,13 +22,12 @@ import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/c
|
||||
import { IResourceEditorInput } from 'vs/platform/editor/common/editor';
|
||||
import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
|
||||
import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
|
||||
import { IMenuService, MenuId, IMenu, MenuItemAction, ICommandAction, SubmenuItemAction, MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IMenuService, MenuId, IMenu, MenuItemAction, ICommandAction, MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { LifecyclePhase, ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
import { IWorkspaceFolderCreationData, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IIntegrityService } from 'vs/workbench/services/integrity/common/integrity';
|
||||
import { isWindows, isMacintosh } from 'vs/base/common/platform';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
@@ -39,15 +38,8 @@ import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessi
|
||||
import { WorkbenchState, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { coalesce } from 'vs/base/common/arrays';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { MenubarControl } from '../browser/parts/titlebar/menubarControl';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { IUpdateService } from 'vs/platform/update/common/update';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { IPreferencesService } from '../services/preferences/common/preferences';
|
||||
import { IMenubarData, IMenubarMenu, IMenubarKeybinding, IMenubarMenuItemSubmenu, IMenubarMenuItemAction, MenubarMenuItem } from 'vs/platform/menubar/common/menubar';
|
||||
import { IMenubarService } from 'vs/platform/menubar/electron-sandbox/menubar';
|
||||
import { withNullAsUndefined, assertIsDefined } from 'vs/base/common/types';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
import { IOpenerService, OpenOptions } from 'vs/platform/opener/common/opener';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
||||
@@ -55,7 +47,6 @@ import { posix, dirname } from 'vs/base/common/path';
|
||||
import { getBaseLabel } from 'vs/base/common/labels';
|
||||
import { ITunnelService, extractLocalHostUriMetaDataForPortMapping } from 'vs/platform/remote/common/tunnel';
|
||||
import { IWorkbenchLayoutService, Parts, positionFromString, Position } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { IWorkingCopyService, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
import { AutoSaveMode, IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
@@ -64,6 +55,8 @@ import { IAddressProvider, IAddress } from 'vs/platform/remote/common/remoteAgen
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { AuthInfo } from 'vs/base/parts/sandbox/electron-sandbox/electronTypes';
|
||||
import { env } from 'vs/base/common/process';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
export class NativeWindow extends Disposable {
|
||||
|
||||
@@ -102,7 +95,6 @@ export class NativeWindow extends Disposable {
|
||||
@INativeWorkbenchEnvironmentService private readonly environmentService: INativeWorkbenchEnvironmentService,
|
||||
@IAccessibilityService private readonly accessibilityService: IAccessibilityService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IOpenerService private readonly openerService: IOpenerService,
|
||||
@INativeHostService private readonly nativeHostService: INativeHostService,
|
||||
@ITunnelService private readonly tunnelService: ITunnelService,
|
||||
@@ -112,7 +104,8 @@ export class NativeWindow extends Disposable {
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@IRemoteAuthorityResolverService private readonly remoteAuthorityResolverService: IRemoteAuthorityResolverService,
|
||||
@IDialogService private readonly dialogService: IDialogService,
|
||||
@IStorageService private readonly storageService: IStorageService
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@ILogService private readonly logService: ILogService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -122,13 +115,16 @@ export class NativeWindow extends Disposable {
|
||||
|
||||
private registerListeners(): void {
|
||||
|
||||
// Layout
|
||||
this._register(addDisposableListener(window, EventType.RESIZE, e => this.onWindowResize(e, true)));
|
||||
|
||||
// React to editor input changes
|
||||
this._register(this.editorService.onDidActiveEditorChange(() => this.updateTouchbarMenu()));
|
||||
|
||||
// prevent opening a real URL inside the shell
|
||||
[DOM.EventType.DRAG_OVER, DOM.EventType.DROP].forEach(event => {
|
||||
// prevent opening a real URL inside the window
|
||||
[EventType.DRAG_OVER, EventType.DROP].forEach(event => {
|
||||
window.document.body.addEventListener(event, (e: DragEvent) => {
|
||||
DOM.EventHelper.stop(e);
|
||||
EventHelper.stop(e);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -173,7 +169,7 @@ export class NativeWindow extends Disposable {
|
||||
// Error reporting from main
|
||||
ipcRenderer.on('vscode:reportError', (event: unknown, error: string) => {
|
||||
if (error) {
|
||||
errors.onUnexpectedError(JSON.parse(error));
|
||||
onUnexpectedError(JSON.parse(error));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -188,13 +184,13 @@ export class NativeWindow extends Disposable {
|
||||
|
||||
// Shell Environment Issue Notifications
|
||||
const choices: IPromptChoice[] = [{
|
||||
label: nls.localize('learnMode', "Learn More"),
|
||||
label: localize('learnMore', "Learn More"),
|
||||
run: () => this.openerService.open('https://go.microsoft.com/fwlink/?linkid=2149667')
|
||||
}];
|
||||
|
||||
ipcRenderer.on('vscode:showShellEnvSlowWarning', () => this.notificationService.prompt(
|
||||
Severity.Warning,
|
||||
nls.localize('shellEnvSlowWarning', "Resolving your shell environment is taking very long. Please review your shell configuration."),
|
||||
localize('shellEnvSlowWarning', "Resolving your shell environment is taking very long. Please review your shell configuration."),
|
||||
choices,
|
||||
{
|
||||
sticky: true,
|
||||
@@ -204,7 +200,7 @@ export class NativeWindow extends Disposable {
|
||||
|
||||
ipcRenderer.on('vscode:showShellEnvTimeoutError', () => this.notificationService.prompt(
|
||||
Severity.Error,
|
||||
nls.localize('shellEnvTimeoutError', "Unable to resolve your shell environment in a reasonable time. Please review your shell configuration."),
|
||||
localize('shellEnvTimeoutError', "Unable to resolve your shell environment in a reasonable time. Please review your shell configuration."),
|
||||
choices
|
||||
));
|
||||
|
||||
@@ -222,20 +218,20 @@ export class NativeWindow extends Disposable {
|
||||
// Proxy Login Dialog
|
||||
ipcRenderer.on('vscode:openProxyAuthenticationDialog', async (event: unknown, payload: { authInfo: AuthInfo, username?: string, password?: string, replyChannel: string }) => {
|
||||
const rememberCredentials = this.storageService.getBoolean(NativeWindow.REMEMBER_PROXY_CREDENTIALS_KEY, StorageScope.GLOBAL);
|
||||
const result = await this.dialogService.input(Severity.Warning, nls.localize('proxyAuthRequired', "Proxy Authentication Required"),
|
||||
const result = await this.dialogService.input(Severity.Warning, localize('proxyAuthRequired', "Proxy Authentication Required"),
|
||||
[
|
||||
nls.localize({ key: 'loginButton', comment: ['&& denotes a mnemonic'] }, "&&Log In"),
|
||||
nls.localize({ key: 'cancelButton', comment: ['&& denotes a mnemonic'] }, "&&Cancel")
|
||||
localize({ key: 'loginButton', comment: ['&& denotes a mnemonic'] }, "&&Log In"),
|
||||
localize({ key: 'cancelButton', comment: ['&& denotes a mnemonic'] }, "&&Cancel")
|
||||
],
|
||||
[
|
||||
{ placeholder: nls.localize('username', "Username"), value: payload.username },
|
||||
{ placeholder: nls.localize('password', "Password"), type: 'password', value: payload.password }
|
||||
{ placeholder: localize('username', "Username"), value: payload.username },
|
||||
{ placeholder: localize('password', "Password"), type: 'password', value: payload.password }
|
||||
],
|
||||
{
|
||||
cancelId: 1,
|
||||
detail: nls.localize('proxyDetail', "The proxy {0} requires a username and password.", `${payload.authInfo.host}:${payload.authInfo.port}`),
|
||||
detail: localize('proxyDetail', "The proxy {0} requires a username and password.", `${payload.authInfo.host}:${payload.authInfo.port}`),
|
||||
checkbox: {
|
||||
label: nls.localize('rememberCredentials', "Remember my credentials"),
|
||||
label: localize('rememberCredentials', "Remember my credentials"),
|
||||
checked: rememberCredentials
|
||||
}
|
||||
});
|
||||
@@ -303,8 +299,8 @@ export class NativeWindow extends Disposable {
|
||||
if (isMacintosh && getTitleBarStyle(this.configurationService) === 'custom') {
|
||||
const titlePart = assertIsDefined(this.layoutService.getContainer(Parts.TITLEBAR_PART));
|
||||
|
||||
this._register(DOM.addDisposableListener(titlePart, DOM.EventType.DBLCLICK, e => {
|
||||
DOM.EventHelper.stop(e);
|
||||
this._register(addDisposableListener(titlePart, EventType.DBLCLICK, e => {
|
||||
EventHelper.stop(e);
|
||||
|
||||
this.nativeHostService.handleTitleDoubleClick();
|
||||
}));
|
||||
@@ -331,12 +327,28 @@ export class NativeWindow extends Disposable {
|
||||
this.onDidChangeMaximized(this.environmentService.configuration.maximized ?? false);
|
||||
|
||||
// Detect panel position to determine minimum width
|
||||
this._register(this.layoutService.onPanelPositionChange(pos => {
|
||||
this.onDidPanelPositionChange(positionFromString(pos));
|
||||
}));
|
||||
this._register(this.layoutService.onPanelPositionChange(pos => this.onDidPanelPositionChange(positionFromString(pos))));
|
||||
this.onDidPanelPositionChange(this.layoutService.getPanelPosition());
|
||||
}
|
||||
|
||||
private onWindowResize(e: UIEvent, retry: boolean): void {
|
||||
if (e.target === window) {
|
||||
if (window.document && window.document.body && window.document.body.clientWidth === 0) {
|
||||
// TODO@bpasero this is an electron issue on macOS when simple fullscreen is enabled
|
||||
// where for some reason the window clientWidth is reported as 0 when switching
|
||||
// between simple fullscreen and normal screen. In that case we schedule the layout
|
||||
// call at the next animation frame once, in the hope that the dimensions are
|
||||
// proper then.
|
||||
if (retry) {
|
||||
scheduleAtNextAnimationFrame(() => this.onWindowResize(e, false));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.layoutService.layout();
|
||||
}
|
||||
}
|
||||
|
||||
private updateDocumentEdited(isDirty = this.workingCopyService.hasDirty): void {
|
||||
if ((!this.isDocumentedEdited && isDirty) || (this.isDocumentedEdited && !isDirty)) {
|
||||
this.isDocumentedEdited = isDirty;
|
||||
@@ -350,18 +362,19 @@ export class NativeWindow extends Disposable {
|
||||
}
|
||||
|
||||
private getWindowMinimumWidth(panelPosition: Position = this.layoutService.getPanelPosition()): number {
|
||||
|
||||
// if panel is on the side, then return the larger minwidth
|
||||
const panelOnSide = panelPosition === Position.LEFT || panelPosition === Position.RIGHT;
|
||||
if (panelOnSide) {
|
||||
return WindowMinimumSize.WIDTH_WITH_VERTICAL_PANEL;
|
||||
}
|
||||
else {
|
||||
return WindowMinimumSize.WIDTH;
|
||||
}
|
||||
|
||||
return WindowMinimumSize.WIDTH;
|
||||
}
|
||||
|
||||
private onDidPanelPositionChange(pos: Position): void {
|
||||
const minWidth = this.getWindowMinimumWidth(pos);
|
||||
|
||||
this.nativeHostService.setMinimumSize(minWidth, undefined);
|
||||
}
|
||||
|
||||
@@ -447,11 +460,6 @@ export class NativeWindow extends Disposable {
|
||||
|
||||
private create(): void {
|
||||
|
||||
// Native menu controller
|
||||
if (isMacintosh || getTitleBarStyle(this.configurationService) === 'native') {
|
||||
this._register(this.instantiationService.createInstance(NativeMenubarControl));
|
||||
}
|
||||
|
||||
// Handle open calls
|
||||
this.setupOpenHandlers();
|
||||
|
||||
@@ -470,12 +478,23 @@ export class NativeWindow extends Disposable {
|
||||
|
||||
// Show warning message (unix only)
|
||||
if (isAdmin && !isWindows) {
|
||||
this.notificationService.warn(nls.localize('runningAsRoot', "It is not recommended to run {0} as root user.", this.productService.nameShort));
|
||||
this.notificationService.warn(localize('runningAsRoot', "It is not recommended to run {0} as root user.", this.productService.nameShort));
|
||||
}
|
||||
});
|
||||
|
||||
// Touchbar menu (if enabled)
|
||||
this.updateTouchbarMenu();
|
||||
|
||||
// Check for cyclic dependencies
|
||||
if (require.hasDependencyCycle()) {
|
||||
if (env['CI'] || env['BUILD_ARTIFACTSTAGINGDIRECTORY']) {
|
||||
this.logService.error('Error: There is a dependency cycle in the AMD modules that needs to be resolved!');
|
||||
this.nativeHostService.exit(37); // running on a build machine, just exit without showing a dialog
|
||||
} else {
|
||||
this.dialogService.show(Severity.Error, localize('loaderCycle', "There is a dependency cycle in the AMD modules that needs to be resolved!"), [localize('ok', "OK")]);
|
||||
this.nativeHostService.openDevTools();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private setupOpenHandlers(): void {
|
||||
@@ -486,7 +505,7 @@ export class NativeWindow extends Disposable {
|
||||
};
|
||||
|
||||
// Handle external open() calls
|
||||
this.openerService.setExternalOpener({
|
||||
this.openerService.setDefaultExternalOpener({
|
||||
openExternal: async (href: string) => {
|
||||
const success = await this.nativeHostService.openExternal(href);
|
||||
if (!success) {
|
||||
@@ -667,199 +686,3 @@ export class NativeWindow extends Disposable {
|
||||
return this.editorService.openEditors(resources);
|
||||
}
|
||||
}
|
||||
|
||||
class NativeMenubarControl extends MenubarControl {
|
||||
constructor(
|
||||
@IMenuService menuService: IMenuService,
|
||||
@IWorkspacesService workspacesService: IWorkspacesService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IKeybindingService keybindingService: IKeybindingService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@ILabelService labelService: ILabelService,
|
||||
@IUpdateService updateService: IUpdateService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@INotificationService notificationService: INotificationService,
|
||||
@IPreferencesService preferencesService: IPreferencesService,
|
||||
@INativeWorkbenchEnvironmentService protected readonly environmentService: INativeWorkbenchEnvironmentService,
|
||||
@IAccessibilityService accessibilityService: IAccessibilityService,
|
||||
@IMenubarService private readonly menubarService: IMenubarService,
|
||||
@IHostService hostService: IHostService,
|
||||
@INativeHostService private readonly nativeHostService: INativeHostService
|
||||
) {
|
||||
super(
|
||||
menuService,
|
||||
workspacesService,
|
||||
contextKeyService,
|
||||
keybindingService,
|
||||
configurationService,
|
||||
labelService,
|
||||
updateService,
|
||||
storageService,
|
||||
notificationService,
|
||||
preferencesService,
|
||||
environmentService,
|
||||
accessibilityService,
|
||||
hostService
|
||||
);
|
||||
|
||||
if (isMacintosh) {
|
||||
this.menus['Preferences'] = this._register(this.menuService.createMenu(MenuId.MenubarPreferencesMenu, this.contextKeyService));
|
||||
this.topLevelTitles['Preferences'] = nls.localize('mPreferences', "Preferences");
|
||||
}
|
||||
|
||||
for (const topLevelMenuName of Object.keys(this.topLevelTitles)) {
|
||||
const menu = this.menus[topLevelMenuName];
|
||||
if (menu) {
|
||||
this._register(menu.onDidChange(() => this.updateMenubar()));
|
||||
}
|
||||
}
|
||||
|
||||
(async () => {
|
||||
this.recentlyOpened = await this.workspacesService.getRecentlyOpened();
|
||||
|
||||
this.doUpdateMenubar();
|
||||
})();
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
protected doUpdateMenubar(): void {
|
||||
// Since the native menubar is shared between windows (main process)
|
||||
// only allow the focused window to update the menubar
|
||||
if (!this.hostService.hasFocus) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send menus to main process to be rendered by Electron
|
||||
const menubarData = { menus: {}, keybindings: {} };
|
||||
if (this.getMenubarMenus(menubarData)) {
|
||||
this.menubarService.updateMenubar(this.nativeHostService.windowId, menubarData);
|
||||
}
|
||||
}
|
||||
|
||||
private getMenubarMenus(menubarData: IMenubarData): boolean {
|
||||
if (!menubarData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
menubarData.keybindings = this.getAdditionalKeybindings();
|
||||
for (const topLevelMenuName of Object.keys(this.topLevelTitles)) {
|
||||
const menu = this.menus[topLevelMenuName];
|
||||
if (menu) {
|
||||
const menubarMenu: IMenubarMenu = { items: [] };
|
||||
this.populateMenuItems(menu, menubarMenu, menubarData.keybindings);
|
||||
if (menubarMenu.items.length === 0) {
|
||||
return false; // Menus are incomplete
|
||||
}
|
||||
menubarData.menus[topLevelMenuName] = menubarMenu;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private populateMenuItems(menu: IMenu, menuToPopulate: IMenubarMenu, keybindings: { [id: string]: IMenubarKeybinding | undefined }) {
|
||||
let groups = menu.getActions();
|
||||
for (let group of groups) {
|
||||
const [, actions] = group;
|
||||
|
||||
actions.forEach(menuItem => {
|
||||
|
||||
if (menuItem instanceof SubmenuItemAction) {
|
||||
const submenu = { items: [] };
|
||||
|
||||
if (!this.menus[menuItem.item.submenu.id]) {
|
||||
const menu = this.menus[menuItem.item.submenu.id] = this.menuService.createMenu(menuItem.item.submenu, this.contextKeyService);
|
||||
this._register(menu.onDidChange(() => this.updateMenubar()));
|
||||
}
|
||||
|
||||
const menuToDispose = this.menuService.createMenu(menuItem.item.submenu, this.contextKeyService);
|
||||
this.populateMenuItems(menuToDispose, submenu, keybindings);
|
||||
|
||||
let menubarSubmenuItem: IMenubarMenuItemSubmenu = {
|
||||
id: menuItem.id,
|
||||
label: menuItem.label,
|
||||
submenu: submenu
|
||||
};
|
||||
|
||||
menuToPopulate.items.push(menubarSubmenuItem);
|
||||
menuToDispose.dispose();
|
||||
} else {
|
||||
if (menuItem.id === 'workbench.action.openRecent') {
|
||||
const actions = this.getOpenRecentActions().map(this.transformOpenRecentAction);
|
||||
menuToPopulate.items.push(...actions);
|
||||
}
|
||||
|
||||
let menubarMenuItem: IMenubarMenuItemAction = {
|
||||
id: menuItem.id,
|
||||
label: menuItem.label
|
||||
};
|
||||
|
||||
if (menuItem.checked) {
|
||||
menubarMenuItem.checked = true;
|
||||
}
|
||||
|
||||
if (!menuItem.enabled) {
|
||||
menubarMenuItem.enabled = false;
|
||||
}
|
||||
|
||||
menubarMenuItem.label = this.calculateActionLabel(menubarMenuItem);
|
||||
keybindings[menuItem.id] = this.getMenubarKeybinding(menuItem.id);
|
||||
menuToPopulate.items.push(menubarMenuItem);
|
||||
}
|
||||
});
|
||||
|
||||
menuToPopulate.items.push({ id: 'vscode.menubar.separator' });
|
||||
}
|
||||
|
||||
if (menuToPopulate.items.length > 0) {
|
||||
menuToPopulate.items.pop();
|
||||
}
|
||||
}
|
||||
|
||||
private transformOpenRecentAction(action: Separator | (IAction & { uri: URI })): MenubarMenuItem {
|
||||
if (action instanceof Separator) {
|
||||
return { id: 'vscode.menubar.separator' };
|
||||
}
|
||||
|
||||
return {
|
||||
id: action.id,
|
||||
uri: action.uri,
|
||||
enabled: action.enabled,
|
||||
label: action.label
|
||||
};
|
||||
}
|
||||
|
||||
private getAdditionalKeybindings(): { [id: string]: IMenubarKeybinding } {
|
||||
const keybindings: { [id: string]: IMenubarKeybinding } = {};
|
||||
if (isMacintosh) {
|
||||
const keybinding = this.getMenubarKeybinding('workbench.action.quit');
|
||||
if (keybinding) {
|
||||
keybindings['workbench.action.quit'] = keybinding;
|
||||
}
|
||||
}
|
||||
|
||||
return keybindings;
|
||||
}
|
||||
|
||||
private getMenubarKeybinding(id: string): IMenubarKeybinding | undefined {
|
||||
const binding = this.keybindingService.lookupKeybinding(id);
|
||||
if (!binding) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// first try to resolve a native accelerator
|
||||
const electronAccelerator = binding.getElectronAccelerator();
|
||||
if (electronAccelerator) {
|
||||
return { label: electronAccelerator, userSettingsLabel: withNullAsUndefined(binding.getUserSettingsLabel()) };
|
||||
}
|
||||
|
||||
// we need this fallback to support keybindings that cannot show in electron menus (e.g. chords)
|
||||
const acceleratorLabel = binding.getLabel();
|
||||
if (acceleratorLabel) {
|
||||
return { label: acceleratorLabel, isNative: false, userSettingsLabel: withNullAsUndefined(binding.getUserSettingsLabel()) };
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user