1import KeyTable from "./keysym.js";
2import keysyms from "./keysymdef.js";
3import vkeys from "./vkeys.js";
4import fixedkeys from "./fixedkeys.js";
5import DOMKeyTable from "./domkeytable.js";
6import * as browser from "../util/browser.js";
8// Get 'KeyboardEvent.code', handling legacy browsers
9export function getKeycode(evt) {
10 // Are we getting proper key identifiers?
11 // (unfortunately Firefox and Chrome are crappy here and gives
12 // us an empty string on some platforms, rather than leaving it
15 // Mozilla isn't fully in sync with the spec yet
17 case 'OSLeft': return 'MetaLeft';
18 case 'OSRight': return 'MetaRight';
24 // The de-facto standard is to use Windows Virtual-Key codes
25 // in the 'keyCode' field for non-printable characters
26 if (evt.keyCode in vkeys) {
27 let code = vkeys[evt.keyCode];
29 // macOS has messed up this code for some reason
30 if (browser.isMac() && (code === 'ContextMenu')) {
34 // The keyCode doesn't distinguish between left and right
35 // for the standard modifiers
36 if (evt.location === 2) {
38 case 'ShiftLeft': return 'ShiftRight';
39 case 'ControlLeft': return 'ControlRight';
40 case 'AltLeft': return 'AltRight';
44 // Nor a bunch of the numpad keys
45 if (evt.location === 3) {
47 case 'Delete': return 'NumpadDecimal';
48 case 'Insert': return 'Numpad0';
49 case 'End': return 'Numpad1';
50 case 'ArrowDown': return 'Numpad2';
51 case 'PageDown': return 'Numpad3';
52 case 'ArrowLeft': return 'Numpad4';
53 case 'ArrowRight': return 'Numpad6';
54 case 'Home': return 'Numpad7';
55 case 'ArrowUp': return 'Numpad8';
56 case 'PageUp': return 'Numpad9';
57 case 'Enter': return 'NumpadEnter';
64 return 'Unidentified';
67// Get 'KeyboardEvent.key', handling legacy browsers
68export function getKey(evt) {
69 // Are we getting a proper key value?
70 if ((evt.key !== undefined) && (evt.key !== 'Unidentified')) {
71 // Mozilla isn't fully in sync with the spec yet
73 case 'OS': return 'Meta';
74 case 'LaunchMyComputer': return 'LaunchApplication1';
75 case 'LaunchCalculator': return 'LaunchApplication2';
78 // iOS leaks some OS names
80 case 'UIKeyInputUpArrow': return 'ArrowUp';
81 case 'UIKeyInputDownArrow': return 'ArrowDown';
82 case 'UIKeyInputLeftArrow': return 'ArrowLeft';
83 case 'UIKeyInputRightArrow': return 'ArrowRight';
84 case 'UIKeyInputEscape': return 'Escape';
87 // Broken behaviour in Chrome
88 if ((evt.key === '\x00') && (evt.code === 'NumpadDecimal')) {
95 // Try to deduce it based on the physical key
96 const code = getKeycode(evt);
97 if (code in fixedkeys) {
98 return fixedkeys[code];
101 // If that failed, then see if we have a printable character
103 return String.fromCharCode(evt.charCode);
106 // At this point we have nothing left to go on
107 return 'Unidentified';
110// Get the most reliable keysym value we can get from a key event
111export function getKeysym(evt) {
112 const key = getKey(evt);
114 if (key === 'Unidentified') {
118 // First look up special keys
119 if (key in DOMKeyTable) {
120 let location = evt.location;
122 // Safari screws up location for the right cmd key
123 if ((key === 'Meta') && (location === 0)) {
128 if ((key === 'Clear') && (location === 3)) {
129 let code = getKeycode(evt);
130 if (code === 'NumLock') {
135 if ((location === undefined) || (location > 3)) {
139 // The original Meta key now gets confused with the Windows key
140 // https://bugs.chromium.org/p/chromium/issues/detail?id=1020141
141 // https://bugzilla.mozilla.org/show_bug.cgi?id=1232918
142 if (key === 'Meta') {
143 let code = getKeycode(evt);
144 if (code === 'AltLeft') {
145 return KeyTable.XK_Meta_L;
146 } else if (code === 'AltRight') {
147 return KeyTable.XK_Meta_R;
151 // macOS has Clear instead of NumLock, but the remote system is
152 // probably not macOS, so lying here is probably best...
153 if (key === 'Clear') {
154 let code = getKeycode(evt);
155 if (code === 'NumLock') {
156 return KeyTable.XK_Num_Lock;
160 // Windows sends alternating symbols for some keys when using a
161 // Japanese layout. We have no way of synchronising with the IM
162 // running on the remote system, so we send some combined keysym
163 // instead and hope for the best.
164 if (browser.isWindows()) {
168 return KeyTable.XK_Zenkaku_Hankaku;
171 return KeyTable.XK_Romaji;
175 return DOMKeyTable[key][location];
178 // Now we need to look at the Unicode symbol instead
180 // Special key? (FIXME: Should have been caught earlier)
181 if (key.length !== 1) {
185 const codepoint = key.charCodeAt();
187 return keysyms.lookup(codepoint);