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