|
| 1 | +import { KeyCode } from './keyCodes'; |
| 2 | + |
| 3 | +class KeyCodeStrMap { |
| 4 | + public _keyCodeToStr: string[]; |
| 5 | + public _strToKeyCode: { [str: string]: KeyCode }; |
| 6 | + |
| 7 | + constructor() { |
| 8 | + this._keyCodeToStr = []; |
| 9 | + this._strToKeyCode = Object.create(null); |
| 10 | + } |
| 11 | + |
| 12 | + define(keyCode: KeyCode, str: string): void { |
| 13 | + this._keyCodeToStr[keyCode] = str; |
| 14 | + this._strToKeyCode[str.toLowerCase()] = keyCode; |
| 15 | + } |
| 16 | + |
| 17 | + keyCodeToStr(keyCode: KeyCode): string { |
| 18 | + return this._keyCodeToStr[keyCode]; |
| 19 | + } |
| 20 | + |
| 21 | + strToKeyCode(str: string): KeyCode { |
| 22 | + return this._strToKeyCode[str.toLowerCase()] || KeyCode.Unknown; |
| 23 | + } |
| 24 | +} |
| 25 | + |
| 26 | +const uiMap = new KeyCodeStrMap(); |
| 27 | +const userSettingsUSMap = new KeyCodeStrMap(); |
| 28 | +const userSettingsGeneralMap = new KeyCodeStrMap(); |
| 29 | + |
| 30 | +export const KeyCodeUtils = { |
| 31 | + toString(keyCode: KeyCode): string { |
| 32 | + return uiMap.keyCodeToStr(keyCode); |
| 33 | + }, |
| 34 | + fromString(key: string): KeyCode { |
| 35 | + return uiMap.strToKeyCode(key); |
| 36 | + }, |
| 37 | + toUserSettingsUS(keyCode: KeyCode): string { |
| 38 | + return userSettingsUSMap.keyCodeToStr(keyCode); |
| 39 | + }, |
| 40 | + toUserSettingsGeneral(keyCode: KeyCode): string { |
| 41 | + return userSettingsGeneralMap.keyCodeToStr(keyCode); |
| 42 | + }, |
| 43 | + fromUserSettings(key: string): KeyCode { |
| 44 | + return userSettingsUSMap.strToKeyCode(key) || userSettingsGeneralMap.strToKeyCode(key); |
| 45 | + }, |
| 46 | +}; |
| 47 | + |
| 48 | +export const EVENT_CODE_TO_KEY_CODE_MAP: { [keyCode: string]: KeyCode } = {}; |
| 49 | + |
| 50 | +(function () { |
| 51 | + // See https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx |
| 52 | + // see https://www.toptal.com/developers/keycode/table |
| 53 | + |
| 54 | + const empty = ''; |
| 55 | + type IMappingEntry = [string, KeyCode, string, string, string]; |
| 56 | + |
| 57 | + const mappings: IMappingEntry[] = [ |
| 58 | + // scanCode, keyCode, keyCodeStr, usUserSettingsLabel, generalUserSettingsLabel |
| 59 | + ['Unidentified', KeyCode.Unknown, 'unknown', empty, empty], |
| 60 | + ['KeyA', KeyCode.KeyA, 'A', empty, empty], |
| 61 | + ['KeyB', KeyCode.KeyB, 'B', empty, empty], |
| 62 | + ['KeyC', KeyCode.KeyC, 'C', empty, empty], |
| 63 | + ['KeyD', KeyCode.KeyD, 'D', empty, empty], |
| 64 | + ['KeyE', KeyCode.KeyE, 'E', empty, empty], |
| 65 | + ['KeyF', KeyCode.KeyF, 'F', empty, empty], |
| 66 | + ['KeyG', KeyCode.KeyG, 'G', empty, empty], |
| 67 | + ['KeyH', KeyCode.KeyH, 'H', empty, empty], |
| 68 | + ['KeyI', KeyCode.KeyI, 'I', empty, empty], |
| 69 | + ['KeyJ', KeyCode.KeyJ, 'J', empty, empty], |
| 70 | + ['KeyK', KeyCode.KeyK, 'K', empty, empty], |
| 71 | + ['KeyL', KeyCode.KeyL, 'L', empty, empty], |
| 72 | + ['KeyM', KeyCode.KeyM, 'M', empty, empty], |
| 73 | + ['KeyN', KeyCode.KeyN, 'N', empty, empty], |
| 74 | + ['KeyO', KeyCode.KeyO, 'O', empty, empty], |
| 75 | + ['KeyP', KeyCode.KeyP, 'P', empty, empty], |
| 76 | + ['KeyQ', KeyCode.KeyQ, 'Q', empty, empty], |
| 77 | + ['KeyR', KeyCode.KeyR, 'R', empty, empty], |
| 78 | + ['KeyS', KeyCode.KeyS, 'S', empty, empty], |
| 79 | + ['KeyT', KeyCode.KeyT, 'T', empty, empty], |
| 80 | + ['KeyU', KeyCode.KeyU, 'U', empty, empty], |
| 81 | + ['KeyV', KeyCode.KeyV, 'V', empty, empty], |
| 82 | + ['KeyW', KeyCode.KeyW, 'W', empty, empty], |
| 83 | + ['KeyX', KeyCode.KeyX, 'X', empty, empty], |
| 84 | + ['KeyY', KeyCode.KeyY, 'Y', empty, empty], |
| 85 | + ['KeyZ', KeyCode.KeyZ, 'Z', empty, empty], |
| 86 | + ['Digit1', KeyCode.Digit1, '1', empty, empty], |
| 87 | + ['Digit2', KeyCode.Digit2, '2', empty, empty], |
| 88 | + ['Digit3', KeyCode.Digit3, '3', empty, empty], |
| 89 | + ['Digit4', KeyCode.Digit4, '4', empty, empty], |
| 90 | + ['Digit5', KeyCode.Digit5, '5', empty, empty], |
| 91 | + ['Digit6', KeyCode.Digit6, '6', empty, empty], |
| 92 | + ['Digit7', KeyCode.Digit7, '7', empty, empty], |
| 93 | + ['Digit8', KeyCode.Digit8, '8', empty, empty], |
| 94 | + ['Digit9', KeyCode.Digit9, '9', empty, empty], |
| 95 | + ['Digit0', KeyCode.Digit0, '0', empty, empty], |
| 96 | + ['Enter', KeyCode.Enter, 'Enter', empty, empty], |
| 97 | + ['Escape', KeyCode.Escape, 'Escape', empty, empty], |
| 98 | + ['Backspace', KeyCode.Backspace, 'Backspace', empty, empty], |
| 99 | + ['Tab', KeyCode.Tab, 'Tab', empty, empty], |
| 100 | + ['Space', KeyCode.Space, 'Space', empty, empty], |
| 101 | + ['Minus', KeyCode.Minus, '-', '-', 'OEM_MINUS'], |
| 102 | + ['Equal', KeyCode.Equal, '=', '=', 'OEM_PLUS'], |
| 103 | + ['BracketLeft', KeyCode.BracketLeft, '[', '[', 'OEM_4'], |
| 104 | + ['BracketRight', KeyCode.BracketRight, ']', ']', 'OEM_6'], |
| 105 | + ['Backslash', KeyCode.Backslash, '\\', '\\', 'OEM_5'], |
| 106 | + ['Semicolon', KeyCode.Semicolon, ';', ';', 'OEM_1'], |
| 107 | + ['Quote', KeyCode.Quote, `'`, `'`, 'OEM_7'], |
| 108 | + ['Backquote', KeyCode.Backquote, '`', '`', 'OEM_3'], |
| 109 | + ['Comma', KeyCode.Comma, ',', ',', 'OEM_COMMA'], |
| 110 | + ['Period', KeyCode.Period, '.', '.', 'OEM_PERIOD'], |
| 111 | + ['Slash', KeyCode.Slash, '/', '/', 'OEM_2'], |
| 112 | + ['CapsLock', KeyCode.CapsLock, 'CapsLock', empty, empty], |
| 113 | + ['F1', KeyCode.F1, 'F1', empty, empty], |
| 114 | + ['F2', KeyCode.F2, 'F2', empty, empty], |
| 115 | + ['F3', KeyCode.F3, 'F3', empty, empty], |
| 116 | + ['F4', KeyCode.F4, 'F4', empty, empty], |
| 117 | + ['F5', KeyCode.F5, 'F5', empty, empty], |
| 118 | + ['F6', KeyCode.F6, 'F6', empty, empty], |
| 119 | + ['F7', KeyCode.F7, 'F7', empty, empty], |
| 120 | + ['F8', KeyCode.F8, 'F8', empty, empty], |
| 121 | + ['F9', KeyCode.F9, 'F9', empty, empty], |
| 122 | + ['F10', KeyCode.F10, 'F10', empty, empty], |
| 123 | + ['F11', KeyCode.F11, 'F11', empty, empty], |
| 124 | + ['F12', KeyCode.F12, 'F12', empty, empty], |
| 125 | + ['PrintScreen', KeyCode.Unknown, empty, empty, empty], |
| 126 | + ['ScrollLock', KeyCode.ScrollLock, 'ScrollLock', empty, empty], |
| 127 | + ['Pause', KeyCode.PauseBreak, 'PauseBreak', empty, empty], |
| 128 | + ['Insert', KeyCode.Insert, 'Insert', empty, empty], |
| 129 | + ['Home', KeyCode.Home, 'Home', empty, empty], |
| 130 | + ['PageUp', KeyCode.PageUp, 'PageUp', empty, empty], |
| 131 | + ['Delete', KeyCode.Delete, 'Delete', empty, empty], |
| 132 | + ['End', KeyCode.End, 'End', empty, empty], |
| 133 | + ['PageDown', KeyCode.PageDown, 'PageDown', empty, empty], |
| 134 | + ['ArrowRight', KeyCode.RightArrow, 'RightArrow', 'Right', empty], |
| 135 | + ['ArrowLeft', KeyCode.LeftArrow, 'LeftArrow', 'Left', empty], |
| 136 | + ['ArrowDown', KeyCode.DownArrow, 'DownArrow', 'Down', empty], |
| 137 | + ['ArrowUp', KeyCode.UpArrow, 'UpArrow', 'Up', empty], |
| 138 | + ['NumLock', KeyCode.NumLock, 'NumLock', empty, empty], |
| 139 | + ['NumpadDivide', KeyCode.NumpadDivide, 'NumPad_Divide', empty, empty], |
| 140 | + ['NumpadMultiply', KeyCode.NumpadMultiply, 'NumPad_Multiply', empty, empty], |
| 141 | + ['NumpadSubtract', KeyCode.NumpadSubtract, 'NumPad_Subtract', empty, empty], |
| 142 | + ['NumpadAdd', KeyCode.NumpadAdd, 'NumPad_Add', empty, empty], |
| 143 | + ['NumpadEnter', KeyCode.Enter, empty, empty, empty], |
| 144 | + ['Numpad1', KeyCode.Numpad1, 'NumPad1', empty, empty], |
| 145 | + ['Numpad2', KeyCode.Numpad2, 'NumPad2', empty, empty], |
| 146 | + ['Numpad3', KeyCode.Numpad3, 'NumPad3', empty, empty], |
| 147 | + ['Numpad4', KeyCode.Numpad4, 'NumPad4', empty, empty], |
| 148 | + ['Numpad5', KeyCode.Numpad5, 'NumPad5', empty, empty], |
| 149 | + ['Numpad6', KeyCode.Numpad6, 'NumPad6', empty, empty], |
| 150 | + ['Numpad7', KeyCode.Numpad7, 'NumPad7', empty, empty], |
| 151 | + ['Numpad8', KeyCode.Numpad8, 'NumPad8', empty, empty], |
| 152 | + ['Numpad9', KeyCode.Numpad9, 'NumPad9', empty, empty], |
| 153 | + ['Numpad0', KeyCode.Numpad0, 'NumPad0', empty, empty], |
| 154 | + ['NumpadDecimal', KeyCode.NumpadDecimal, 'NumPad_Decimal', empty, empty], |
| 155 | + ['IntlBackslash', KeyCode.IntlBackslash, 'OEM_102', empty, empty], |
| 156 | + ['ContextMenu', KeyCode.ContextMenu, 'ContextMenu', empty, empty], |
| 157 | + ['Power', KeyCode.Unknown, empty, empty, empty], |
| 158 | + ['NumpadEqual', KeyCode.Unknown, empty, empty, empty], |
| 159 | + ['F13', KeyCode.F13, 'F13', empty, empty], |
| 160 | + ['F14', KeyCode.F14, 'F14', empty, empty], |
| 161 | + ['F15', KeyCode.F15, 'F15', empty, empty], |
| 162 | + ['F16', KeyCode.F16, 'F16', empty, empty], |
| 163 | + ['F17', KeyCode.F17, 'F17', empty, empty], |
| 164 | + ['F18', KeyCode.F18, 'F18', empty, empty], |
| 165 | + ['F19', KeyCode.F19, 'F19', empty, empty], |
| 166 | + ['F20', KeyCode.F20, 'F20', empty, empty], |
| 167 | + ['F21', KeyCode.F21, 'F21', empty, empty], |
| 168 | + ['F22', KeyCode.F22, 'F22', empty, empty], |
| 169 | + ['F23', KeyCode.F23, 'F23', empty, empty], |
| 170 | + ['F24', KeyCode.F24, 'F24', empty, empty], |
| 171 | + ['AudioVolumeMute', KeyCode.AudioVolumeMute, 'AudioVolumeMute', empty, empty], |
| 172 | + ['AudioVolumeUp', KeyCode.AudioVolumeUp, 'AudioVolumeUp', empty, empty], |
| 173 | + ['AudioVolumeDown', KeyCode.AudioVolumeDown, 'AudioVolumeDown', empty, empty], |
| 174 | + ['NumpadComma', KeyCode.NUMPAD_SEPARATOR, 'NumPad_Separator', empty, empty], |
| 175 | + ['IntlRo', KeyCode.ABNT_C1, 'ABNT_C1', empty, empty], |
| 176 | + ['NumpadClear', KeyCode.Clear, 'Clear', empty, empty], |
| 177 | + [empty, KeyCode.Ctrl, 'Ctrl', empty, empty], |
| 178 | + [empty, KeyCode.Shift, 'Shift', empty, empty], |
| 179 | + [empty, KeyCode.Alt, 'Alt', empty, empty], |
| 180 | + [empty, KeyCode.Meta, 'Meta', empty, empty], |
| 181 | + ['ControlLeft', KeyCode.Ctrl, empty, empty, empty], |
| 182 | + ['ShiftLeft', KeyCode.Shift, empty, empty, empty], |
| 183 | + ['AltLeft', KeyCode.Alt, empty, empty, empty], |
| 184 | + ['MetaLeft', KeyCode.Meta, empty, empty, empty], |
| 185 | + ['ControlRight', KeyCode.Ctrl, empty, empty, empty], |
| 186 | + ['ShiftRight', KeyCode.Shift, empty, empty, empty], |
| 187 | + ['AltRight', KeyCode.Alt, empty, empty, empty], |
| 188 | + ['MetaRight', KeyCode.Meta, empty, empty, empty], |
| 189 | + ['MediaTrackNext', KeyCode.MediaTrackNext, 'MediaTrackNext', empty, empty], |
| 190 | + ['MediaTrackPrevious', KeyCode.MediaTrackPrevious, 'MediaTrackPrevious', empty, empty], |
| 191 | + ['MediaStop', KeyCode.MediaStop, 'MediaStop', empty, empty], |
| 192 | + ['MediaPlayPause', KeyCode.MediaPlayPause, 'MediaPlayPause', empty, empty], |
| 193 | + ['MediaSelect', KeyCode.LaunchMediaPlayer, 'LaunchMediaPlayer', empty, empty], |
| 194 | + ['LaunchMail', KeyCode.LaunchMail, 'LaunchMail', empty, empty], |
| 195 | + ['LaunchApp2', KeyCode.LaunchApp2, 'LaunchApp2', empty, empty], |
| 196 | + ['LaunchScreenSaver', KeyCode.Unknown, empty, empty, empty], |
| 197 | + ['BrowserSearch', KeyCode.BrowserSearch, 'BrowserSearch', empty, empty], |
| 198 | + ['BrowserHome', KeyCode.BrowserHome, 'BrowserHome', empty, empty], |
| 199 | + ['BrowserBack', KeyCode.BrowserBack, 'BrowserBack', empty, empty], |
| 200 | + ['BrowserForward', KeyCode.BrowserForward, 'BrowserForward', empty, empty], |
| 201 | + |
| 202 | + // See https://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html |
| 203 | + // If an Input Method Editor is processing key input and the event is keydown, return 229. |
| 204 | + [empty, KeyCode.KEY_IN_COMPOSITION, 'KeyInComposition', empty, empty], |
| 205 | + [empty, KeyCode.ABNT_C2, 'ABNT_C2', empty, empty], |
| 206 | + [empty, KeyCode.OEM_8, 'OEM_8', empty, empty], |
| 207 | + ]; |
| 208 | + |
| 209 | + const seenKeyCode: boolean[] = []; |
| 210 | + |
| 211 | + for (const mapping of mappings) { |
| 212 | + const [scanCode, keyCode, keyCodeStr, usUserSettingsLabel, generalUserSettingsLabel] = mapping; |
| 213 | + |
| 214 | + if (!seenKeyCode[keyCode]) { |
| 215 | + seenKeyCode[keyCode] = true; |
| 216 | + if (!keyCodeStr) { |
| 217 | + throw new Error(`String representation missing for key code ${keyCode} around scan code ${scanCode}`); |
| 218 | + } |
| 219 | + uiMap.define(keyCode, keyCodeStr); |
| 220 | + userSettingsUSMap.define(keyCode, usUserSettingsLabel || keyCodeStr); |
| 221 | + userSettingsGeneralMap.define(keyCode, generalUserSettingsLabel || usUserSettingsLabel || keyCodeStr); |
| 222 | + } |
| 223 | + |
| 224 | + if (scanCode) { |
| 225 | + EVENT_CODE_TO_KEY_CODE_MAP[scanCode] = keyCode; |
| 226 | + } |
| 227 | + } |
| 228 | + |
| 229 | + console.log( |
| 230 | + '%c [ IMMUTABLE_KEY_CODE_TO_CODE ]-500', |
| 231 | + 'font-size:13px; background:pink; color:#bf2c9f;', |
| 232 | + uiMap, |
| 233 | + userSettingsUSMap, |
| 234 | + userSettingsGeneralMap, |
| 235 | + EVENT_CODE_TO_KEY_CODE_MAP, |
| 236 | + ); |
| 237 | +})(); |
| 238 | + |
| 239 | +export function KeyChord(firstPart: number, secondPart: number): number { |
| 240 | + const chordPart = ((secondPart & 0x0000ffff) << 16) >>> 0; |
| 241 | + return (firstPart | chordPart) >>> 0; |
| 242 | +} |
0 commit comments