Path: blob/main/src/vs/workbench/services/keybinding/electron-browser/nativeKeyboardLayout.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 { Disposable } from '../../../../base/common/lifecycle.js';6import { IKeyboardLayoutInfo, IKeyboardLayoutService, IKeyboardMapping, ILinuxKeyboardLayoutInfo, IMacKeyboardLayoutInfo, IMacLinuxKeyboardMapping, IWindowsKeyboardLayoutInfo, IWindowsKeyboardMapping } from '../../../../platform/keyboardLayout/common/keyboardLayout.js';7import { Emitter } from '../../../../base/common/event.js';8import { OperatingSystem, OS } from '../../../../base/common/platform.js';9import { CachedKeyboardMapper, IKeyboardMapper } from '../../../../platform/keyboardLayout/common/keyboardMapper.js';10import { WindowsKeyboardMapper } from '../common/windowsKeyboardMapper.js';11import { FallbackKeyboardMapper } from '../common/fallbackKeyboardMapper.js';12import { MacLinuxKeyboardMapper } from '../common/macLinuxKeyboardMapper.js';13import { DispatchConfig, readKeyboardConfig } from '../../../../platform/keyboardLayout/common/keyboardConfig.js';14import { IKeyboardEvent } from '../../../../platform/keybinding/common/keybinding.js';15import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';16import { INativeKeyboardLayoutService } from './nativeKeyboardLayoutService.js';17import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';1819export class KeyboardLayoutService extends Disposable implements IKeyboardLayoutService {2021declare readonly _serviceBrand: undefined;2223private readonly _onDidChangeKeyboardLayout = this._register(new Emitter<void>());24readonly onDidChangeKeyboardLayout = this._onDidChangeKeyboardLayout.event;2526private _keyboardMapper: IKeyboardMapper | null;2728constructor(29@INativeKeyboardLayoutService private readonly _nativeKeyboardLayoutService: INativeKeyboardLayoutService,30@IConfigurationService private readonly _configurationService: IConfigurationService31) {32super();33this._keyboardMapper = null;3435this._register(this._nativeKeyboardLayoutService.onDidChangeKeyboardLayout(async () => {36this._keyboardMapper = null;37this._onDidChangeKeyboardLayout.fire();38}));3940this._register(_configurationService.onDidChangeConfiguration(async (e) => {41if (e.affectsConfiguration('keyboard')) {42this._keyboardMapper = null;43this._onDidChangeKeyboardLayout.fire();44}45}));46}4748public getRawKeyboardMapping(): IKeyboardMapping | null {49return this._nativeKeyboardLayoutService.getRawKeyboardMapping();50}5152public getCurrentKeyboardLayout(): IKeyboardLayoutInfo | null {53return this._nativeKeyboardLayoutService.getCurrentKeyboardLayout();54}5556public getAllKeyboardLayouts(): IKeyboardLayoutInfo[] {57return [];58}5960public getKeyboardMapper(): IKeyboardMapper {61const config = readKeyboardConfig(this._configurationService);62if (config.dispatch === DispatchConfig.KeyCode) {63// Forcefully set to use keyCode64return new FallbackKeyboardMapper(config.mapAltGrToCtrlAlt, OS);65}66if (!this._keyboardMapper) {67this._keyboardMapper = new CachedKeyboardMapper(createKeyboardMapper(this.getCurrentKeyboardLayout(), this.getRawKeyboardMapping(), config.mapAltGrToCtrlAlt));68}69return this._keyboardMapper;70}7172public validateCurrentKeyboardMapping(keyboardEvent: IKeyboardEvent): void {73return;74}75}7677function createKeyboardMapper(layoutInfo: IKeyboardLayoutInfo | null, rawMapping: IKeyboardMapping | null, mapAltGrToCtrlAlt: boolean): IKeyboardMapper {78const _isUSStandard = isUSStandard(layoutInfo);79if (OS === OperatingSystem.Windows) {80return new WindowsKeyboardMapper(_isUSStandard, <IWindowsKeyboardMapping>rawMapping, mapAltGrToCtrlAlt);81}8283if (!rawMapping || Object.keys(rawMapping).length === 0) {84// Looks like reading the mappings failed (most likely Mac + Japanese/Chinese keyboard layouts)85return new FallbackKeyboardMapper(mapAltGrToCtrlAlt, OS);86}8788if (OS === OperatingSystem.Macintosh) {89const kbInfo = <IMacKeyboardLayoutInfo>layoutInfo;90if (kbInfo.id === 'com.apple.keylayout.DVORAK-QWERTYCMD') {91// Use keyCode based dispatching for DVORAK - QWERTY ⌘92return new FallbackKeyboardMapper(mapAltGrToCtrlAlt, OS);93}94}9596return new MacLinuxKeyboardMapper(_isUSStandard, <IMacLinuxKeyboardMapping>rawMapping, mapAltGrToCtrlAlt, OS);97}9899function isUSStandard(_kbInfo: IKeyboardLayoutInfo | null): boolean {100if (!_kbInfo) {101return false;102}103104if (OS === OperatingSystem.Linux) {105const kbInfo = <ILinuxKeyboardLayoutInfo>_kbInfo;106const layouts = kbInfo.layout.split(/,/g);107return (layouts[kbInfo.group] === 'us');108}109110if (OS === OperatingSystem.Macintosh) {111const kbInfo = <IMacKeyboardLayoutInfo>_kbInfo;112return (kbInfo.id === 'com.apple.keylayout.US');113}114115if (OS === OperatingSystem.Windows) {116const kbInfo = <IWindowsKeyboardLayoutInfo>_kbInfo;117return (kbInfo.name === '00000409');118}119120return false;121}122123registerSingleton(IKeyboardLayoutService, KeyboardLayoutService, InstantiationType.Delayed);124125126