Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/base/browser/keyboardEvent.ts
5251 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 * as browser from './browser.js';
7
import { EVENT_KEY_CODE_MAP, isModifierKey, KeyCode, KeyCodeUtils, KeyMod } from '../common/keyCodes.js';
8
import { KeyCodeChord } from '../common/keybindings.js';
9
import * as platform from '../common/platform.js';
10
11
function extractKeyCode(e: KeyboardEvent): KeyCode {
12
if (e.charCode) {
13
// "keypress" events mostly
14
const char = String.fromCharCode(e.charCode).toUpperCase();
15
return KeyCodeUtils.fromString(char);
16
}
17
18
const keyCode = e.keyCode;
19
20
// browser quirks
21
if (keyCode === 3) {
22
return KeyCode.PauseBreak;
23
} else if (browser.isFirefox) {
24
switch (keyCode) {
25
case 59: return KeyCode.Semicolon;
26
case 60:
27
if (platform.isLinux) { return KeyCode.IntlBackslash; }
28
break;
29
case 61: return KeyCode.Equal;
30
// based on: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode#numpad_keys
31
case 107: return KeyCode.NumpadAdd;
32
case 109: return KeyCode.NumpadSubtract;
33
case 173: return KeyCode.Minus;
34
case 224:
35
if (platform.isMacintosh) { return KeyCode.Meta; }
36
break;
37
}
38
} else if (browser.isWebKit) {
39
if (platform.isMacintosh && keyCode === 93) {
40
// the two meta keys in the Mac have different key codes (91 and 93)
41
return KeyCode.Meta;
42
} else if (!platform.isMacintosh && keyCode === 92) {
43
return KeyCode.Meta;
44
}
45
}
46
47
// cross browser keycodes:
48
return EVENT_KEY_CODE_MAP[keyCode] || KeyCode.Unknown;
49
}
50
51
export interface IKeyboardEvent {
52
53
readonly _standardKeyboardEventBrand: true;
54
55
readonly browserEvent: KeyboardEvent;
56
readonly target: HTMLElement;
57
58
readonly ctrlKey: boolean;
59
readonly shiftKey: boolean;
60
readonly altKey: boolean;
61
readonly metaKey: boolean;
62
readonly altGraphKey: boolean;
63
readonly keyCode: KeyCode;
64
readonly code: string;
65
66
/**
67
* @internal
68
*/
69
toKeyCodeChord(): KeyCodeChord;
70
equals(keybinding: number): boolean;
71
72
preventDefault(): void;
73
stopPropagation(): void;
74
}
75
76
const ctrlKeyMod = (platform.isMacintosh ? KeyMod.WinCtrl : KeyMod.CtrlCmd);
77
const altKeyMod = KeyMod.Alt;
78
const shiftKeyMod = KeyMod.Shift;
79
const metaKeyMod = (platform.isMacintosh ? KeyMod.CtrlCmd : KeyMod.WinCtrl);
80
81
export function printKeyboardEvent(e: KeyboardEvent): string {
82
const modifiers: string[] = [];
83
if (e.ctrlKey) {
84
modifiers.push(`ctrl`);
85
}
86
if (e.shiftKey) {
87
modifiers.push(`shift`);
88
}
89
if (e.altKey) {
90
modifiers.push(`alt`);
91
}
92
if (e.metaKey) {
93
modifiers.push(`meta`);
94
}
95
return `modifiers: [${modifiers.join(',')}], code: ${e.code}, keyCode: ${e.keyCode}, key: ${e.key}`;
96
}
97
98
export function printStandardKeyboardEvent(e: StandardKeyboardEvent): string {
99
const modifiers: string[] = [];
100
if (e.ctrlKey) {
101
modifiers.push(`ctrl`);
102
}
103
if (e.shiftKey) {
104
modifiers.push(`shift`);
105
}
106
if (e.altKey) {
107
modifiers.push(`alt`);
108
}
109
if (e.metaKey) {
110
modifiers.push(`meta`);
111
}
112
return `modifiers: [${modifiers.join(',')}], code: ${e.code}, keyCode: ${e.keyCode} ('${KeyCodeUtils.toString(e.keyCode)}')`;
113
}
114
115
export function hasModifierKeys(keyStatus: {
116
readonly ctrlKey: boolean;
117
readonly shiftKey: boolean;
118
readonly altKey: boolean;
119
readonly metaKey: boolean;
120
}): boolean {
121
return keyStatus.ctrlKey || keyStatus.shiftKey || keyStatus.altKey || keyStatus.metaKey;
122
}
123
124
export class StandardKeyboardEvent implements IKeyboardEvent {
125
126
readonly _standardKeyboardEventBrand = true;
127
128
public readonly browserEvent: KeyboardEvent;
129
public readonly target: HTMLElement;
130
131
public readonly ctrlKey: boolean;
132
public readonly shiftKey: boolean;
133
public readonly altKey: boolean;
134
public readonly metaKey: boolean;
135
public readonly altGraphKey: boolean;
136
public readonly keyCode: KeyCode;
137
public readonly code: string;
138
139
private _asKeybinding: number;
140
private _asKeyCodeChord: KeyCodeChord;
141
142
constructor(source: KeyboardEvent) {
143
const e = source;
144
145
this.browserEvent = e;
146
this.target = <HTMLElement>e.target;
147
148
this.ctrlKey = e.ctrlKey;
149
this.shiftKey = e.shiftKey;
150
this.altKey = e.altKey;
151
this.metaKey = e.metaKey;
152
this.altGraphKey = e.getModifierState?.('AltGraph');
153
this.keyCode = extractKeyCode(e);
154
this.code = e.code;
155
156
// console.info(e.type + ": keyCode: " + e.keyCode + ", which: " + e.which + ", charCode: " + e.charCode + ", detail: " + e.detail + " ====> " + this.keyCode + ' -- ' + KeyCode[this.keyCode]);
157
158
this.ctrlKey = this.ctrlKey || this.keyCode === KeyCode.Ctrl;
159
this.altKey = this.altKey || this.keyCode === KeyCode.Alt;
160
this.shiftKey = this.shiftKey || this.keyCode === KeyCode.Shift;
161
this.metaKey = this.metaKey || this.keyCode === KeyCode.Meta;
162
163
this._asKeybinding = this._computeKeybinding();
164
this._asKeyCodeChord = this._computeKeyCodeChord();
165
166
// console.log(`code: ${e.code}, keyCode: ${e.keyCode}, key: ${e.key}`);
167
}
168
169
public preventDefault(): void {
170
if (this.browserEvent && this.browserEvent.preventDefault) {
171
this.browserEvent.preventDefault();
172
}
173
}
174
175
public stopPropagation(): void {
176
if (this.browserEvent && this.browserEvent.stopPropagation) {
177
this.browserEvent.stopPropagation();
178
}
179
}
180
181
public toKeyCodeChord(): KeyCodeChord {
182
return this._asKeyCodeChord;
183
}
184
185
public equals(other: number): boolean {
186
return this._asKeybinding === other;
187
}
188
189
private _computeKeybinding(): number {
190
let key = KeyCode.Unknown;
191
if (!isModifierKey(this.keyCode)) {
192
key = this.keyCode;
193
}
194
195
let result = 0;
196
if (this.ctrlKey) {
197
result |= ctrlKeyMod;
198
}
199
if (this.altKey) {
200
result |= altKeyMod;
201
}
202
if (this.shiftKey) {
203
result |= shiftKeyMod;
204
}
205
if (this.metaKey) {
206
result |= metaKeyMod;
207
}
208
result |= key;
209
210
return result;
211
}
212
213
private _computeKeyCodeChord(): KeyCodeChord {
214
let key = KeyCode.Unknown;
215
if (!isModifierKey(this.keyCode)) {
216
key = this.keyCode;
217
}
218
return new KeyCodeChord(this.ctrlKey, this.shiftKey, this.altKey, this.metaKey, key);
219
}
220
}
221
222