Path: blob/main/src/vs/workbench/contrib/preferences/browser/keyboardLayoutPicker.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import * as nls from '../../../../nls.js';6import { StatusbarAlignment, IStatusbarService, IStatusbarEntryAccessor } from '../../../services/statusbar/browser/statusbar.js';7import { Disposable, MutableDisposable } from '../../../../base/common/lifecycle.js';8import { parseKeyboardLayoutDescription, areKeyboardLayoutsEqual, getKeyboardLayoutId, IKeyboardLayoutService, IKeyboardLayoutInfo } from '../../../../platform/keyboardLayout/common/keyboardLayout.js';9import { IWorkbenchContribution, WorkbenchPhase, registerWorkbenchContribution2 } from '../../../common/contributions.js';10import { KEYBOARD_LAYOUT_OPEN_PICKER } from '../common/preferences.js';11import { isMacintosh, isWindows } from '../../../../base/common/platform.js';12import { QuickPickInput, IQuickInputService, IQuickPickItem } from '../../../../platform/quickinput/common/quickInput.js';13import { Action2, registerAction2 } from '../../../../platform/actions/common/actions.js';14import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';15import { IEnvironmentService } from '../../../../platform/environment/common/environment.js';16import { IFileService } from '../../../../platform/files/common/files.js';17import { IEditorService } from '../../../services/editor/common/editorService.js';18import { VSBuffer } from '../../../../base/common/buffer.js';19import { IEditorPane } from '../../../common/editor.js';20import { ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';2122export class KeyboardLayoutPickerContribution extends Disposable implements IWorkbenchContribution {2324static readonly ID = 'workbench.contrib.keyboardLayoutPicker';2526private readonly pickerElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());2728constructor(29@IKeyboardLayoutService private readonly keyboardLayoutService: IKeyboardLayoutService,30@IStatusbarService private readonly statusbarService: IStatusbarService,31) {32super();3334const name = nls.localize('status.workbench.keyboardLayout', "Keyboard Layout");3536const layout = this.keyboardLayoutService.getCurrentKeyboardLayout();37if (layout) {38const layoutInfo = parseKeyboardLayoutDescription(layout);39const text = nls.localize('keyboardLayout', "Layout: {0}", layoutInfo.label);4041this.pickerElement.value = this.statusbarService.addEntry(42{43name,44text,45ariaLabel: text,46command: KEYBOARD_LAYOUT_OPEN_PICKER47},48'status.workbench.keyboardLayout',49StatusbarAlignment.RIGHT50);51}5253this._register(this.keyboardLayoutService.onDidChangeKeyboardLayout(() => {54const layout = this.keyboardLayoutService.getCurrentKeyboardLayout();55const layoutInfo = parseKeyboardLayoutDescription(layout);5657if (this.pickerElement.value) {58const text = nls.localize('keyboardLayout', "Layout: {0}", layoutInfo.label);59this.pickerElement.value.update({60name,61text,62ariaLabel: text,63command: KEYBOARD_LAYOUT_OPEN_PICKER64});65} else {66const text = nls.localize('keyboardLayout', "Layout: {0}", layoutInfo.label);67this.pickerElement.value = this.statusbarService.addEntry(68{69name,70text,71ariaLabel: text,72command: KEYBOARD_LAYOUT_OPEN_PICKER73},74'status.workbench.keyboardLayout',75StatusbarAlignment.RIGHT76);77}78}));79}80}8182registerWorkbenchContribution2(KeyboardLayoutPickerContribution.ID, KeyboardLayoutPickerContribution, WorkbenchPhase.BlockStartup);8384interface LayoutQuickPickItem extends IQuickPickItem {85layout: IKeyboardLayoutInfo;86}8788interface IUnknownLayout {89text?: string;90lang?: string;91layout?: string;92}9394const DEFAULT_CONTENT: string = [95`// ${nls.localize('displayLanguage', 'Defines the keyboard layout used in VS Code in the browser environment.')}`,96`// ${nls.localize('doc', 'Open VS Code and run "Developer: Inspect Key Mappings (JSON)" from Command Palette.')}`,97``,98`// Once you have the keyboard layout info, please paste it below.`,99'\n'100].join('\n');101102registerAction2(class extends Action2 {103constructor() {104super({105id: KEYBOARD_LAYOUT_OPEN_PICKER,106title: nls.localize2('keyboard.chooseLayout', "Change Keyboard Layout"),107f1: true108});109}110111async run(accessor: ServicesAccessor): Promise<void> {112const keyboardLayoutService = accessor.get(IKeyboardLayoutService);113const quickInputService = accessor.get(IQuickInputService);114const configurationService = accessor.get(IConfigurationService);115const environmentService = accessor.get(IEnvironmentService);116const editorService = accessor.get(IEditorService);117const fileService = accessor.get(IFileService);118119const layouts = keyboardLayoutService.getAllKeyboardLayouts();120const currentLayout = keyboardLayoutService.getCurrentKeyboardLayout();121const layoutConfig = configurationService.getValue('keyboard.layout');122const isAutoDetect = layoutConfig === 'autodetect';123124const picks: QuickPickInput[] = layouts.map(layout => {125const picked = !isAutoDetect && areKeyboardLayoutsEqual(currentLayout, layout);126const layoutInfo = parseKeyboardLayoutDescription(layout);127return {128layout: layout,129label: [layoutInfo.label, (layout && layout.isUserKeyboardLayout) ? '(User configured layout)' : ''].join(' '),130id: (layout as IUnknownLayout).text || (layout as IUnknownLayout).lang || (layout as IUnknownLayout).layout,131description: layoutInfo.description + (picked ? ' (Current layout)' : ''),132picked: !isAutoDetect && areKeyboardLayoutsEqual(currentLayout, layout)133};134}).sort((a: IQuickPickItem, b: IQuickPickItem) => {135return a.label < b.label ? -1 : (a.label > b.label ? 1 : 0);136});137138if (picks.length > 0) {139const platform = isMacintosh ? 'Mac' : isWindows ? 'Win' : 'Linux';140picks.unshift({ type: 'separator', label: nls.localize('layoutPicks', "Keyboard Layouts ({0})", platform) });141}142143const configureKeyboardLayout: IQuickPickItem = { label: nls.localize('configureKeyboardLayout', "Configure Keyboard Layout") };144145picks.unshift(configureKeyboardLayout);146147// Offer to "Auto Detect"148const autoDetectMode: IQuickPickItem = {149label: nls.localize('autoDetect', "Auto Detect"),150description: isAutoDetect ? `Current: ${parseKeyboardLayoutDescription(currentLayout).label}` : undefined,151picked: isAutoDetect ? true : undefined152};153154picks.unshift(autoDetectMode);155156const pick = await quickInputService.pick(picks, { placeHolder: nls.localize('pickKeyboardLayout', "Select Keyboard Layout"), matchOnDescription: true });157if (!pick) {158return;159}160161if (pick === autoDetectMode) {162// set keymap service to auto mode163configurationService.updateValue('keyboard.layout', 'autodetect');164return;165}166167if (pick === configureKeyboardLayout) {168const file = environmentService.keyboardLayoutResource;169170await fileService.stat(file).then(undefined, () => {171return fileService.createFile(file, VSBuffer.fromString(DEFAULT_CONTENT));172}).then((stat): Promise<IEditorPane | undefined> | undefined => {173if (!stat) {174return undefined;175}176return editorService.openEditor({177resource: stat.resource,178languageId: 'jsonc',179options: { pinned: true }180});181}, (error) => {182throw new Error(nls.localize('fail.createSettings', "Unable to create '{0}' ({1}).", file.toString(), error));183});184185return Promise.resolve();186}187188configurationService.updateValue('keyboard.layout', getKeyboardLayoutId((<LayoutQuickPickItem>pick).layout));189}190});191192193