Skip to content

Commit c9244de

Browse files
committed
Merge branch 'rebornix/keyboardlayouts'
2 parents 9d88369 + cc83415 commit c9244de

53 files changed

Lines changed: 7419 additions & 50 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/vs/workbench/services/keybinding/browser/browserKeymapService.ts

Lines changed: 0 additions & 48 deletions
This file was deleted.

src/vs/workbench/services/keybinding/browser/keybindingService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/commo
1818
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
1919
import { Extensions, IJSONContributionRegistry } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
2020
import { AbstractKeybindingService } from 'vs/platform/keybinding/common/abstractKeybindingService';
21-
import { IKeybindingEvent, IKeyboardEvent, IUserFriendlyKeybinding, KeybindingSource, IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
21+
import { IKeyboardEvent, IUserFriendlyKeybinding, KeybindingSource, IKeybindingService, IKeybindingEvent } from 'vs/platform/keybinding/common/keybinding';
2222
import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver';
2323
import { IKeybindingItem, IKeybindingRule2, KeybindingWeight, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
2424
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
@@ -313,6 +313,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
313313
}
314314

315315
public resolveKeyboardEvent(keyboardEvent: IKeyboardEvent): ResolvedKeybinding {
316+
this.keymapService.validateCurrentKeyboardMapping(keyboardEvent);
316317
return this._keyboardMapper.resolveKeyboardEvent(keyboardEvent);
317318
}
318319

Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
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 { IKeyboardLayoutInfo } from 'vs/workbench/services/keybinding/common/keymapService';
7+
import { isWindows } from 'vs/base/common/platform';
8+
9+
function deserializeMapping(serializedMapping: ISerializedMapping) {
10+
let mapping = serializedMapping;
11+
12+
let ret = {};
13+
for (let key in mapping) {
14+
let result: (string | number)[] = mapping[key];
15+
if (result.length) {
16+
let value = result[0];
17+
let withShift = result[1];
18+
let withAltGr = result[2];
19+
let withShiftAltGr = result[3];
20+
let mask = Number(result[4]);
21+
let vkey = result.length === 6 ? result[5] : undefined;
22+
ret[key] = {
23+
'value': value,
24+
'vkey': vkey,
25+
'withShift': withShift,
26+
'withAltGr': withAltGr,
27+
'withShiftAltGr': withShiftAltGr,
28+
'valueIsDeadKey': (mask & 1) > 0,
29+
'withShiftIsDeadKey': (mask & 2) > 0,
30+
'withAltGrIsDeadKey': (mask & 4) > 0,
31+
'withShiftAltGrIsDeadKey': (mask & 8) > 0
32+
};
33+
} else {
34+
ret[key] = {
35+
'value': '',
36+
'valueIsDeadKey': false,
37+
'withShift': '',
38+
'withShiftIsDeadKey': false,
39+
'withAltGr': '',
40+
'withAltGrIsDeadKey': false,
41+
'withShiftAltGr': '',
42+
'withShiftAltGrIsDeadKey': false
43+
};
44+
}
45+
}
46+
47+
return ret;
48+
}
49+
50+
interface IKeyboardMapping {
51+
[key: string]: {
52+
value: string,
53+
withShift: string;
54+
withAltGr: string;
55+
withShiftAltGr: string;
56+
valueIsDeadKey?: boolean;
57+
withShiftIsDeadKey?: boolean;
58+
withAltGrIsDeadKey?: boolean;
59+
withShiftAltGrIsDeadKey?: boolean;
60+
61+
};
62+
}
63+
64+
interface ISerializedMapping {
65+
[key: string]: (string | number)[];
66+
}
67+
68+
export class KeyboardLayoutInfo {
69+
value: IKeyboardMapping;
70+
71+
constructor(public layout: IKeyboardLayoutInfo, public secondaryLayouts: IKeyboardLayoutInfo[], keyboardMapping: ISerializedMapping) {
72+
this.value = deserializeMapping(keyboardMapping);
73+
}
74+
75+
fuzzyEqual(other: IKeyboardMapping): boolean {
76+
for (let key in other) {
77+
if (isWindows && (key === 'Backslash' || key === 'KeyQ')) {
78+
// keymap from Chromium is probably wrong.
79+
continue;
80+
}
81+
if (this.value[key] === undefined) {
82+
return false;
83+
}
84+
85+
let currentMapping = this.value[key];
86+
let otherMapping = other[key];
87+
88+
if (currentMapping.value !== otherMapping.value) {
89+
return false;
90+
}
91+
}
92+
93+
return true;
94+
}
95+
}
96+
97+
export const EN_US = new KeyboardLayoutInfo(
98+
{ id: 'com.apple.keylayout.US', lang: 'en' },
99+
[],
100+
{
101+
KeyA: ['a', 'A', 'å', 'Å', 0],
102+
KeyB: ['b', 'B', '∫', 'ı', 0],
103+
KeyC: ['c', 'C', 'ç', 'Ç', 0],
104+
KeyD: ['d', 'D', '∂', 'Î', 0],
105+
KeyE: ['e', 'E', '´', '´', 4],
106+
KeyF: ['f', 'F', 'ƒ', 'Ï', 0],
107+
KeyG: ['g', 'G', '©', '˝', 0],
108+
KeyH: ['h', 'H', '˙', 'Ó', 0],
109+
KeyI: ['i', 'I', 'ˆ', 'ˆ', 4],
110+
KeyJ: ['j', 'J', '∆', 'Ô', 0],
111+
KeyK: ['k', 'K', '˚', '', 0],
112+
KeyL: ['l', 'L', '¬', 'Ò', 0],
113+
KeyM: ['m', 'M', 'µ', 'Â', 0],
114+
KeyN: ['n', 'N', '˜', '˜', 4],
115+
KeyO: ['o', 'O', 'ø', 'Ø', 0],
116+
KeyP: ['p', 'P', 'π', '∏', 0],
117+
KeyQ: ['q', 'Q', 'œ', 'Œ', 0],
118+
KeyR: ['r', 'R', '®', '‰', 0],
119+
KeyS: ['s', 'S', 'ß', 'Í', 0],
120+
KeyT: ['t', 'T', '†', 'ˇ', 0],
121+
KeyU: ['u', 'U', '¨', '¨', 4],
122+
KeyV: ['v', 'V', '√', '◊', 0],
123+
KeyW: ['w', 'W', '∑', '„', 0],
124+
KeyX: ['x', 'X', '≈', '˛', 0],
125+
KeyY: ['y', 'Y', '¥', 'Á', 0],
126+
KeyZ: ['z', 'Z', 'Ω', '¸', 0],
127+
Digit1: ['1', '!', '¡', '⁄', 0],
128+
Digit2: ['2', '@', '™', '€', 0],
129+
Digit3: ['3', '#', '£', '‹', 0],
130+
Digit4: ['4', '$', '¢', '›', 0],
131+
Digit5: ['5', '%', '∞', 'fi', 0],
132+
Digit6: ['6', '^', '§', 'fl', 0],
133+
Digit7: ['7', '&', '¶', '‡', 0],
134+
Digit8: ['8', '*', '•', '°', 0],
135+
Digit9: ['9', '(', 'ª', '·', 0],
136+
Digit0: ['0', ')', 'º', '‚', 0],
137+
Enter: [],
138+
Escape: [],
139+
Backspace: [],
140+
Tab: [],
141+
Space: [' ', ' ', ' ', ' ', 0],
142+
Minus: ['-', '_', '–', '—', 0],
143+
Equal: ['=', '+', '≠', '±', 0],
144+
BracketLeft: ['[', '{', '“', '”', 0],
145+
BracketRight: [']', '}', '‘', '’', 0],
146+
Backslash: ['\\', '|', '«', '»', 0],
147+
Semicolon: [';', ':', '…', 'Ú', 0],
148+
Quote: ['\'', '"', 'æ', 'Æ', 0],
149+
Backquote: ['`', '~', '`', '`', 4],
150+
Comma: [',', '<', '≤', '¯', 0],
151+
Period: ['.', '>', '≥', '˘', 0],
152+
Slash: ['/', '?', '÷', '¿', 0],
153+
CapsLock: [],
154+
F1: [],
155+
F2: [],
156+
F3: [],
157+
F4: [],
158+
F5: [],
159+
F6: [],
160+
F7: [],
161+
F8: [],
162+
F9: [],
163+
F10: [],
164+
F11: [],
165+
F12: [],
166+
Insert: [],
167+
Home: [],
168+
PageUp: [],
169+
Delete: [],
170+
End: [],
171+
PageDown: [],
172+
ArrowRight: [],
173+
ArrowLeft: [],
174+
ArrowDown: [],
175+
ArrowUp: [],
176+
NumLock: [],
177+
NumpadDivide: ['/', '/', '/', '/', 0],
178+
NumpadMultiply: ['*', '*', '*', '*', 0],
179+
NumpadSubtract: ['-', '-', '-', '-', 0],
180+
NumpadAdd: ['+', '+', '+', '+', 0],
181+
NumpadEnter: [],
182+
Numpad1: ['1', '1', '1', '1', 0],
183+
Numpad2: ['2', '2', '2', '2', 0],
184+
Numpad3: ['3', '3', '3', '3', 0],
185+
Numpad4: ['4', '4', '4', '4', 0],
186+
Numpad5: ['5', '5', '5', '5', 0],
187+
Numpad6: ['6', '6', '6', '6', 0],
188+
Numpad7: ['7', '7', '7', '7', 0],
189+
Numpad8: ['8', '8', '8', '8', 0],
190+
Numpad9: ['9', '9', '9', '9', 0],
191+
Numpad0: ['0', '0', '0', '0', 0],
192+
NumpadDecimal: ['.', '.', '.', '.', 0],
193+
IntlBackslash: ['§', '±', '§', '±', 0],
194+
ContextMenu: [],
195+
NumpadEqual: ['=', '=', '=', '=', 0],
196+
F13: [],
197+
F14: [],
198+
F15: [],
199+
F16: [],
200+
F17: [],
201+
F18: [],
202+
F19: [],
203+
F20: [],
204+
AudioVolumeMute: [],
205+
AudioVolumeUp: ['', '=', '', '=', 0],
206+
AudioVolumeDown: [],
207+
NumpadComma: [],
208+
IntlRo: [],
209+
KanaMode: [],
210+
IntlYen: [],
211+
ControlLeft: [],
212+
ShiftLeft: [],
213+
AltLeft: [],
214+
MetaLeft: [],
215+
ControlRight: [],
216+
ShiftRight: [],
217+
AltRight: [],
218+
MetaRight: []
219+
}
220+
);
221+
222+
export class KeyboardLayoutProvider {
223+
public static readonly INSTANCE: KeyboardLayoutProvider = new KeyboardLayoutProvider();
224+
225+
private _layoutInfos: KeyboardLayoutInfo[] = [];
226+
private _mru: KeyboardLayoutInfo[] = [];
227+
private _active: KeyboardLayoutInfo | null;
228+
229+
private constructor() {
230+
this._active = null;
231+
}
232+
233+
registerKeyboardLayout(layout: KeyboardLayoutInfo) {
234+
this._layoutInfos.push(layout);
235+
this._mru = this._layoutInfos;
236+
}
237+
238+
get activeKeyboardLayout() {
239+
return this._active;
240+
}
241+
242+
isActive(keymap: IKeyboardMapping) {
243+
return this._active && this._active.fuzzyEqual(keymap);
244+
}
245+
246+
setActive(keymap: IKeyboardMapping) {
247+
this._active = this.getMatchedKeyboardLayout(keymap);
248+
249+
if (!this._active) {
250+
return;
251+
}
252+
const index = this._mru.indexOf(this._active);
253+
254+
if (index === 0) {
255+
return;
256+
}
257+
258+
this._mru.splice(index, 1);
259+
this._mru.unshift(this._active);
260+
}
261+
262+
getMatchedKeyboardLayout(keymap: IKeyboardMapping): KeyboardLayoutInfo | null {
263+
// TODO go through mru list instead of _layoutInfos
264+
for (let i = 0; i < this._mru.length; i++) {
265+
if (this._mru[i].fuzzyEqual(keymap)) {
266+
return this._mru[i];
267+
}
268+
}
269+
270+
return null;
271+
}
272+
273+
getKeyboardLayouts(): KeyboardLayoutInfo[] {
274+
return this._layoutInfos.slice(0);
275+
}
276+
}

0 commit comments

Comments
 (0)