Use KeyboardEvent.key too look up keysyms
And emulate it on browsers where it is missing or incorrect. This makes the code more future oriented as it primarily uses the standardised fields.
This commit is contained in:
parent
634cc1ba46
commit
9782d4a324
|
@ -0,0 +1,310 @@
|
||||||
|
/*
|
||||||
|
* noVNC: HTML5 VNC client
|
||||||
|
* Copyright (C) 2017 Pierre Ossman for Cendio AB
|
||||||
|
* Licensed under MPL 2.0 or any later version (see LICENSE.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import KeyTable from "./keysym.js"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mapping between HTML key values and VNC/X11 keysyms for "special"
|
||||||
|
* keys that cannot be handled via their Unicode codepoint.
|
||||||
|
*
|
||||||
|
* See https://www.w3.org/TR/uievents-key/ for possible values.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var DOMKeyTable = {};
|
||||||
|
|
||||||
|
function addStandard(key, standard)
|
||||||
|
{
|
||||||
|
if (standard === undefined) throw "Undefined keysym for key \"" + key + "\"";
|
||||||
|
if (key in DOMKeyTable) throw "Duplicate entry for key \"" + key + "\"";
|
||||||
|
DOMKeyTable[key] = [standard, standard, standard, standard];
|
||||||
|
}
|
||||||
|
|
||||||
|
function addLeftRight(key, left, right)
|
||||||
|
{
|
||||||
|
if (left === undefined) throw "Undefined keysym for key \"" + key + "\"";
|
||||||
|
if (right === undefined) throw "Undefined keysym for key \"" + key + "\"";
|
||||||
|
if (key in DOMKeyTable) throw "Duplicate entry for key \"" + key + "\"";
|
||||||
|
DOMKeyTable[key] = [left, left, right, left];
|
||||||
|
}
|
||||||
|
|
||||||
|
function addNumpad(key, standard, numpad)
|
||||||
|
{
|
||||||
|
if (standard === undefined) throw "Undefined keysym for key \"" + key + "\"";
|
||||||
|
if (numpad === undefined) throw "Undefined keysym for key \"" + key + "\"";
|
||||||
|
if (key in DOMKeyTable) throw "Duplicate entry for key \"" + key + "\"";
|
||||||
|
DOMKeyTable[key] = [standard, standard, standard, numpad];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.2. Modifier Keys
|
||||||
|
|
||||||
|
addLeftRight("Alt", KeyTable.XK_Alt_L, KeyTable.XK_Alt_R);
|
||||||
|
addStandard("AltGraph", KeyTable.XK_ISO_Level3_Shift);
|
||||||
|
addStandard("CapsLock", KeyTable.XK_Caps_Lock);
|
||||||
|
addLeftRight("Control", KeyTable.XK_Control_L, KeyTable.XK_Control_R);
|
||||||
|
// - Fn
|
||||||
|
// - FnLock
|
||||||
|
addLeftRight("Hyper", KeyTable.XK_Super_L, KeyTable.XK_Super_R);
|
||||||
|
addLeftRight("Meta", KeyTable.XK_Super_L, KeyTable.XK_Super_R);
|
||||||
|
addStandard("NumLock", KeyTable.XK_Num_Lock);
|
||||||
|
addStandard("ScrollLock", KeyTable.XK_Scroll_Lock);
|
||||||
|
addLeftRight("Shift", KeyTable.XK_Shift_L, KeyTable.XK_Shift_R);
|
||||||
|
addLeftRight("Super", KeyTable.XK_Super_L, KeyTable.XK_Super_R);
|
||||||
|
// - Symbol
|
||||||
|
// - SymbolLock
|
||||||
|
|
||||||
|
// 2.3. Whitespace Keys
|
||||||
|
|
||||||
|
addNumpad("Enter", KeyTable.XK_Return, KeyTable.XK_KP_Enter);
|
||||||
|
addStandard("Tab", KeyTable.XK_Tab);
|
||||||
|
addNumpad(" ", KeyTable.XK_space, KeyTable.XK_KP_Space);
|
||||||
|
|
||||||
|
// 2.4. Navigation Keys
|
||||||
|
|
||||||
|
addNumpad("ArrowDown", KeyTable.XK_Down, KeyTable.XK_KP_Down);
|
||||||
|
addNumpad("ArrowUp", KeyTable.XK_Up, KeyTable.XK_KP_Up);
|
||||||
|
addNumpad("ArrowLeft", KeyTable.XK_Left, KeyTable.XK_KP_Left);
|
||||||
|
addNumpad("ArrowRight", KeyTable.XK_Right, KeyTable.XK_KP_Right);
|
||||||
|
addNumpad("End", KeyTable.XK_End, KeyTable.XK_KP_End);
|
||||||
|
addNumpad("Home", KeyTable.XK_Home, KeyTable.XK_KP_Home);
|
||||||
|
addNumpad("PageDown", KeyTable.XK_Next, KeyTable.XK_KP_Next);
|
||||||
|
addNumpad("PageUp", KeyTable.XK_Prior, KeyTable.XK_KP_Prior);
|
||||||
|
|
||||||
|
// 2.5. Editing Keys
|
||||||
|
|
||||||
|
addStandard("Backspace", KeyTable.XK_BackSpace);
|
||||||
|
addStandard("Clear", KeyTable.XK_Clear);
|
||||||
|
addStandard("Copy", KeyTable.XF86XK_Copy);
|
||||||
|
// - CrSel
|
||||||
|
addStandard("Cut", KeyTable.XF86XK_Cut);
|
||||||
|
addNumpad("Delete", KeyTable.XK_Delete, KeyTable.XK_KP_Delete);
|
||||||
|
// - EraseEof
|
||||||
|
// - ExSel
|
||||||
|
addNumpad("Insert", KeyTable.XK_Insert, KeyTable.XK_KP_Insert);
|
||||||
|
addStandard("Paste", KeyTable.XF86XK_Paste);
|
||||||
|
addStandard("Redo", KeyTable.XK_Redo);
|
||||||
|
addStandard("Undo", KeyTable.XK_Undo);
|
||||||
|
|
||||||
|
// 2.6. UI Keys
|
||||||
|
|
||||||
|
// - Accept
|
||||||
|
// - Again (could just be XK_Redo)
|
||||||
|
// - Attn
|
||||||
|
addStandard("Cancel", KeyTable.XK_Cancel);
|
||||||
|
addStandard("ContextMenu", KeyTable.XK_Menu);
|
||||||
|
addStandard("Escape", KeyTable.XK_Escape);
|
||||||
|
addStandard("Execute", KeyTable.XK_Execute);
|
||||||
|
addStandard("Find", KeyTable.XK_Find);
|
||||||
|
addStandard("Help", KeyTable.XK_Help);
|
||||||
|
addStandard("Pause", KeyTable.XK_Pause);
|
||||||
|
// - Play
|
||||||
|
// - Props
|
||||||
|
addStandard("Select", KeyTable.XK_Select);
|
||||||
|
addStandard("ZoomIn", KeyTable.XF86XK_ZoomIn);
|
||||||
|
addStandard("ZoomOut", KeyTable.XF86XK_ZoomOut);
|
||||||
|
|
||||||
|
// 2.7. Device Keys
|
||||||
|
|
||||||
|
addStandard("BrightnessDown", KeyTable.XF86XK_MonBrightnessDown);
|
||||||
|
addStandard("BrightnessUp", KeyTable.XF86XK_MonBrightnessUp);
|
||||||
|
addStandard("Eject", KeyTable.XF86XK_Eject);
|
||||||
|
addStandard("LogOff", KeyTable.XF86XK_LogOff);
|
||||||
|
addStandard("Power", KeyTable.XF86XK_PowerOff);
|
||||||
|
addStandard("PowerOff", KeyTable.XF86XK_PowerDown);
|
||||||
|
addStandard("PrintScreen", KeyTable.XK_Print);
|
||||||
|
addStandard("Hibernate", KeyTable.XF86XK_Hibernate);
|
||||||
|
addStandard("Standby", KeyTable.XF86XK_Standby);
|
||||||
|
addStandard("WakeUp", KeyTable.XF86XK_WakeUp);
|
||||||
|
|
||||||
|
// 2.8. IME and Composition Keys
|
||||||
|
|
||||||
|
addStandard("AllCandidates", KeyTable.XK_MultipleCandidate);
|
||||||
|
addStandard("Alphanumeric", KeyTable.XK_Eisu_Shift); // could also be _Eisu_Toggle
|
||||||
|
addStandard("CodeInput", KeyTable.XK_Codeinput);
|
||||||
|
addStandard("Compose", KeyTable.XK_Multi_key);
|
||||||
|
addStandard("Convert", KeyTable.XK_Henkan);
|
||||||
|
// - Dead
|
||||||
|
// - FinalMode
|
||||||
|
addStandard("GroupFirst", KeyTable.XK_ISO_First_Group);
|
||||||
|
addStandard("GroupLast", KeyTable.XK_ISO_Last_Group);
|
||||||
|
addStandard("GroupNext", KeyTable.XK_ISO_Next_Group);
|
||||||
|
addStandard("GroupPrevious", KeyTable.XK_ISO_Prev_Group);
|
||||||
|
// - ModeChange (XK_Mode_switch is often used for AltGr)
|
||||||
|
// - NextCandidate
|
||||||
|
addStandard("NonConvert", KeyTable.XK_Muhenkan);
|
||||||
|
addStandard("PreviousCandidate", KeyTable.XK_PreviousCandidate);
|
||||||
|
// - Process
|
||||||
|
addStandard("SingleCandidate", KeyTable.XK_SingleCandidate);
|
||||||
|
addStandard("HangulMode", KeyTable.XK_Hangul);
|
||||||
|
addStandard("HanjaMode", KeyTable.XK_Hangul_Hanja);
|
||||||
|
addStandard("JunjuaMode", KeyTable.XK_Hangul_Jeonja);
|
||||||
|
addStandard("Eisu", KeyTable.XK_Eisu_toggle);
|
||||||
|
addStandard("Hankaku", KeyTable.XK_Hankaku);
|
||||||
|
addStandard("Hiragana", KeyTable.XK_Hiragana);
|
||||||
|
addStandard("HiraganaKatakana", KeyTable.XK_Hiragana_Katakana);
|
||||||
|
addStandard("KanaMode", KeyTable.XK_Kana_Shift); // could also be _Kana_Lock
|
||||||
|
addStandard("KanjiMode", KeyTable.XK_Kanji);
|
||||||
|
addStandard("Katakana", KeyTable.XK_Katakana);
|
||||||
|
addStandard("Romaji", KeyTable.XK_Romaji);
|
||||||
|
addStandard("Zenkaku", KeyTable.XK_Zenkaku);
|
||||||
|
addStandard("ZenkakuHanaku", KeyTable.XK_Zenkaku_Hankaku);
|
||||||
|
|
||||||
|
// 2.9. General-Purpose Function Keys
|
||||||
|
|
||||||
|
addStandard("F1", KeyTable.XK_F1);
|
||||||
|
addStandard("F2", KeyTable.XK_F2);
|
||||||
|
addStandard("F3", KeyTable.XK_F3);
|
||||||
|
addStandard("F4", KeyTable.XK_F4);
|
||||||
|
addStandard("F5", KeyTable.XK_F5);
|
||||||
|
addStandard("F6", KeyTable.XK_F6);
|
||||||
|
addStandard("F7", KeyTable.XK_F7);
|
||||||
|
addStandard("F8", KeyTable.XK_F8);
|
||||||
|
addStandard("F9", KeyTable.XK_F9);
|
||||||
|
addStandard("F10", KeyTable.XK_F10);
|
||||||
|
addStandard("F11", KeyTable.XK_F11);
|
||||||
|
addStandard("F12", KeyTable.XK_F12);
|
||||||
|
addStandard("F13", KeyTable.XK_F13);
|
||||||
|
addStandard("F14", KeyTable.XK_F14);
|
||||||
|
addStandard("F15", KeyTable.XK_F15);
|
||||||
|
addStandard("F16", KeyTable.XK_F16);
|
||||||
|
addStandard("F17", KeyTable.XK_F17);
|
||||||
|
addStandard("F18", KeyTable.XK_F18);
|
||||||
|
addStandard("F19", KeyTable.XK_F19);
|
||||||
|
addStandard("F20", KeyTable.XK_F20);
|
||||||
|
addStandard("F21", KeyTable.XK_F21);
|
||||||
|
addStandard("F22", KeyTable.XK_F22);
|
||||||
|
addStandard("F23", KeyTable.XK_F23);
|
||||||
|
addStandard("F24", KeyTable.XK_F24);
|
||||||
|
addStandard("F25", KeyTable.XK_F25);
|
||||||
|
addStandard("F26", KeyTable.XK_F26);
|
||||||
|
addStandard("F27", KeyTable.XK_F27);
|
||||||
|
addStandard("F28", KeyTable.XK_F28);
|
||||||
|
addStandard("F29", KeyTable.XK_F29);
|
||||||
|
addStandard("F30", KeyTable.XK_F30);
|
||||||
|
addStandard("F31", KeyTable.XK_F31);
|
||||||
|
addStandard("F32", KeyTable.XK_F32);
|
||||||
|
addStandard("F33", KeyTable.XK_F33);
|
||||||
|
addStandard("F34", KeyTable.XK_F34);
|
||||||
|
addStandard("F35", KeyTable.XK_F35);
|
||||||
|
// - Soft1...
|
||||||
|
|
||||||
|
// 2.10. Multimedia Keys
|
||||||
|
|
||||||
|
// - ChannelDown
|
||||||
|
// - ChannelUp
|
||||||
|
addStandard("Close", KeyTable.XF86XK_Close);
|
||||||
|
addStandard("MailForward", KeyTable.XF86XK_MailForward);
|
||||||
|
addStandard("MailReply", KeyTable.XF86XK_Reply);
|
||||||
|
addStandard("MainSend", KeyTable.XF86XK_Send);
|
||||||
|
addStandard("MediaFastForward", KeyTable.XF86XK_AudioForward);
|
||||||
|
addStandard("MediaPause", KeyTable.XF86XK_AudioPause);
|
||||||
|
addStandard("MediaPlay", KeyTable.XF86XK_AudioPlay);
|
||||||
|
addStandard("MediaRecord", KeyTable.XF86XK_AudioRecord);
|
||||||
|
addStandard("MediaRewind", KeyTable.XF86XK_AudioRewind);
|
||||||
|
addStandard("MediaStop", KeyTable.XF86XK_AudioStop);
|
||||||
|
addStandard("MediaTrackNext", KeyTable.XF86XK_AudioNext);
|
||||||
|
addStandard("MediaTrackPrevious", KeyTable.XF86XK_AudioPrev);
|
||||||
|
addStandard("New", KeyTable.XF86XK_New);
|
||||||
|
addStandard("Open", KeyTable.XF86XK_Open);
|
||||||
|
addStandard("Print", KeyTable.XK_Print);
|
||||||
|
addStandard("Save", KeyTable.XF86XK_Save);
|
||||||
|
addStandard("SpellCheck", KeyTable.XF86XK_Spell);
|
||||||
|
|
||||||
|
// 2.11. Multimedia Numpad Keys
|
||||||
|
|
||||||
|
// - Key11
|
||||||
|
// - Key12
|
||||||
|
|
||||||
|
// 2.12. Audio Keys
|
||||||
|
|
||||||
|
// - AudioBalanceLeft
|
||||||
|
// - AudioBalanceRight
|
||||||
|
// - AudioBassDown
|
||||||
|
// - AudioBassBoostDown
|
||||||
|
// - AudioBassBoostToggle
|
||||||
|
// - AudioBassBoostUp
|
||||||
|
// - AudioBassUp
|
||||||
|
// - AudioFaderFront
|
||||||
|
// - AudioFaderRear
|
||||||
|
// - AudioSurroundModeNext
|
||||||
|
// - AudioTrebleDown
|
||||||
|
// - AudioTrebleUp
|
||||||
|
addStandard("AudioVolumeDown", KeyTable.XF86XK_AudioLowerVolume);
|
||||||
|
addStandard("AudioVolumeUp", KeyTable.XF86XK_AudioRaiseVolume);
|
||||||
|
addStandard("AudioVolumeMute", KeyTable.XF86XK_AudioMute);
|
||||||
|
// - MicrophoneToggle
|
||||||
|
// - MicrophoneVolumeDown
|
||||||
|
// - MicrophoneVolumeUp
|
||||||
|
addStandard("MicrophoneVolumeMute", KeyTable.XF86XK_AudioMicMute);
|
||||||
|
|
||||||
|
// 2.13. Speech Keys
|
||||||
|
|
||||||
|
// - SpeechCorrectionList
|
||||||
|
// - SpeechInputToggle
|
||||||
|
|
||||||
|
// 2.14. Application Keys
|
||||||
|
|
||||||
|
addStandard("LaunchCalculator", KeyTable.XF86XK_Calculator);
|
||||||
|
addStandard("LaunchCalendar", KeyTable.XF86XK_Calendar);
|
||||||
|
addStandard("LaunchMail", KeyTable.XF86XK_Mail);
|
||||||
|
addStandard("LaunchMediaPlayer", KeyTable.XF86XK_AudioMedia);
|
||||||
|
addStandard("LaunchMusicPlayer", KeyTable.XF86XK_Music);
|
||||||
|
addStandard("LaunchMyComputer", KeyTable.XF86XK_MyComputer);
|
||||||
|
addStandard("LaunchPhone", KeyTable.XF86XK_Phone);
|
||||||
|
addStandard("LaunchScreenSaver", KeyTable.XF86XK_ScreenSaver);
|
||||||
|
addStandard("LaunchSpreadsheet", KeyTable.XF86XK_Excel);
|
||||||
|
addStandard("LaunchWebBrowser", KeyTable.XF86XK_WWW);
|
||||||
|
addStandard("LaunchWebCam", KeyTable.XF86XK_WebCam);
|
||||||
|
addStandard("LaunchWordProcessor", KeyTable.XF86XK_Word);
|
||||||
|
|
||||||
|
// 2.15. Browser Keys
|
||||||
|
|
||||||
|
addStandard("BrowserBack", KeyTable.XF86XK_Back);
|
||||||
|
addStandard("BrowserFavorites", KeyTable.XF86XK_Favorites);
|
||||||
|
addStandard("BrowserForward", KeyTable.XF86XK_Forward);
|
||||||
|
addStandard("BrowserHome", KeyTable.XF86XK_HomePage);
|
||||||
|
addStandard("BrowserRefresh", KeyTable.XF86XK_Refresh);
|
||||||
|
addStandard("BrowserSearch", KeyTable.XF86XK_Search);
|
||||||
|
addStandard("BrowserStop", KeyTable.XF86XK_Stop);
|
||||||
|
|
||||||
|
// 2.16. Mobile Phone Keys
|
||||||
|
|
||||||
|
// - A whole bunch...
|
||||||
|
|
||||||
|
// 2.17. TV Keys
|
||||||
|
|
||||||
|
// - A whole bunch...
|
||||||
|
|
||||||
|
// 2.18. Media Controller Keys
|
||||||
|
|
||||||
|
// - A whole bunch...
|
||||||
|
addStandard("Dimmer", KeyTable.XF86XK_BrightnessAdjust);
|
||||||
|
addStandard("MediaAudioTrack", KeyTable.XF86XK_AudioCycleTrack);
|
||||||
|
addStandard("RandomToggle", KeyTable.XF86XK_AudioRandomPlay);
|
||||||
|
addStandard("SplitScreenToggle", KeyTable.XF86XK_SplitScreen);
|
||||||
|
addStandard("Subtitle", KeyTable.XF86XK_Subtitle);
|
||||||
|
addStandard("VideoModeNext", KeyTable.XF86XK_Next_VMode);
|
||||||
|
|
||||||
|
// Extra: Numpad
|
||||||
|
|
||||||
|
addNumpad("=", KeyTable.XK_equal, KeyTable.XK_KP_Equal);
|
||||||
|
addNumpad("+", KeyTable.XK_plus, KeyTable.XK_KP_Add);
|
||||||
|
addNumpad("-", KeyTable.XK_minus, KeyTable.XK_KP_Subtract);
|
||||||
|
addNumpad("*", KeyTable.XK_asterisk, KeyTable.XK_KP_Multiply);
|
||||||
|
addNumpad("/", KeyTable.XK_slash, KeyTable.XK_KP_Divide);
|
||||||
|
addNumpad(".", KeyTable.XK_period, KeyTable.XK_KP_Decimal);
|
||||||
|
addNumpad(",", KeyTable.XK_comma, KeyTable.XK_KP_Separator);
|
||||||
|
addNumpad("0", KeyTable.XK_0, KeyTable.XK_KP_0);
|
||||||
|
addNumpad("1", KeyTable.XK_1, KeyTable.XK_KP_1);
|
||||||
|
addNumpad("2", KeyTable.XK_2, KeyTable.XK_KP_2);
|
||||||
|
addNumpad("3", KeyTable.XK_3, KeyTable.XK_KP_3);
|
||||||
|
addNumpad("4", KeyTable.XK_4, KeyTable.XK_KP_4);
|
||||||
|
addNumpad("5", KeyTable.XK_5, KeyTable.XK_KP_5);
|
||||||
|
addNumpad("6", KeyTable.XK_6, KeyTable.XK_KP_6);
|
||||||
|
addNumpad("7", KeyTable.XK_7, KeyTable.XK_KP_7);
|
||||||
|
addNumpad("8", KeyTable.XK_8, KeyTable.XK_KP_8);
|
||||||
|
addNumpad("9", KeyTable.XK_9, KeyTable.XK_KP_9);
|
||||||
|
|
||||||
|
export default DOMKeyTable;
|
|
@ -5,108 +5,123 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mapping between HTML key codes and VNC/X11 keysyms for the
|
* Fallback mapping between HTML key codes (physical keys) and
|
||||||
* subset of keys that have the same mapping on every keyboard
|
* HTML key values. This only works for keys that don't vary
|
||||||
* layout. Keys that vary between layouts must never be included
|
* between layouts. We also omit those who manage fine by mapping the
|
||||||
* in this list.
|
* Unicode representation.
|
||||||
|
*
|
||||||
|
* See https://www.w3.org/TR/uievents-code/ for possible codes.
|
||||||
|
* See https://www.w3.org/TR/uievents-key/ for possible values.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import KeyTable from "./keysym.js";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
'Backspace': KeyTable.XK_BackSpace,
|
|
||||||
'AltLeft': KeyTable.XK_Alt_L,
|
// 3.1.1.1. Writing System Keys
|
||||||
// AltRight is special
|
|
||||||
'CapsLock': KeyTable.XK_Caps_Lock,
|
'Backspace': 'Backspace',
|
||||||
'ContextMenu': KeyTable.XK_Menu,
|
|
||||||
'ControlLeft': KeyTable.XK_Control_L,
|
// 3.1.1.2. Functional Keys
|
||||||
'ControlRight': KeyTable.XK_Control_R,
|
|
||||||
'Enter': KeyTable.XK_Return,
|
'AltLeft': 'Alt',
|
||||||
'MetaLeft': KeyTable.XK_Super_L,
|
'AltRight': 'Alt', // This could also be 'AltGraph'
|
||||||
'MetaRight': KeyTable.XK_Super_R,
|
'CapsLock': 'CapsLock',
|
||||||
'ShiftLeft': KeyTable.XK_Shift_L,
|
'ContextMenu': 'ContextMenu',
|
||||||
'ShiftRight': KeyTable.XK_Shift_R,
|
'ControlLeft': 'Control',
|
||||||
'Space': KeyTable.XK_space,
|
'ControlRight': 'Control',
|
||||||
'Tab': KeyTable.XK_Tab,
|
'Enter': 'Enter',
|
||||||
|
'MetaLeft': 'Meta',
|
||||||
|
'MetaRight': 'Meta',
|
||||||
|
'ShiftLeft': 'Shift',
|
||||||
|
'ShiftRight': 'Shift',
|
||||||
|
'Tab': 'Tab',
|
||||||
// FIXME: Japanese/Korean keys
|
// FIXME: Japanese/Korean keys
|
||||||
'Delete': KeyTable.XK_Delete,
|
|
||||||
'End': KeyTable.XK_End,
|
// 3.1.2. Control Pad Section
|
||||||
'Help': KeyTable.XK_Help,
|
|
||||||
'Home': KeyTable.XK_Home,
|
'Delete': 'Delete',
|
||||||
'Insert': KeyTable.XK_Insert,
|
'End': 'End',
|
||||||
'PageDown': KeyTable.XK_Next,
|
'Help': 'Help',
|
||||||
'PageUp': KeyTable.XK_Prior,
|
'Home': 'Home',
|
||||||
'ArrowDown': KeyTable.XK_Down,
|
'Insert': 'Insert',
|
||||||
'ArrowLeft': KeyTable.XK_Left,
|
'PageDown': 'PageDown',
|
||||||
'ArrowRight': KeyTable.XK_Right,
|
'PageUp': 'PageUp',
|
||||||
'ArrowUp': KeyTable.XK_Up,
|
|
||||||
'NumLock': KeyTable.XK_Num_Lock,
|
// 3.1.3. Arrow Pad Section
|
||||||
'NumpadAdd': KeyTable.XK_KP_Add,
|
|
||||||
'NumpadBackspace': KeyTable.XK_KP_Delete,
|
'ArrowDown': 'ArrowDown',
|
||||||
'NumpadClear': KeyTable.XK_Clear,
|
'ArrowLeft': 'ArrowLeft',
|
||||||
// NumpadDecimal is special
|
'ArrowRight': 'ArrowRight',
|
||||||
'NumpadDivide': KeyTable.XK_KP_Divide,
|
'ArrowUp': 'ArrowUp',
|
||||||
'NumpadEnter': KeyTable.XK_KP_Enter,
|
|
||||||
'NumpadEqual': KeyTable.XK_KP_Equal,
|
// 3.1.4. Numpad Section
|
||||||
'NumpadMultiply': KeyTable.XK_KP_Multiply,
|
|
||||||
'NumpadSubtract': KeyTable.XK_KP_Subtract,
|
'NumLock': 'NumLock',
|
||||||
'Escape': KeyTable.XK_Escape,
|
'NumpadBackspace': 'Backspace',
|
||||||
'F1': KeyTable.XK_F1,
|
'NumpadClear': 'Clear',
|
||||||
'F2': KeyTable.XK_F2,
|
|
||||||
'F3': KeyTable.XK_F3,
|
// 3.1.5. Function Section
|
||||||
'F4': KeyTable.XK_F4,
|
|
||||||
'F5': KeyTable.XK_F5,
|
'Escape': 'Escape',
|
||||||
'F6': KeyTable.XK_F6,
|
'F1': 'F1',
|
||||||
'F7': KeyTable.XK_F7,
|
'F2': 'F2',
|
||||||
'F8': KeyTable.XK_F8,
|
'F3': 'F3',
|
||||||
'F9': KeyTable.XK_F9,
|
'F4': 'F4',
|
||||||
'F10': KeyTable.XK_F10,
|
'F5': 'F5',
|
||||||
'F11': KeyTable.XK_F11,
|
'F6': 'F6',
|
||||||
'F12': KeyTable.XK_F12,
|
'F7': 'F7',
|
||||||
'F13': KeyTable.XK_F13,
|
'F8': 'F8',
|
||||||
'F14': KeyTable.XK_F14,
|
'F9': 'F9',
|
||||||
'F15': KeyTable.XK_F15,
|
'F10': 'F10',
|
||||||
'F16': KeyTable.XK_F16,
|
'F11': 'F11',
|
||||||
'F17': KeyTable.XK_F17,
|
'F12': 'F12',
|
||||||
'F18': KeyTable.XK_F18,
|
'F13': 'F13',
|
||||||
'F19': KeyTable.XK_F19,
|
'F14': 'F14',
|
||||||
'F20': KeyTable.XK_F20,
|
'F15': 'F15',
|
||||||
'F21': KeyTable.XK_F21,
|
'F16': 'F16',
|
||||||
'F22': KeyTable.XK_F22,
|
'F17': 'F17',
|
||||||
'F23': KeyTable.XK_F23,
|
'F18': 'F18',
|
||||||
'F24': KeyTable.XK_F24,
|
'F19': 'F19',
|
||||||
'F25': KeyTable.XK_F25,
|
'F20': 'F20',
|
||||||
'F26': KeyTable.XK_F26,
|
'F21': 'F21',
|
||||||
'F27': KeyTable.XK_F27,
|
'F22': 'F22',
|
||||||
'F28': KeyTable.XK_F28,
|
'F23': 'F23',
|
||||||
'F29': KeyTable.XK_F29,
|
'F24': 'F24',
|
||||||
'F30': KeyTable.XK_F30,
|
'F25': 'F25',
|
||||||
'F31': KeyTable.XK_F31,
|
'F26': 'F26',
|
||||||
'F32': KeyTable.XK_F32,
|
'F27': 'F27',
|
||||||
'F33': KeyTable.XK_F33,
|
'F28': 'F28',
|
||||||
'F34': KeyTable.XK_F34,
|
'F29': 'F29',
|
||||||
'F35': KeyTable.XK_F35,
|
'F30': 'F30',
|
||||||
'PrintScreen': KeyTable.XK_Print,
|
'F31': 'F31',
|
||||||
'ScrollLock': KeyTable.XK_Scroll_Lock,
|
'F32': 'F32',
|
||||||
'Pause': KeyTable.XK_Pause,
|
'F33': 'F33',
|
||||||
'BrowserBack': KeyTable.XF86XK_Back,
|
'F34': 'F34',
|
||||||
'BrowserFavorites': KeyTable.XF86XK_Favorites,
|
'F35': 'F35',
|
||||||
'BrowserForward': KeyTable.XF86XK_Forward,
|
'PrintScreen': 'PrintScreen',
|
||||||
'BrowserHome': KeyTable.XF86XK_HomePage,
|
'ScrollLock': 'ScrollLock',
|
||||||
'BrowserRefresh': KeyTable.XF86XK_Refresh,
|
'Pause': 'Pause',
|
||||||
'BrowserSearch': KeyTable.XF86XK_Search,
|
|
||||||
'BrowserStop': KeyTable.XF86XK_Stop,
|
// 3.1.6. Media Keys
|
||||||
'LaunchApp1': KeyTable.XF86XK_Explorer,
|
|
||||||
'LaunchApp2': KeyTable.XF86XK_Calculator,
|
'BrowserBack': 'BrowserBack',
|
||||||
'LaunchMail': KeyTable.XF86XK_Mail,
|
'BrowserFavorites': 'BrowserFavorites',
|
||||||
'MediaPlayPause': KeyTable.XF86XK_AudioPlay,
|
'BrowserForward': 'BrowserForward',
|
||||||
'MediaStop': KeyTable.XF86XK_AudioStop,
|
'BrowserHome': 'BrowserHome',
|
||||||
'MediaTrackNext': KeyTable.XF86XK_AudioNext,
|
'BrowserRefresh': 'BrowserRefresh',
|
||||||
'MediaTrackPrevious': KeyTable.XF86XK_AudioPrev,
|
'BrowserSearch': 'BrowserSearch',
|
||||||
'Power': KeyTable.XF86XK_PowerOff,
|
'BrowserStop': 'BrowserStop',
|
||||||
'Sleep': KeyTable.XF86XK_Sleep,
|
'Eject': 'Eject',
|
||||||
'AudioVolumeDown': KeyTable.XF86XK_AudioLowerVolume,
|
'LaunchApp1': 'LaunchMyComputer',
|
||||||
'AudioVolumeMute': KeyTable.XF86XK_AudioMute,
|
'LaunchApp2': 'LaunchCalendar',
|
||||||
'AudioVolumeUp': KeyTable.XF86XK_AudioRaiseVolume,
|
'LaunchMail': 'LaunchMail',
|
||||||
'WakeUp': KeyTable.XF86XK_WakeUp,
|
'MediaPlayPause': 'MediaPlay',
|
||||||
|
'MediaStop': 'MediaStop',
|
||||||
|
'MediaTrackNext': 'MediaTrackNext',
|
||||||
|
'MediaTrackPrevious': 'MediaTrackPrevious',
|
||||||
|
'Power': 'Power',
|
||||||
|
'Sleep': 'Sleep',
|
||||||
|
'AudioVolumeDown': 'AudioVolumeDown',
|
||||||
|
'AudioVolumeMute': 'AudioVolumeMute',
|
||||||
|
'AudioVolumeUp': 'AudioVolumeUp',
|
||||||
|
'WakeUp': 'WakeUp',
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,6 +12,37 @@ export default {
|
||||||
XK_Escape: 0xff1b,
|
XK_Escape: 0xff1b,
|
||||||
XK_Delete: 0xffff, /* Delete, rubout */
|
XK_Delete: 0xffff, /* Delete, rubout */
|
||||||
|
|
||||||
|
/* International & multi-key character composition */
|
||||||
|
|
||||||
|
XK_Multi_key: 0xff20, /* Multi-key character compose */
|
||||||
|
XK_Codeinput: 0xff37,
|
||||||
|
XK_SingleCandidate: 0xff3c,
|
||||||
|
XK_MultipleCandidate: 0xff3d,
|
||||||
|
XK_PreviousCandidate: 0xff3e,
|
||||||
|
|
||||||
|
/* Japanese keyboard support */
|
||||||
|
|
||||||
|
XK_Kanji: 0xff21, /* Kanji, Kanji convert */
|
||||||
|
XK_Muhenkan: 0xff22, /* Cancel Conversion */
|
||||||
|
XK_Henkan_Mode: 0xff23, /* Start/Stop Conversion */
|
||||||
|
XK_Henkan: 0xff23, /* Alias for Henkan_Mode */
|
||||||
|
XK_Romaji: 0xff24, /* to Romaji */
|
||||||
|
XK_Hiragana: 0xff25, /* to Hiragana */
|
||||||
|
XK_Katakana: 0xff26, /* to Katakana */
|
||||||
|
XK_Hiragana_Katakana: 0xff27, /* Hiragana/Katakana toggle */
|
||||||
|
XK_Zenkaku: 0xff28, /* to Zenkaku */
|
||||||
|
XK_Hankaku: 0xff29, /* to Hankaku */
|
||||||
|
XK_Zenkaku_Hankaku: 0xff2a, /* Zenkaku/Hankaku toggle */
|
||||||
|
XK_Touroku: 0xff2b, /* Add to Dictionary */
|
||||||
|
XK_Massyo: 0xff2c, /* Delete from Dictionary */
|
||||||
|
XK_Kana_Lock: 0xff2d, /* Kana Lock */
|
||||||
|
XK_Kana_Shift: 0xff2e, /* Kana Shift */
|
||||||
|
XK_Eisu_Shift: 0xff2f, /* Alphanumeric Shift */
|
||||||
|
XK_Eisu_toggle: 0xff30, /* Alphanumeric toggle */
|
||||||
|
XK_Kanji_Bangou: 0xff37, /* Codeinput */
|
||||||
|
XK_Zen_Koho: 0xff3d, /* Multiple/All Candidate(s) */
|
||||||
|
XK_Mae_Koho: 0xff3e, /* Previous Candidate */
|
||||||
|
|
||||||
/* Cursor control & motion */
|
/* Cursor control & motion */
|
||||||
|
|
||||||
XK_Home: 0xff50,
|
XK_Home: 0xff50,
|
||||||
|
@ -171,7 +202,17 @@ export default {
|
||||||
XK_Hyper_L: 0xffed, /* Left hyper */
|
XK_Hyper_L: 0xffed, /* Left hyper */
|
||||||
XK_Hyper_R: 0xffee, /* Right hyper */
|
XK_Hyper_R: 0xffee, /* Right hyper */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Keyboard (XKB) Extension function and modifier keys
|
||||||
|
* (from Appendix C of "The X Keyboard Extension: Protocol Specification")
|
||||||
|
* Byte 3 = 0xfe
|
||||||
|
*/
|
||||||
|
|
||||||
XK_ISO_Level3_Shift: 0xfe03, /* AltGr */
|
XK_ISO_Level3_Shift: 0xfe03, /* AltGr */
|
||||||
|
XK_ISO_Next_Group: 0xfe08,
|
||||||
|
XK_ISO_Prev_Group: 0xfe0a,
|
||||||
|
XK_ISO_First_Group: 0xfe0c,
|
||||||
|
XK_ISO_Last_Group: 0xfe0e,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Latin 1
|
* Latin 1
|
||||||
|
@ -378,6 +419,15 @@ export default {
|
||||||
XK_thorn: 0x00fe, /* U+00FE LATIN SMALL LETTER THORN */
|
XK_thorn: 0x00fe, /* U+00FE LATIN SMALL LETTER THORN */
|
||||||
XK_ydiaeresis: 0x00ff, /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */
|
XK_ydiaeresis: 0x00ff, /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Korean
|
||||||
|
* Byte 3 = 0x0e
|
||||||
|
*/
|
||||||
|
|
||||||
|
XK_Hangul: 0xff31, /* Hangul start/stop(toggle) */
|
||||||
|
XK_Hangul_Hanja: 0xff34, /* Start Hangul->Hanja Conversion */
|
||||||
|
XK_Hangul_Jeonja: 0xff38, /* Jeonja mode */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XFree86 vendor specific keysyms.
|
* XFree86 vendor specific keysyms.
|
||||||
*
|
*
|
||||||
|
|
|
@ -2,10 +2,17 @@ import KeyTable from "./keysym.js";
|
||||||
import keysyms from "./keysymdef.js";
|
import keysyms from "./keysymdef.js";
|
||||||
import vkeys from "./vkeys.js";
|
import vkeys from "./vkeys.js";
|
||||||
import fixedkeys from "./fixedkeys.js";
|
import fixedkeys from "./fixedkeys.js";
|
||||||
|
import DOMKeyTable from "./domkeytable.js";
|
||||||
|
|
||||||
function isMac() {
|
function isMac() {
|
||||||
return navigator && !!(/mac/i).exec(navigator.platform);
|
return navigator && !!(/mac/i).exec(navigator.platform);
|
||||||
}
|
}
|
||||||
|
function isIE() {
|
||||||
|
return navigator && !!(/trident/i).exec(navigator.userAgent);
|
||||||
|
}
|
||||||
|
function isEdge() {
|
||||||
|
return navigator && !!(/edge/i).exec(navigator.userAgent);
|
||||||
|
}
|
||||||
|
|
||||||
// Get 'KeyboardEvent.code', handling legacy browsers
|
// Get 'KeyboardEvent.code', handling legacy browsers
|
||||||
export function getKeycode(evt){
|
export function getKeycode(evt){
|
||||||
|
@ -67,88 +74,91 @@ export function getKeycode(evt){
|
||||||
return 'Unidentified';
|
return 'Unidentified';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the most reliable keysym value we can get from a key event
|
// Get 'KeyboardEvent.key', handling legacy browsers
|
||||||
export function getKeysym(evt){
|
export function getKey(evt) {
|
||||||
|
// Are we getting a proper key value?
|
||||||
|
if (evt.key !== undefined) {
|
||||||
|
// IE and Edge use some ancient version of the spec
|
||||||
|
// https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8860571/
|
||||||
|
switch (evt.key) {
|
||||||
|
case 'Spacebar': return ' ';
|
||||||
|
case 'Esc': return 'Escape';
|
||||||
|
case 'Scroll': return 'ScrollLock';
|
||||||
|
case 'Win': return 'Meta';
|
||||||
|
case 'Apps': return 'ContextMenu';
|
||||||
|
case 'Up': return 'ArrowUp';
|
||||||
|
case 'Left': return 'ArrowLeft';
|
||||||
|
case 'Right': return 'ArrowRight';
|
||||||
|
case 'Down': return 'ArrowDown';
|
||||||
|
case 'Del': return 'Delete';
|
||||||
|
case 'Divide': return '/';
|
||||||
|
case 'Multiply': return '*';
|
||||||
|
case 'Subtract': return '-';
|
||||||
|
case 'Add': return '+';
|
||||||
|
case 'Decimal': return evt.char;
|
||||||
|
}
|
||||||
|
|
||||||
// We start with layout independent keys
|
// Mozilla isn't fully in sync with the spec yet
|
||||||
|
switch (evt.key) {
|
||||||
|
case 'OS': return 'Meta';
|
||||||
|
}
|
||||||
|
|
||||||
|
// IE and Edge have broken handling of AltGraph so we cannot
|
||||||
|
// trust them for printable characters
|
||||||
|
if ((evt.key.length !== 1) || (!isIE() && !isEdge())) {
|
||||||
|
return evt.key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to deduce it based on the physical key
|
||||||
var code = getKeycode(evt);
|
var code = getKeycode(evt);
|
||||||
if (code in fixedkeys) {
|
if (code in fixedkeys) {
|
||||||
return fixedkeys[code];
|
return fixedkeys[code];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next with mildly layout or state sensitive stuff
|
// If that failed, then see if we have a printable character
|
||||||
|
if (evt.charCode) {
|
||||||
// Like AltGraph
|
return String.fromCharCode(evt.charCode);
|
||||||
if (code === 'AltRight') {
|
|
||||||
if (evt.key === 'AltGraph') {
|
|
||||||
return KeyTable.XK_ISO_Level3_Shift;
|
|
||||||
} else {
|
|
||||||
return KeyTable.XK_Alt_R;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Or the numpad
|
// At this point we have nothing left to go on
|
||||||
if (evt.location === 3) {
|
return 'Unidentified';
|
||||||
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
|
// Get the most reliable keysym value we can get from a key event
|
||||||
if ((key === undefined) && (evt.charCode)) {
|
export function getKeysym(evt){
|
||||||
key = String.fromCharCode(evt.charCode);
|
var key = getKey(evt);
|
||||||
|
|
||||||
|
if (key === 'Unidentified') {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (key) {
|
// First look up special keys
|
||||||
case '0': return KeyTable.XK_KP_0;
|
if (key in DOMKeyTable) {
|
||||||
case '1': return KeyTable.XK_KP_1;
|
var location = evt.location;
|
||||||
case '2': return KeyTable.XK_KP_2;
|
|
||||||
case '3': return KeyTable.XK_KP_3;
|
// Safari screws up location for the right cmd key
|
||||||
case '4': return KeyTable.XK_KP_4;
|
if ((key === 'Meta') && (location === 0)) {
|
||||||
case '5': return KeyTable.XK_KP_5;
|
location = 2;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((location === undefined) || (location > 3)) {
|
||||||
|
location = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DOMKeyTable[key][location];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we need to look at the Unicode symbol instead
|
// Now we need to look at the Unicode symbol instead
|
||||||
|
|
||||||
var codepoint;
|
var codepoint;
|
||||||
|
|
||||||
if ('key' in evt) {
|
|
||||||
// Special key? (FIXME: Should have been caught earlier)
|
// Special key? (FIXME: Should have been caught earlier)
|
||||||
if (evt.key.length !== 1) {
|
if (key.length !== 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
codepoint = evt.key.charCodeAt();
|
codepoint = key.charCodeAt();
|
||||||
} else if ('charCode' in evt) {
|
|
||||||
codepoint = evt.charCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (codepoint) {
|
if (codepoint) {
|
||||||
return keysyms.lookup(codepoint);
|
return keysyms.lookup(codepoint);
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,39 +98,104 @@ describe('Helpers', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getKeysym', function() {
|
describe('getKey', function() {
|
||||||
it('should prefer key', function() {
|
it('should prefer key', function() {
|
||||||
expect(KeyboardUtil.getKeysym({key: 'a', charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.be.equal(0x61);
|
expect(KeyboardUtil.getKey({key: 'a', charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.be.equal('a');
|
||||||
|
});
|
||||||
|
it('should map legacy values', function() {
|
||||||
|
expect(KeyboardUtil.getKey({key: 'Spacebar'})).to.be.equal(' ');
|
||||||
|
expect(KeyboardUtil.getKey({key: 'Left'})).to.be.equal('ArrowLeft');
|
||||||
|
expect(KeyboardUtil.getKey({key: 'OS'})).to.be.equal('Meta');
|
||||||
|
expect(KeyboardUtil.getKey({key: 'Win'})).to.be.equal('Meta');
|
||||||
|
});
|
||||||
|
it('should use code if no key', function() {
|
||||||
|
expect(KeyboardUtil.getKey({code: 'NumpadBackspace'})).to.be.equal('Backspace');
|
||||||
|
});
|
||||||
|
it('should not use code fallback for character keys', function() {
|
||||||
|
expect(KeyboardUtil.getKey({code: 'KeyA'})).to.be.equal('Unidentified');
|
||||||
|
expect(KeyboardUtil.getKey({code: 'Digit1'})).to.be.equal('Unidentified');
|
||||||
|
expect(KeyboardUtil.getKey({code: 'Period'})).to.be.equal('Unidentified');
|
||||||
|
expect(KeyboardUtil.getKey({code: 'Numpad1'})).to.be.equal('Unidentified');
|
||||||
});
|
});
|
||||||
it('should use charCode if no key', function() {
|
it('should use charCode if no key', function() {
|
||||||
expect(KeyboardUtil.getKeysym({charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.be.equal(0x01a9);
|
expect(KeyboardUtil.getKey({charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.be.equal('Š');
|
||||||
|
});
|
||||||
|
it('should return Unidentified when it cannot map the key', function() {
|
||||||
|
expect(KeyboardUtil.getKey({keycode: 0x42})).to.be.equal('Unidentified');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Broken key AltGraph on IE/Edge', function() {
|
||||||
|
var origNavigator;
|
||||||
|
beforeEach(function () {
|
||||||
|
// window.navigator is a protected read-only property in many
|
||||||
|
// environments, so we need to redefine it whilst running these
|
||||||
|
// tests.
|
||||||
|
origNavigator = Object.getOwnPropertyDescriptor(window, "navigator");
|
||||||
|
if (origNavigator === undefined) {
|
||||||
|
// Object.getOwnPropertyDescriptor() doesn't work
|
||||||
|
// properly in any version of IE
|
||||||
|
this.skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(window, "navigator", {value: {}});
|
||||||
|
if (window.navigator.platform !== undefined) {
|
||||||
|
// Object.defineProperty() doesn't work properly in old
|
||||||
|
// versions of Chrome
|
||||||
|
this.skip();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
afterEach(function () {
|
||||||
|
Object.defineProperty(window, "navigator", origNavigator);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should ignore printable character key on IE', function() {
|
||||||
|
window.navigator.userAgent = "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko";
|
||||||
|
expect(KeyboardUtil.getKey({key: 'a'})).to.be.equal('Unidentified');
|
||||||
|
});
|
||||||
|
it('should ignore printable character key on Edge', function() {
|
||||||
|
window.navigator.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393";
|
||||||
|
expect(KeyboardUtil.getKey({key: 'a'})).to.be.equal('Unidentified');
|
||||||
|
});
|
||||||
|
it('should allow non-printable character key on IE', function() {
|
||||||
|
window.navigator.userAgent = "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko";
|
||||||
|
expect(KeyboardUtil.getKey({key: 'Shift'})).to.be.equal('Shift');
|
||||||
|
});
|
||||||
|
it('should allow non-printable character key on Edge', function() {
|
||||||
|
window.navigator.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393";
|
||||||
|
expect(KeyboardUtil.getKey({key: 'Shift'})).to.be.equal('Shift');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getKeysym', function() {
|
||||||
describe('Non-character keys', function() {
|
describe('Non-character keys', function() {
|
||||||
it('should recognize the right keys', function() {
|
it('should recognize the right keys', function() {
|
||||||
expect(KeyboardUtil.getKeysym({code: 'Enter'})).to.be.equal(0xFF0D);
|
expect(KeyboardUtil.getKeysym({key: 'Enter'})).to.be.equal(0xFF0D);
|
||||||
expect(KeyboardUtil.getKeysym({code: 'Backspace'})).to.be.equal(0xFF08);
|
expect(KeyboardUtil.getKeysym({key: 'Backspace'})).to.be.equal(0xFF08);
|
||||||
expect(KeyboardUtil.getKeysym({code: 'Tab'})).to.be.equal(0xFF09);
|
expect(KeyboardUtil.getKeysym({key: 'Tab'})).to.be.equal(0xFF09);
|
||||||
expect(KeyboardUtil.getKeysym({code: 'ShiftLeft'})).to.be.equal(0xFFE1);
|
expect(KeyboardUtil.getKeysym({key: 'Shift'})).to.be.equal(0xFFE1);
|
||||||
expect(KeyboardUtil.getKeysym({code: 'ControlLeft'})).to.be.equal(0xFFE3);
|
expect(KeyboardUtil.getKeysym({key: 'Control'})).to.be.equal(0xFFE3);
|
||||||
expect(KeyboardUtil.getKeysym({code: 'AltLeft'})).to.be.equal(0xFFE9);
|
expect(KeyboardUtil.getKeysym({key: 'Alt'})).to.be.equal(0xFFE9);
|
||||||
expect(KeyboardUtil.getKeysym({code: 'MetaLeft'})).to.be.equal(0xFFEB);
|
expect(KeyboardUtil.getKeysym({key: 'Meta'})).to.be.equal(0xFFEB);
|
||||||
expect(KeyboardUtil.getKeysym({code: 'Escape'})).to.be.equal(0xFF1B);
|
expect(KeyboardUtil.getKeysym({key: 'Escape'})).to.be.equal(0xFF1B);
|
||||||
expect(KeyboardUtil.getKeysym({code: 'ArrowUp'})).to.be.equal(0xFF52);
|
expect(KeyboardUtil.getKeysym({key: 'ArrowUp'})).to.be.equal(0xFF52);
|
||||||
|
});
|
||||||
|
it('should map left/right side', function() {
|
||||||
|
expect(KeyboardUtil.getKeysym({key: 'Shift', location: 1})).to.be.equal(0xFFE1);
|
||||||
|
expect(KeyboardUtil.getKeysym({key: 'Shift', location: 2})).to.be.equal(0xFFE2);
|
||||||
|
expect(KeyboardUtil.getKeysym({key: 'Control', location: 1})).to.be.equal(0xFFE3);
|
||||||
|
expect(KeyboardUtil.getKeysym({key: 'Control', location: 2})).to.be.equal(0xFFE4);
|
||||||
});
|
});
|
||||||
it('should handle AltGraph', function() {
|
it('should handle AltGraph', function() {
|
||||||
expect(KeyboardUtil.getKeysym({code: 'AltRight', key: 'AltRight'})).to.be.equal(0xFFEA);
|
expect(KeyboardUtil.getKeysym({code: 'AltRight', key: 'Alt', location: 2})).to.be.equal(0xFFEA);
|
||||||
expect(KeyboardUtil.getKeysym({code: 'AltRight', key: 'AltGraph'})).to.be.equal(0xFE03);
|
expect(KeyboardUtil.getKeysym({code: 'AltRight', key: 'AltGraph', location: 2})).to.be.equal(0xFE03);
|
||||||
});
|
});
|
||||||
it('should return null for unknown codes', function() {
|
it('should return null for unknown keys', function() {
|
||||||
expect(KeyboardUtil.getKeysym({code: 'Semicolon'})).to.be.null;
|
expect(KeyboardUtil.getKeysym({key: 'Semicolon'})).to.be.null;
|
||||||
expect(KeyboardUtil.getKeysym({code: 'BracketRight'})).to.be.null;
|
expect(KeyboardUtil.getKeysym({key: 'BracketRight'})).to.be.null;
|
||||||
});
|
});
|
||||||
it('should not recognize character keys', function() {
|
it('should handle remappings', function() {
|
||||||
expect(KeyboardUtil.getKeysym({code: 'KeyA'})).to.be.null;
|
expect(KeyboardUtil.getKeysym({code: 'ControlLeft', key: 'Tab'})).to.be.equal(0xFF09);
|
||||||
expect(KeyboardUtil.getKeysym({code: 'Digit1'})).to.be.null;
|
|
||||||
expect(KeyboardUtil.getKeysym({code: 'Period'})).to.be.null;
|
|
||||||
expect(KeyboardUtil.getKeysym({code: 'Numpad1'})).to.be.null;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -145,10 +210,6 @@ describe('Helpers', function() {
|
||||||
expect(KeyboardUtil.getKeysym({code: 'Delete', key: 'Delete', location: 0})).to.be.equal(0xFFFF);
|
expect(KeyboardUtil.getKeysym({code: 'Delete', key: 'Delete', location: 0})).to.be.equal(0xFFFF);
|
||||||
expect(KeyboardUtil.getKeysym({code: 'NumpadDecimal', key: 'Delete', location: 3})).to.be.equal(0xFF9F);
|
expect(KeyboardUtil.getKeysym({code: 'NumpadDecimal', key: 'Delete', location: 3})).to.be.equal(0xFF9F);
|
||||||
});
|
});
|
||||||
it('should handle IE/Edge key names', function() {
|
|
||||||
expect(KeyboardUtil.getKeysym({code: 'Numpad6', key: 'Right', location: 3})).to.be.equal(0xFF98);
|
|
||||||
expect(KeyboardUtil.getKeysym({code: 'NumpadDecimal', key: 'Del', location: 3})).to.be.equal(0xFF9F);
|
|
||||||
});
|
|
||||||
it('should handle Numpad Decimal key', function() {
|
it('should handle Numpad Decimal key', function() {
|
||||||
expect(KeyboardUtil.getKeysym({code: 'NumpadDecimal', key: '.', location: 3})).to.be.equal(0xFFAE);
|
expect(KeyboardUtil.getKeysym({code: 'NumpadDecimal', key: '.', location: 3})).to.be.equal(0xFFAE);
|
||||||
expect(KeyboardUtil.getKeysym({code: 'NumpadDecimal', key: ',', location: 3})).to.be.equal(0xFFAC);
|
expect(KeyboardUtil.getKeysym({code: 'NumpadDecimal', key: ',', location: 3})).to.be.equal(0xFFAC);
|
||||||
|
|
|
@ -187,8 +187,8 @@ describe('Key Event Handling', function() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
kbd._handleKeyDown(keyevent('keydown', {code: 'AltLeft', key: 'Alt'}));
|
kbd._handleKeyDown(keyevent('keydown', {code: 'AltLeft', key: 'Alt', location: 1}));
|
||||||
kbd._handleKeyDown(keyevent('keydown', {code: 'AltRight', key: 'Alt'}));
|
kbd._handleKeyDown(keyevent('keydown', {code: 'AltRight', key: 'Alt', location: 2}));
|
||||||
expect(count).to.be.equal(2);
|
expect(count).to.be.equal(2);
|
||||||
});
|
});
|
||||||
it('should change left Super to Alt', function(done) {
|
it('should change left Super to Alt', function(done) {
|
||||||
|
@ -198,7 +198,7 @@ describe('Key Event Handling', function() {
|
||||||
expect(code).to.be.equal('MetaLeft');
|
expect(code).to.be.equal('MetaLeft');
|
||||||
done();
|
done();
|
||||||
}});
|
}});
|
||||||
kbd._handleKeyDown(keyevent('keydown', {code: 'MetaLeft', key: 'Meta'}));
|
kbd._handleKeyDown(keyevent('keydown', {code: 'MetaLeft', key: 'Meta', location: 1}));
|
||||||
});
|
});
|
||||||
it('should change right Super to left Super', function(done) {
|
it('should change right Super to left Super', function(done) {
|
||||||
var kbd = new Keyboard({
|
var kbd = new Keyboard({
|
||||||
|
@ -207,7 +207,7 @@ describe('Key Event Handling', function() {
|
||||||
expect(code).to.be.equal('MetaRight');
|
expect(code).to.be.equal('MetaRight');
|
||||||
done();
|
done();
|
||||||
}});
|
}});
|
||||||
kbd._handleKeyDown(keyevent('keydown', {code: 'MetaRight', key: 'Meta'}));
|
kbd._handleKeyDown(keyevent('keydown', {code: 'MetaRight', key: 'Meta', location: 2}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -280,8 +280,8 @@ describe('Key Event Handling', function() {
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
// First the modifier combo
|
// First the modifier combo
|
||||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control'}));
|
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1}));
|
||||||
kbd._handleKeyDown(keyevent('keydown', {code: 'AltRight', key: 'Alt'}));
|
kbd._handleKeyDown(keyevent('keydown', {code: 'AltRight', key: 'Alt', location: 2}));
|
||||||
// Next a normal character
|
// Next a normal character
|
||||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
|
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
|
||||||
expect(times_called).to.be.equal(7);
|
expect(times_called).to.be.equal(7);
|
||||||
|
@ -299,8 +299,8 @@ describe('Key Event Handling', function() {
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
// First the modifier combo
|
// First the modifier combo
|
||||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control'}));
|
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1}));
|
||||||
kbd._handleKeyDown(keyevent('keydown', {code: 'AltRight', key: 'Alt'}));
|
kbd._handleKeyDown(keyevent('keydown', {code: 'AltRight', key: 'Alt', location: 2}));
|
||||||
// Next a normal character
|
// Next a normal character
|
||||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
|
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
|
||||||
kbd._handleKeyUp(keyevent('keyup', {code: 'KeyA', key: 'a'}));
|
kbd._handleKeyUp(keyevent('keyup', {code: 'KeyA', key: 'a'}));
|
||||||
|
@ -329,10 +329,10 @@ describe('Key Event Handling', function() {
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
// First the modifier combo
|
// First the modifier combo
|
||||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control'}));
|
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1}));
|
||||||
kbd._handleKeyDown(keyevent('keydown', {code: 'AltLeft', key: 'Alt'}));
|
kbd._handleKeyDown(keyevent('keydown', {code: 'AltLeft', key: 'Alt', location: 1}));
|
||||||
// Then one of the keys again
|
// Then one of the keys again
|
||||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control'}));
|
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1}));
|
||||||
expect(times_called).to.be.equal(3);
|
expect(times_called).to.be.equal(3);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue