Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/services/keybinding/electron-browser/nativeKeyboardLayout.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Disposable } from '../../../../base/common/lifecycle.js';
7
import { IKeyboardLayoutInfo, IKeyboardLayoutService, IKeyboardMapping, ILinuxKeyboardLayoutInfo, IMacKeyboardLayoutInfo, IMacLinuxKeyboardMapping, IWindowsKeyboardLayoutInfo, IWindowsKeyboardMapping } from '../../../../platform/keyboardLayout/common/keyboardLayout.js';
8
import { Emitter } from '../../../../base/common/event.js';
9
import { OperatingSystem, OS } from '../../../../base/common/platform.js';
10
import { CachedKeyboardMapper, IKeyboardMapper } from '../../../../platform/keyboardLayout/common/keyboardMapper.js';
11
import { WindowsKeyboardMapper } from '../common/windowsKeyboardMapper.js';
12
import { FallbackKeyboardMapper } from '../common/fallbackKeyboardMapper.js';
13
import { MacLinuxKeyboardMapper } from '../common/macLinuxKeyboardMapper.js';
14
import { DispatchConfig, readKeyboardConfig } from '../../../../platform/keyboardLayout/common/keyboardConfig.js';
15
import { IKeyboardEvent } from '../../../../platform/keybinding/common/keybinding.js';
16
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
17
import { INativeKeyboardLayoutService } from './nativeKeyboardLayoutService.js';
18
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
19
20
export class KeyboardLayoutService extends Disposable implements IKeyboardLayoutService {
21
22
declare readonly _serviceBrand: undefined;
23
24
private readonly _onDidChangeKeyboardLayout = this._register(new Emitter<void>());
25
readonly onDidChangeKeyboardLayout = this._onDidChangeKeyboardLayout.event;
26
27
private _keyboardMapper: IKeyboardMapper | null;
28
29
constructor(
30
@INativeKeyboardLayoutService private readonly _nativeKeyboardLayoutService: INativeKeyboardLayoutService,
31
@IConfigurationService private readonly _configurationService: IConfigurationService
32
) {
33
super();
34
this._keyboardMapper = null;
35
36
this._register(this._nativeKeyboardLayoutService.onDidChangeKeyboardLayout(async () => {
37
this._keyboardMapper = null;
38
this._onDidChangeKeyboardLayout.fire();
39
}));
40
41
this._register(_configurationService.onDidChangeConfiguration(async (e) => {
42
if (e.affectsConfiguration('keyboard')) {
43
this._keyboardMapper = null;
44
this._onDidChangeKeyboardLayout.fire();
45
}
46
}));
47
}
48
49
public getRawKeyboardMapping(): IKeyboardMapping | null {
50
return this._nativeKeyboardLayoutService.getRawKeyboardMapping();
51
}
52
53
public getCurrentKeyboardLayout(): IKeyboardLayoutInfo | null {
54
return this._nativeKeyboardLayoutService.getCurrentKeyboardLayout();
55
}
56
57
public getAllKeyboardLayouts(): IKeyboardLayoutInfo[] {
58
return [];
59
}
60
61
public getKeyboardMapper(): IKeyboardMapper {
62
const config = readKeyboardConfig(this._configurationService);
63
if (config.dispatch === DispatchConfig.KeyCode) {
64
// Forcefully set to use keyCode
65
return new FallbackKeyboardMapper(config.mapAltGrToCtrlAlt, OS);
66
}
67
if (!this._keyboardMapper) {
68
this._keyboardMapper = new CachedKeyboardMapper(createKeyboardMapper(this.getCurrentKeyboardLayout(), this.getRawKeyboardMapping(), config.mapAltGrToCtrlAlt));
69
}
70
return this._keyboardMapper;
71
}
72
73
public validateCurrentKeyboardMapping(keyboardEvent: IKeyboardEvent): void {
74
return;
75
}
76
}
77
78
function createKeyboardMapper(layoutInfo: IKeyboardLayoutInfo | null, rawMapping: IKeyboardMapping | null, mapAltGrToCtrlAlt: boolean): IKeyboardMapper {
79
const _isUSStandard = isUSStandard(layoutInfo);
80
if (OS === OperatingSystem.Windows) {
81
return new WindowsKeyboardMapper(_isUSStandard, <IWindowsKeyboardMapping>rawMapping, mapAltGrToCtrlAlt);
82
}
83
84
if (!rawMapping || Object.keys(rawMapping).length === 0) {
85
// Looks like reading the mappings failed (most likely Mac + Japanese/Chinese keyboard layouts)
86
return new FallbackKeyboardMapper(mapAltGrToCtrlAlt, OS);
87
}
88
89
if (OS === OperatingSystem.Macintosh) {
90
const kbInfo = <IMacKeyboardLayoutInfo>layoutInfo;
91
if (kbInfo.id === 'com.apple.keylayout.DVORAK-QWERTYCMD') {
92
// Use keyCode based dispatching for DVORAK - QWERTY ⌘
93
return new FallbackKeyboardMapper(mapAltGrToCtrlAlt, OS);
94
}
95
}
96
97
return new MacLinuxKeyboardMapper(_isUSStandard, <IMacLinuxKeyboardMapping>rawMapping, mapAltGrToCtrlAlt, OS);
98
}
99
100
function isUSStandard(_kbInfo: IKeyboardLayoutInfo | null): boolean {
101
if (!_kbInfo) {
102
return false;
103
}
104
105
if (OS === OperatingSystem.Linux) {
106
const kbInfo = <ILinuxKeyboardLayoutInfo>_kbInfo;
107
const layouts = kbInfo.layout.split(/,/g);
108
return (layouts[kbInfo.group] === 'us');
109
}
110
111
if (OS === OperatingSystem.Macintosh) {
112
const kbInfo = <IMacKeyboardLayoutInfo>_kbInfo;
113
return (kbInfo.id === 'com.apple.keylayout.US');
114
}
115
116
if (OS === OperatingSystem.Windows) {
117
const kbInfo = <IWindowsKeyboardLayoutInfo>_kbInfo;
118
return (kbInfo.name === '00000409');
119
}
120
121
return false;
122
}
123
124
registerSingleton(IKeyboardLayoutService, KeyboardLayoutService, InstantiationType.Delayed);
125
126