noVNC/core/input/util.js

158 lines
5.1 KiB
JavaScript

import KeyTable from "./keysym.js";
import keysyms from "./keysymdef.js";
import vkeys from "./vkeys.js";
import fixedkeys from "./fixedkeys.js";
function isMac() {
return navigator && !!(/mac/i).exec(navigator.platform);
}
// Get 'KeyboardEvent.code', handling legacy browsers
export function getKeycode(evt){
// Are we getting proper key identifiers?
// (unfortunately Firefox and Chrome are crappy here and gives
// us an empty string on some platforms, rather than leaving it
// undefined)
if (evt.code) {
// Mozilla isn't fully in sync with the spec yet
switch (evt.code) {
case 'OSLeft': return 'MetaLeft';
case 'OSRight': return 'MetaRight';
}
return evt.code;
}
// The de-facto standard is to use Windows Virtual-Key codes
// in the 'keyCode' field for non-printable characters. However
// Webkit sets it to the same as charCode in 'keypress' events.
if ((evt.type !== 'keypress') && (evt.keyCode in vkeys)) {
var code = vkeys[evt.keyCode];
// macOS has messed up this code for some reason
if (isMac() && (code === 'ContextMenu')) {
code = 'MetaRight';
}
// The keyCode doesn't distinguish between left and right
// for the standard modifiers
if (evt.location === 2) {
switch (code) {
case 'ShiftLeft': return 'ShiftRight';
case 'ControlLeft': return 'ControlRight';
case 'AltLeft': return 'AltRight';
}
}
// Nor a bunch of the numpad keys
if (evt.location === 3) {
switch (code) {
case 'Delete': return 'NumpadDecimal';
case 'Insert': return 'Numpad0';
case 'End': return 'Numpad1';
case 'ArrowDown': return 'Numpad2';
case 'PageDown': return 'Numpad3';
case 'ArrowLeft': return 'Numpad4';
case 'ArrowRight': return 'Numpad6';
case 'Home': return 'Numpad7';
case 'ArrowUp': return 'Numpad8';
case 'PageUp': return 'Numpad9';
case 'Enter': return 'NumpadEnter';
}
}
return code;
}
return 'Unidentified';
}
// Get the most reliable keysym value we can get from a key event
export function getKeysym(evt){
// We start with layout independent keys
var code = getKeycode(evt);
if (code in fixedkeys) {
return fixedkeys[code];
}
// Next with mildly layout or state sensitive stuff
// Like AltGraph
if (code === 'AltRight') {
if (evt.key === 'AltGraph') {
return KeyTable.XK_ISO_Level3_Shift;
} else {
return KeyTable.XK_Alt_R;
}
}
// Or the numpad
if (evt.location === 3) {
var key = evt.key;
// IE and Edge use some ancient version of the spec
// https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8860571/
switch (key) {
case 'Up': key = 'ArrowUp'; break;
case 'Left': key = 'ArrowLeft'; break;
case 'Right': key = 'ArrowRight'; break;
case 'Down': key = 'ArrowDown'; break;
case 'Del': key = 'Delete'; break;
}
// Safari doesn't support KeyboardEvent.key yet
if ((key === undefined) && (evt.charCode)) {
key = String.fromCharCode(evt.charCode);
}
switch (key) {
case '0': return KeyTable.XK_KP_0;
case '1': return KeyTable.XK_KP_1;
case '2': return KeyTable.XK_KP_2;
case '3': return KeyTable.XK_KP_3;
case '4': return KeyTable.XK_KP_4;
case '5': return KeyTable.XK_KP_5;
case '6': return KeyTable.XK_KP_6;
case '7': return KeyTable.XK_KP_7;
case '8': return KeyTable.XK_KP_8;
case '9': return KeyTable.XK_KP_9;
// There is utter mayhem in the world when it comes to which
// character to use as a decimal separator...
case '.': return KeyTable.XK_KP_Decimal;
case ',': return KeyTable.XK_KP_Separator;
case 'Home': return KeyTable.XK_KP_Home;
case 'End': return KeyTable.XK_KP_End;
case 'PageUp': return KeyTable.XK_KP_Prior;
case 'PageDown': return KeyTable.XK_KP_Next;
case 'Insert': return KeyTable.XK_KP_Insert;
case 'Delete': return KeyTable.XK_KP_Delete;
case 'ArrowUp': return KeyTable.XK_KP_Up;
case 'ArrowLeft': return KeyTable.XK_KP_Left;
case 'ArrowRight': return KeyTable.XK_KP_Right;
case 'ArrowDown': return KeyTable.XK_KP_Down;
}
}
// Now we need to look at the Unicode symbol instead
var codepoint;
if ('key' in evt) {
// Special key? (FIXME: Should have been caught earlier)
if (evt.key.length !== 1) {
return null;
}
codepoint = evt.key.charCodeAt();
} else if ('charCode' in evt) {
codepoint = evt.charCode;
}
if (codepoint) {
return keysyms.lookup(codepoint);
}
return null;
}