Browse Source
* Physical key handling for Windows * Physical key handling for macOS * Physical key handling for X11 * Physical keys: cleanup unused keys * Key symbols: ensure consistent behavior between platforms * Fix dead key symbol for Windows * Physical key handling for browser * Physical keys: use new overloads where possible * Key symbol for VNC * Physical key handling in previewer * Key symbol for forwarded X11 IME key * Key symbol for Android * Obsolete old RawKeyEventArgs ctor * Fix key symbols for macOS with modifiers * Adjust PhysicalKey members naming * Use explicit std::hash for AvnKey/AvnPhysicalKey Should hopefully satisfy the older compiler on the CI server * Headless: added KeyPressQwerty --------- Co-authored-by: Dan Walmsley <dan@walms.co.uk> Co-authored-by: Steven Kirk <grokys@users.noreply.github.com>pull/12996/head
committed by
GitHub
40 changed files with 4078 additions and 1584 deletions
@ -1,14 +1,15 @@ |
|||
#ifndef keytransform_h |
|||
#define keytransform_h |
|||
|
|||
#import <cstdint> |
|||
#include "common.h" |
|||
#include <map> |
|||
|
|||
extern std::map<int, AvnKey> s_KeyMap; |
|||
AvnPhysicalKey PhysicalKeyFromScanCode(uint16_t scanCode); |
|||
|
|||
extern std::map<AvnKey, int> s_AvnKeyMap; |
|||
AvnKey VirtualKeyFromScanCode(uint16_t scanCode, NSEventModifierFlags modifierFlags); |
|||
|
|||
extern std::map<int, const char*> s_QwertyKeyMap; |
|||
NSString* KeySymbolFromScanCode(uint16_t scanCode, NSEventModifierFlags modifierFlags); |
|||
|
|||
extern std::map<AvnKey, int> s_UnicodeKeyMap; |
|||
uint16_t MenuCharFromVirtualKey(AvnKey key); |
|||
|
|||
#endif |
|||
|
|||
@ -1,391 +1,511 @@ |
|||
#include "KeyTransform.h" |
|||
|
|||
const int kVK_ANSI_A = 0x00; |
|||
const int kVK_ANSI_S = 0x01; |
|||
const int kVK_ANSI_D = 0x02; |
|||
const int kVK_ANSI_F = 0x03; |
|||
const int kVK_ANSI_H = 0x04; |
|||
const int kVK_ANSI_G = 0x05; |
|||
const int kVK_ANSI_Z = 0x06; |
|||
const int kVK_ANSI_X = 0x07; |
|||
const int kVK_ANSI_C = 0x08; |
|||
const int kVK_ANSI_V = 0x09; |
|||
const int kVK_ANSI_B = 0x0B; |
|||
const int kVK_ANSI_Q = 0x0C; |
|||
const int kVK_ANSI_W = 0x0D; |
|||
const int kVK_ANSI_E = 0x0E; |
|||
const int kVK_ANSI_R = 0x0F; |
|||
const int kVK_ANSI_Y = 0x10; |
|||
const int kVK_ANSI_T = 0x11; |
|||
const int kVK_ANSI_1 = 0x12; |
|||
const int kVK_ANSI_2 = 0x13; |
|||
const int kVK_ANSI_3 = 0x14; |
|||
const int kVK_ANSI_4 = 0x15; |
|||
const int kVK_ANSI_6 = 0x16; |
|||
const int kVK_ANSI_5 = 0x17; |
|||
const int kVK_ANSI_Equal = 0x18; |
|||
const int kVK_ANSI_9 = 0x19; |
|||
const int kVK_ANSI_7 = 0x1A; |
|||
const int kVK_ANSI_Minus = 0x1B; |
|||
const int kVK_ANSI_8 = 0x1C; |
|||
const int kVK_ANSI_0 = 0x1D; |
|||
const int kVK_ANSI_RightBracket = 0x1E; |
|||
const int kVK_ANSI_O = 0x1F; |
|||
const int kVK_ANSI_U = 0x20; |
|||
const int kVK_ANSI_LeftBracket = 0x21; |
|||
const int kVK_ANSI_I = 0x22; |
|||
const int kVK_ANSI_P = 0x23; |
|||
const int kVK_ANSI_L = 0x25; |
|||
const int kVK_ANSI_J = 0x26; |
|||
const int kVK_ANSI_Quote = 0x27; |
|||
const int kVK_ANSI_K = 0x28; |
|||
const int kVK_ANSI_Semicolon = 0x29; |
|||
const int kVK_ANSI_Backslash = 0x2A; |
|||
const int kVK_ANSI_Comma = 0x2B; |
|||
const int kVK_ANSI_Slash = 0x2C; |
|||
const int kVK_ANSI_N = 0x2D; |
|||
const int kVK_ANSI_M = 0x2E; |
|||
const int kVK_ANSI_Period = 0x2F; |
|||
const int kVK_ANSI_Grave = 0x32; |
|||
const int kVK_ANSI_KeypadDecimal = 0x41; |
|||
const int kVK_ANSI_KeypadMultiply = 0x43; |
|||
const int kVK_ANSI_KeypadPlus = 0x45; |
|||
const int kVK_ANSI_KeypadClear = 0x47; |
|||
const int kVK_ANSI_KeypadDivide = 0x4B; |
|||
const int kVK_ANSI_KeypadEnter = 0x4C; |
|||
const int kVK_ANSI_KeypadMinus = 0x4E; |
|||
const int kVK_ANSI_KeypadEquals = 0x51; |
|||
const int kVK_ANSI_Keypad0 = 0x52; |
|||
const int kVK_ANSI_Keypad1 = 0x53; |
|||
const int kVK_ANSI_Keypad2 = 0x54; |
|||
const int kVK_ANSI_Keypad3 = 0x55; |
|||
const int kVK_ANSI_Keypad4 = 0x56; |
|||
const int kVK_ANSI_Keypad5 = 0x57; |
|||
const int kVK_ANSI_Keypad6 = 0x58; |
|||
const int kVK_ANSI_Keypad7 = 0x59; |
|||
const int kVK_ANSI_Keypad8 = 0x5B; |
|||
const int kVK_ANSI_Keypad9 = 0x5C; |
|||
const int kVK_Return = 0x24; |
|||
const int kVK_Tab = 0x30; |
|||
const int kVK_Space = 0x31; |
|||
const int kVK_Delete = 0x33; |
|||
const int kVK_Escape = 0x35; |
|||
const int kVK_Command = 0x37; |
|||
const int kVK_Shift = 0x38; |
|||
const int kVK_CapsLock = 0x39; |
|||
const int kVK_Option = 0x3A; |
|||
const int kVK_Control = 0x3B; |
|||
const int kVK_RightCommand = 0x36; |
|||
const int kVK_RightShift = 0x3C; |
|||
const int kVK_RightOption = 0x3D; |
|||
const int kVK_RightControl = 0x3E; |
|||
//const int kVK_Function = 0x3F; |
|||
const int kVK_F17 = 0x40; |
|||
const int kVK_VolumeUp = 0x48; |
|||
const int kVK_VolumeDown = 0x49; |
|||
const int kVK_Mute = 0x4A; |
|||
const int kVK_F18 = 0x4F; |
|||
const int kVK_F19 = 0x50; |
|||
const int kVK_F20 = 0x5A; |
|||
const int kVK_F5 = 0x60; |
|||
const int kVK_F6 = 0x61; |
|||
const int kVK_F7 = 0x62; |
|||
const int kVK_F3 = 0x63; |
|||
const int kVK_F8 = 0x64; |
|||
const int kVK_F9 = 0x65; |
|||
const int kVK_F11 = 0x67; |
|||
const int kVK_F13 = 0x69; |
|||
const int kVK_F16 = 0x6A; |
|||
const int kVK_F14 = 0x6B; |
|||
const int kVK_F10 = 0x6D; |
|||
const int kVK_F12 = 0x6F; |
|||
const int kVK_F15 = 0x71; |
|||
const int kVK_Help = 0x72; |
|||
const int kVK_Home = 0x73; |
|||
const int kVK_PageUp = 0x74; |
|||
const int kVK_ForwardDelete = 0x75; |
|||
const int kVK_F4 = 0x76; |
|||
const int kVK_End = 0x77; |
|||
const int kVK_F2 = 0x78; |
|||
const int kVK_PageDown = 0x79; |
|||
const int kVK_F1 = 0x7A; |
|||
const int kVK_LeftArrow = 0x7B; |
|||
const int kVK_RightArrow = 0x7C; |
|||
const int kVK_DownArrow = 0x7D; |
|||
const int kVK_UpArrow = 0x7E; |
|||
//const int kVK_ISO_Section = 0x0A; |
|||
//const int kVK_JIS_Yen = 0x5D; |
|||
//const int kVK_JIS_Underscore = 0x5E; |
|||
//const int kVK_JIS_KeypadComma = 0x5F; |
|||
//const int kVK_JIS_Eisu = 0x66; |
|||
const int kVK_JIS_Kana = 0x68; |
|||
|
|||
// converts from AvaloniaKeys to UnicodeSpecial keys. |
|||
std::map<AvnKey, int> s_UnicodeKeyMap = |
|||
#import <Carbon/Carbon.h> |
|||
#include <array> |
|||
#include <unordered_map> |
|||
|
|||
struct KeyInfo |
|||
{ |
|||
{ Up, NSUpArrowFunctionKey }, |
|||
{ Down, NSDownArrowFunctionKey }, |
|||
{ Left, NSLeftArrowFunctionKey }, |
|||
{ Right, NSRightArrowFunctionKey }, |
|||
{ F1, NSF1FunctionKey }, |
|||
{ F2, NSF2FunctionKey }, |
|||
{ F3, NSF3FunctionKey }, |
|||
{ F4, NSF4FunctionKey }, |
|||
{ F5, NSF5FunctionKey }, |
|||
{ F6, NSF6FunctionKey }, |
|||
{ F7, NSF7FunctionKey }, |
|||
{ F8, NSF8FunctionKey }, |
|||
{ F9, NSF9FunctionKey }, |
|||
{ F10, NSF10FunctionKey }, |
|||
{ F11, NSF11FunctionKey }, |
|||
{ F12, NSF12FunctionKey }, |
|||
{ F13, NSF13FunctionKey }, |
|||
{ F14, NSF14FunctionKey }, |
|||
{ F15, NSF15FunctionKey }, |
|||
{ F16, NSF16FunctionKey }, |
|||
{ F17, NSF17FunctionKey }, |
|||
{ F18, NSF18FunctionKey }, |
|||
{ F19, NSF19FunctionKey }, |
|||
{ F20, NSF20FunctionKey }, |
|||
{ F21, NSF21FunctionKey }, |
|||
{ F22, NSF22FunctionKey }, |
|||
{ F23, NSF23FunctionKey }, |
|||
{ F24, NSF24FunctionKey }, |
|||
{ Insert, NSInsertFunctionKey }, |
|||
{ Delete, NSDeleteFunctionKey }, |
|||
{ Home, NSHomeFunctionKey }, |
|||
//{ Begin, NSBeginFunctionKey }, |
|||
{ End, NSEndFunctionKey }, |
|||
{ PageUp, NSPageUpFunctionKey }, |
|||
{ PageDown, NSPageDownFunctionKey }, |
|||
{ PrintScreen, NSPrintScreenFunctionKey }, |
|||
{ Scroll, NSScrollLockFunctionKey }, |
|||
//{ SysReq, NSSysReqFunctionKey }, |
|||
//{ Break, NSBreakFunctionKey }, |
|||
//{ Reset, NSResetFunctionKey }, |
|||
//{ Stop, NSStopFunctionKey }, |
|||
//{ Menu, NSMenuFunctionKey }, |
|||
//{ UserFunction, NSUserFunctionKey }, |
|||
//{ SystemFunction, NSSystemFunctionKey }, |
|||
{ Print, NSPrintFunctionKey }, |
|||
//{ ClearLine, NSClearLineFunctionKey }, |
|||
//{ ClearDisplay, NSClearDisplayFunctionKey }, |
|||
uint16_t scanCode; |
|||
AvnPhysicalKey physicalKey; |
|||
AvnKey qwertyKey; |
|||
uint16_t menuChar; |
|||
}; |
|||
|
|||
// Converts from Ansi virtual keys to Qwerty Keyboard map. |
|||
std::map<int, const char*> s_QwertyKeyMap = |
|||
// ScanCode - PhysicalKey - Key mapping (the virtual key is mapped as in a standard QWERTY keyboard) |
|||
// https://github.com/chromium/chromium/blob/main/ui/events/keycodes/dom/dom_code_data.inc |
|||
// This list has the same order as the PhysicalKey enum. |
|||
const KeyInfo keyInfos[] = |
|||
{ |
|||
{ 0, "a" }, |
|||
{ 1, "s" }, |
|||
{ 2, "d" }, |
|||
{ 3, "f" }, |
|||
{ 4, "h" }, |
|||
{ 5, "g" }, |
|||
{ 6, "z" }, |
|||
{ 7, "x" }, |
|||
{ 8, "c" }, |
|||
{ 9, "v" }, |
|||
{ 10, "§" }, |
|||
{ 11, "b" }, |
|||
{ 12, "q" }, |
|||
{ 13, "w" }, |
|||
{ 14, "e" }, |
|||
{ 15, "r" }, |
|||
{ 16, "y" }, |
|||
{ 17, "t" }, |
|||
{ 18, "1" }, |
|||
{ 19, "2" }, |
|||
{ 20, "3" }, |
|||
{ 21, "4" }, |
|||
{ 22, "6" }, |
|||
{ 23, "5" }, |
|||
{ 24, "=" }, |
|||
{ 25, "9" }, |
|||
{ 26, "7" }, |
|||
{ 27, "-" }, |
|||
{ 28, "8" }, |
|||
{ 29, "0" }, |
|||
{ 30, "]" }, |
|||
{ 31, "o" }, |
|||
{ 32, "u" }, |
|||
{ 33, "[" }, |
|||
{ 34, "i" }, |
|||
{ 35, "p" }, |
|||
{ 37, "l" }, |
|||
{ 38, "j" }, |
|||
{ 39, "'" }, |
|||
{ 40, "k" }, |
|||
{ 41, ";" }, |
|||
{ 42, "\\" }, |
|||
{ 43, "," }, |
|||
{ 44, "/" }, |
|||
{ 45, "n" }, |
|||
{ 46, "m" }, |
|||
{ 47, "." }, |
|||
{ 48, "\t" }, |
|||
{ 49, " " }, |
|||
{ 50, "`" }, |
|||
{ 51, "" }, |
|||
{ 52, "" }, |
|||
{ 53, "" }, |
|||
{ 65, "." }, |
|||
{ 66, "" }, |
|||
{ 67, "*" }, |
|||
{ 69, "+" }, |
|||
{ 70, "" }, |
|||
{ 71, "" }, |
|||
{ 72, "" }, |
|||
{ 75, "/" }, |
|||
{ 76, "" }, |
|||
{ 77, "" }, |
|||
{ 78, "-" }, |
|||
{ 81, "=" }, |
|||
{ 82, "0" }, |
|||
{ 83, "1" }, |
|||
{ 84, "2" }, |
|||
{ 85, "3" }, |
|||
{ 86, "4" }, |
|||
{ 87, "5" }, |
|||
{ 88, "6" }, |
|||
{ 89, "7" }, |
|||
{ 91, "8" }, |
|||
{ 92, "9" } |
|||
// Writing System Keys |
|||
{ 0x32, AvnPhysicalKeyBackquote, AvnKeyOem3, '`' }, |
|||
{ 0x2A, AvnPhysicalKeyBackslash, AvnKeyOem5, '\\' }, |
|||
{ 0x21, AvnPhysicalKeyBracketLeft,AvnKeyOem4, '[' }, |
|||
{ 0x1E, AvnPhysicalKeyBracketRight, AvnKeyOem6, ']' }, |
|||
{ 0x2B, AvnPhysicalKeyComma, AvnKeyOemComma, ',' }, |
|||
{ 0x1D, AvnPhysicalKeyDigit0, AvnKeyD0, '0' }, |
|||
{ 0x12, AvnPhysicalKeyDigit1, AvnKeyD1, '1' }, |
|||
{ 0x13, AvnPhysicalKeyDigit2, AvnKeyD2, '2' }, |
|||
{ 0x14, AvnPhysicalKeyDigit3, AvnKeyD3, '3' }, |
|||
{ 0x15, AvnPhysicalKeyDigit4, AvnKeyD4, '4' }, |
|||
{ 0x17, AvnPhysicalKeyDigit5, AvnKeyD5, '5' }, |
|||
{ 0x16, AvnPhysicalKeyDigit6, AvnKeyD6, '6' }, |
|||
{ 0x1A, AvnPhysicalKeyDigit7, AvnKeyD7, '7' }, |
|||
{ 0x1C, AvnPhysicalKeyDigit8, AvnKeyD8, '8' }, |
|||
{ 0x19, AvnPhysicalKeyDigit9, AvnKeyD9, '9' }, |
|||
{ 0x18, AvnPhysicalKeyEqual, AvnKeyOemMinus, '-' }, |
|||
{ 0x0A, AvnPhysicalKeyIntlBackslash, AvnKeyOem102, 0 }, |
|||
{ 0x5E, AvnPhysicalKeyIntlRo, AvnKeyOem102, 0 }, |
|||
{ 0x5D, AvnPhysicalKeyIntlYen, AvnKeyOem5, 0 }, |
|||
{ 0x00, AvnPhysicalKeyA, AvnKeyA, 'a' }, |
|||
{ 0x0B, AvnPhysicalKeyB, AvnKeyB, 'b' }, |
|||
{ 0x08, AvnPhysicalKeyC, AvnKeyC, 'c' }, |
|||
{ 0x02, AvnPhysicalKeyD, AvnKeyD, 'd' }, |
|||
{ 0x0E, AvnPhysicalKeyE, AvnKeyE, 'e' }, |
|||
{ 0x03, AvnPhysicalKeyF, AvnKeyF, 'f' }, |
|||
{ 0x05, AvnPhysicalKeyG, AvnKeyG, 'g' }, |
|||
{ 0x04, AvnPhysicalKeyH, AvnKeyH, 'h' }, |
|||
{ 0x22, AvnPhysicalKeyI, AvnKeyI, 'i' }, |
|||
{ 0x26, AvnPhysicalKeyJ, AvnKeyJ, 'j' }, |
|||
{ 0x28, AvnPhysicalKeyK, AvnKeyK, 'k' }, |
|||
{ 0x25, AvnPhysicalKeyL, AvnKeyL, 'l' }, |
|||
{ 0x2E, AvnPhysicalKeyM, AvnKeyM, 'm' }, |
|||
{ 0x2D, AvnPhysicalKeyN, AvnKeyN, 'n' }, |
|||
{ 0x1F, AvnPhysicalKeyO, AvnKeyO, 'o' }, |
|||
{ 0x23, AvnPhysicalKeyP, AvnKeyP, 'p' }, |
|||
{ 0x0C, AvnPhysicalKeyQ, AvnKeyQ, 'q' }, |
|||
{ 0x0F, AvnPhysicalKeyR, AvnKeyR, 'r' }, |
|||
{ 0x01, AvnPhysicalKeyS, AvnKeyS, 's' }, |
|||
{ 0x11, AvnPhysicalKeyT, AvnKeyT, 't' }, |
|||
{ 0x20, AvnPhysicalKeyU, AvnKeyU, 'u' }, |
|||
{ 0x09, AvnPhysicalKeyV, AvnKeyV, 'v' }, |
|||
{ 0x0D, AvnPhysicalKeyW, AvnKeyW, 'w' }, |
|||
{ 0x07, AvnPhysicalKeyX, AvnKeyX, 'x' }, |
|||
{ 0x10, AvnPhysicalKeyY, AvnKeyY, 'y' }, |
|||
{ 0x06, AvnPhysicalKeyZ, AvnKeyZ, 'z' }, |
|||
{ 0x1B, AvnPhysicalKeyMinus, AvnKeyOemMinus, '-' }, |
|||
{ 0x2F, AvnPhysicalKeyPeriod, AvnKeyOemPeriod, '.' }, |
|||
{ 0x27, AvnPhysicalKeyQuote, AvnKeyOem7, '\'' }, |
|||
{ 0x29, AvnPhysicalKeySemicolon, AvnKeyOem1, ';' }, |
|||
{ 0x2C, AvnPhysicalKeySlash, AvnKeyOem2, '/' }, |
|||
|
|||
// Functional Keys |
|||
{ 0x3A, AvnPhysicalKeyAltLeft, AvnKeyLeftAlt, 0 }, |
|||
{ 0x3D, AvnPhysicalKeyAltRight, AvnKeyRightAlt, 0 }, |
|||
{ 0x33, AvnPhysicalKeyBackspace, AvnKeyBack, kBackspaceCharCode }, |
|||
{ 0x39, AvnPhysicalKeyCapsLock, AvnKeyCapsLock, 0 }, |
|||
{ 0x6E, AvnPhysicalKeyContextMenu, AvnKeyApps, 0 }, |
|||
{ 0x3B, AvnPhysicalKeyControlLeft, AvnKeyLeftCtrl, 0 }, |
|||
{ 0x3E, AvnPhysicalKeyControlRight, AvnKeyRightCtrl, 0 }, |
|||
{ 0x24, AvnPhysicalKeyEnter, AvnKeyEnter, kReturnCharCode }, |
|||
{ 0x37, AvnPhysicalKeyMetaLeft, AvnKeyLWin, 0 }, |
|||
{ 0x36, AvnPhysicalKeyMetaRight, AvnKeyRWin, 0 }, |
|||
{ 0x38, AvnPhysicalKeyShiftLeft, AvnKeyLeftShift, 0 }, |
|||
{ 0x3C, AvnPhysicalKeyShiftRight, AvnKeyRightShift, 0 }, |
|||
{ 0x31, AvnPhysicalKeySpace, AvnKeySpace, kSpaceCharCode }, |
|||
{ 0x30, AvnPhysicalKeyTab, AvnKeyTab, kTabCharCode }, |
|||
//{ , AvnPhysicalKeyConvert, 0 }, |
|||
//{ , AvnPhysicalKeyKanaMode, 0 }, |
|||
{ 0x68, AvnPhysicalKeyLang1, AvnKeyKanaMode, 0 }, |
|||
{ 0x66, AvnPhysicalKeyLang2, AvnKeyHanjaMode, 0 }, |
|||
//{ , AvnPhysicalKeyLang3, 0 }, |
|||
//{ , AvnPhysicalKeyLang4, 0 }, |
|||
//{ , AvnPhysicalKeyLang5, 0 }, |
|||
//{ , AvnPhysicalKeyNonConvert, 0 }, |
|||
|
|||
// Control Pad Section |
|||
{ 0x75, AvnPhysicalKeyDelete, AvnKeyDelete, NSDeleteFunctionKey }, |
|||
{ 0x77, AvnPhysicalKeyEnd, AvnKeyEnd, NSEndFunctionKey }, |
|||
//{ , AvnPhysicalKeyHelp, 0 }, |
|||
{ 0x73, AvnPhysicalKeyHome, AvnKeyHome, NSHomeFunctionKey }, |
|||
{ 0x72, AvnPhysicalKeyInsert, AvnKeyInsert, NSInsertFunctionKey }, |
|||
{ 0x79, AvnPhysicalKeyPageDown, AvnKeyPageDown, NSPageDownFunctionKey }, |
|||
{ 0x74, AvnPhysicalKeyPageUp, AvnKeyPageUp, NSPageUpFunctionKey }, |
|||
|
|||
// Arrow Pad Section |
|||
{ 0x7D, AvnPhysicalKeyArrowDown, AvnKeyDown, NSDownArrowFunctionKey }, |
|||
{ 0x7B, AvnPhysicalKeyArrowLeft, AvnKeyLeft, NSLeftArrowFunctionKey }, |
|||
{ 0x7C, AvnPhysicalKeyArrowRight, AvnKeyRight, NSRightArrowFunctionKey }, |
|||
{ 0x7E, AvnPhysicalKeyArrowUp, AvnKeyUp, NSUpArrowFunctionKey }, |
|||
|
|||
// Numpad Section |
|||
{ 0x47, AvnPhysicalKeyNumLock, AvnKeyClear, kClearCharCode }, |
|||
{ 0x52, AvnPhysicalKeyNumPad0, AvnKeyNumPad0, '0' }, |
|||
{ 0x53, AvnPhysicalKeyNumPad1, AvnKeyNumPad1, '1' }, |
|||
{ 0x54, AvnPhysicalKeyNumPad2, AvnKeyNumPad2, '2' }, |
|||
{ 0x55, AvnPhysicalKeyNumPad3, AvnKeyNumPad3, '3' }, |
|||
{ 0x56, AvnPhysicalKeyNumPad4, AvnKeyNumPad4, '4' }, |
|||
{ 0x57, AvnPhysicalKeyNumPad5, AvnKeyNumPad5, '5' }, |
|||
{ 0x58, AvnPhysicalKeyNumPad6, AvnKeyNumPad6, '6' }, |
|||
{ 0x59, AvnPhysicalKeyNumPad7, AvnKeyNumPad7, '7' }, |
|||
{ 0x5B, AvnPhysicalKeyNumPad8, AvnKeyNumPad8, '8' }, |
|||
{ 0x5C, AvnPhysicalKeyNumPad9, AvnKeyNumPad9, '9' }, |
|||
{ 0x45, AvnPhysicalKeyNumPadAdd, AvnKeyAdd, '+' }, |
|||
//{ , AvnPhysicalKeyNumPadClear, 0 }, |
|||
{ 0x5F, AvnPhysicalKeyNumPadComma, AvnKeyAbntC2, 0 }, |
|||
{ 0x41, AvnPhysicalKeyNumPadDecimal, AvnKeyDecimal, '.' }, |
|||
{ 0x4B, AvnPhysicalKeyNumPadDivide, AvnKeyDivide, '/' }, |
|||
{ 0x4C, AvnPhysicalKeyNumPadEnter, AvnKeyEnter, kReturnCharCode }, |
|||
{ 0x51, AvnPhysicalKeyNumPadEqual, AvnKeyOemPlus, '=' }, |
|||
{ 0x43, AvnPhysicalKeyNumPadMultiply, AvnKeyMultiply, '*' }, |
|||
//{ , AvnPhysicalKeyNumPadParenLeft, 0 }, |
|||
//{ , AvnPhysicalKeyNumPadParenRight, 0 }, |
|||
{ 0x4E, AvnPhysicalKeyNumPadSubtract, AvnKeySubtract, '-' }, |
|||
|
|||
// Function Section |
|||
{ 0x35, AvnPhysicalKeyEscape, AvnKeyEscape, kEscapeCharCode }, |
|||
{ 0x7A, AvnPhysicalKeyF1, AvnKeyF1, NSF1FunctionKey }, |
|||
{ 0x78, AvnPhysicalKeyF2, AvnKeyF2, NSF2FunctionKey }, |
|||
{ 0x63, AvnPhysicalKeyF3, AvnKeyF3, NSF3FunctionKey }, |
|||
{ 0x76, AvnPhysicalKeyF4, AvnKeyF4, NSF4FunctionKey }, |
|||
{ 0x60, AvnPhysicalKeyF5, AvnKeyF5, NSF5FunctionKey }, |
|||
{ 0x61, AvnPhysicalKeyF6, AvnKeyF6, NSF6FunctionKey }, |
|||
{ 0x62, AvnPhysicalKeyF7, AvnKeyF7, NSF7FunctionKey }, |
|||
{ 0x64, AvnPhysicalKeyF8, AvnKeyF8, NSF8FunctionKey }, |
|||
{ 0x65, AvnPhysicalKeyF9, AvnKeyF9, NSF9FunctionKey }, |
|||
{ 0x6D, AvnPhysicalKeyF10, AvnKeyF10, NSF10FunctionKey }, |
|||
{ 0x67, AvnPhysicalKeyF11, AvnKeyF11, NSF11FunctionKey }, |
|||
{ 0x6F, AvnPhysicalKeyF12, AvnKeyF12, NSF12FunctionKey }, |
|||
{ 0x69, AvnPhysicalKeyF13, AvnKeyF13, NSF13FunctionKey }, |
|||
{ 0x6B, AvnPhysicalKeyF14, AvnKeyF14, NSF14FunctionKey }, |
|||
{ 0x71, AvnPhysicalKeyF15, AvnKeyF15, NSF15FunctionKey }, |
|||
{ 0x6A, AvnPhysicalKeyF16, AvnKeyF16, NSF16FunctionKey }, |
|||
{ 0x40, AvnPhysicalKeyF17, AvnKeyF17, NSF17FunctionKey }, |
|||
{ 0x4F, AvnPhysicalKeyF18, AvnKeyF18, NSF18FunctionKey }, |
|||
{ 0x50, AvnPhysicalKeyF19, AvnKeyF19, NSF19FunctionKey }, |
|||
{ 0x5A, AvnPhysicalKeyF20, AvnKeyF20, NSF20FunctionKey }, |
|||
//{ , AvnPhysicalKeyF21, 0 }, |
|||
//{ , AvnPhysicalKeyF22, 0 }, |
|||
//{ , AvnPhysicalKeyF23, 0 }, |
|||
//{ , AvnPhysicalKeyF24, 0 }, |
|||
//{ , AvnPhysicalKeyPrintScreen, 0 }, |
|||
//{ , AvnPhysicalKeyScrollLock, 0 }, |
|||
//{ , AvnPhysicalKeyPause, 0 }, |
|||
|
|||
// Media Keys |
|||
//{ , AvnPhysicalKeyBrowserBack, 0 }, |
|||
//{ , AvnPhysicalKeyBrowserFavorites, 0 }, |
|||
//{ , AvnPhysicalKeyBrowserForward, 0 }, |
|||
//{ , AvnPhysicalKeyBrowserHome, 0 }, |
|||
//{ , AvnPhysicalKeyBrowserRefresh, 0 }, |
|||
//{ , AvnPhysicalKeyBrowserSearch, 0 }, |
|||
//{ , AvnPhysicalKeyBrowserStop, 0 }, |
|||
//{ , AvnPhysicalKeyEject, 0 }, |
|||
//{ , AvnPhysicalKeyLaunchApp1, 0 }, |
|||
//{ , AvnPhysicalKeyLaunchApp2, 0 }, |
|||
//{ , AvnPhysicalKeyLaunchMail, 0 }, |
|||
//{ , AvnPhysicalKeyMediaPlayPause, 0 }, |
|||
//{ , AvnPhysicalKeyMediaSelect, 0 }, |
|||
//{ , AvnPhysicalKeyMediaStop, 0 }, |
|||
//{ , AvnPhysicalKeyMediaTrackNext, 0 }, |
|||
//{ , AvnPhysicalKeyMediaTrackPrevious, 0 }, |
|||
//{ , AvnPhysicalKeyPower, 0 }, |
|||
//{ , AvnPhysicalKeySleep, 0 }, |
|||
{ 0x49, AvnPhysicalKeyAudioVolumeDown, AvnKeyVolumeDown, 0 }, |
|||
{ 0x4A, AvnPhysicalKeyAudioVolumeMute, AvnKeyVolumeMute, 0 }, |
|||
{ 0x48, AvnPhysicalKeyAudioVolumeUp, AvnKeyVolumeUp, 0 }, |
|||
//{ , AvnPhysicalKeyWakeUp, 0 }, |
|||
|
|||
// Legacy Keys |
|||
//{ , AvnPhysicalKeyAgain, 0 }, |
|||
//{ , AvnPhysicalKeyCopy, 0 }, |
|||
//{ , AvnPhysicalKeyCut, 0 }, |
|||
//{ , AvnPhysicalKeyFind, 0 }, |
|||
//{ , AvnPhysicalKeyOpen, 0 }, |
|||
//{ , AvnPhysicalKeyPaste, 0 }, |
|||
//{ , AvnPhysicalKeyProps, 0 }, |
|||
//{ , AvnPhysicalKeySelect, 0 }, |
|||
//{ , AvnPhysicalKeyUndo, 0 } |
|||
}; |
|||
|
|||
// converts from ansi virtualkeys to AvnKeys. |
|||
std::map<int, AvnKey> s_KeyMap = |
|||
{ |
|||
{kVK_ANSI_A, A}, |
|||
{kVK_ANSI_S, S}, |
|||
{kVK_ANSI_D, D}, |
|||
{kVK_ANSI_F, F}, |
|||
{kVK_ANSI_H, H}, |
|||
{kVK_ANSI_G, G}, |
|||
{kVK_ANSI_Z, Z}, |
|||
{kVK_ANSI_X, X}, |
|||
{kVK_ANSI_C, C}, |
|||
{kVK_ANSI_V, V}, |
|||
{kVK_ANSI_B, B}, |
|||
{kVK_ANSI_Q, Q}, |
|||
{kVK_ANSI_W, W}, |
|||
{kVK_ANSI_E, E}, |
|||
{kVK_ANSI_R, R}, |
|||
{kVK_ANSI_Y, Y}, |
|||
{kVK_ANSI_T, T}, |
|||
{kVK_ANSI_1, D1}, |
|||
{kVK_ANSI_2, D2}, |
|||
{kVK_ANSI_3, D3}, |
|||
{kVK_ANSI_4, D4}, |
|||
{kVK_ANSI_6, D6}, |
|||
{kVK_ANSI_5, D5}, |
|||
{kVK_ANSI_Equal, OemPlus}, |
|||
{kVK_ANSI_9, D9}, |
|||
{kVK_ANSI_7, D7}, |
|||
{kVK_ANSI_Minus, OemMinus}, |
|||
{kVK_ANSI_8, D8}, |
|||
{kVK_ANSI_0, D0}, |
|||
{kVK_ANSI_RightBracket, OemCloseBrackets}, |
|||
{kVK_ANSI_O, O}, |
|||
{kVK_ANSI_U, U}, |
|||
{kVK_ANSI_LeftBracket, OemOpenBrackets}, |
|||
{kVK_ANSI_I, I}, |
|||
{kVK_ANSI_P, P}, |
|||
{kVK_ANSI_L, L}, |
|||
{kVK_ANSI_J, J}, |
|||
{kVK_ANSI_Quote, OemQuotes}, |
|||
{kVK_ANSI_K, AvnKeyK}, |
|||
{kVK_ANSI_Semicolon, OemSemicolon}, |
|||
{kVK_ANSI_Backslash, OemBackslash}, |
|||
{kVK_ANSI_Comma, OemComma}, |
|||
{kVK_ANSI_Slash, Oem2}, |
|||
{kVK_ANSI_N, N}, |
|||
{kVK_ANSI_M, M}, |
|||
{kVK_ANSI_Period, OemPeriod}, |
|||
{kVK_ANSI_Grave, OemTilde}, |
|||
{kVK_ANSI_KeypadDecimal, Decimal}, |
|||
{kVK_ANSI_KeypadMultiply, Multiply}, |
|||
{kVK_ANSI_KeypadPlus, OemPlus}, |
|||
{kVK_ANSI_KeypadClear, AvnKeyClear}, |
|||
{kVK_ANSI_KeypadDivide, Divide}, |
|||
{kVK_ANSI_KeypadEnter, AvnKeyEnter}, |
|||
{kVK_ANSI_KeypadMinus, OemMinus}, |
|||
{kVK_ANSI_KeypadEquals, OemPlus}, |
|||
{kVK_ANSI_Keypad0, NumPad0}, |
|||
{kVK_ANSI_Keypad1, NumPad1}, |
|||
{kVK_ANSI_Keypad2, NumPad2}, |
|||
{kVK_ANSI_Keypad3, NumPad3}, |
|||
{kVK_ANSI_Keypad4, NumPad4}, |
|||
{kVK_ANSI_Keypad5, NumPad5}, |
|||
{kVK_ANSI_Keypad6, NumPad6}, |
|||
{kVK_ANSI_Keypad7, NumPad7}, |
|||
{kVK_ANSI_Keypad8, NumPad8}, |
|||
{kVK_ANSI_Keypad9, NumPad9}, |
|||
{kVK_Return, AvnKeyReturn}, |
|||
{kVK_Tab, AvnKeyTab}, |
|||
{kVK_Space, Space}, |
|||
{kVK_Delete, AvnKeyBack}, |
|||
{kVK_Escape, Escape}, |
|||
{kVK_Command, LWin}, |
|||
{kVK_Shift, LeftShift}, |
|||
{kVK_CapsLock, AvnKeyCapsLock}, |
|||
{kVK_Option, LeftAlt}, |
|||
{kVK_Control, LeftCtrl}, |
|||
{kVK_RightCommand, RWin}, |
|||
{kVK_RightShift, RightShift}, |
|||
{kVK_RightOption, RightAlt}, |
|||
{kVK_RightControl, RightCtrl}, |
|||
//{kVK_Function, ?}, |
|||
{kVK_F17, F17}, |
|||
{kVK_VolumeUp, VolumeUp}, |
|||
{kVK_VolumeDown, VolumeDown}, |
|||
{kVK_Mute, VolumeMute}, |
|||
{kVK_F18, F18}, |
|||
{kVK_F19, F19}, |
|||
{kVK_F20, F20}, |
|||
{kVK_F5, F5}, |
|||
{kVK_F6, F6}, |
|||
{kVK_F7, F7}, |
|||
{kVK_F3, F3}, |
|||
{kVK_F8, F8}, |
|||
{kVK_F9, F9}, |
|||
{kVK_F11, F11}, |
|||
{kVK_F13, F13}, |
|||
{kVK_F16, F16}, |
|||
{kVK_F14, F14}, |
|||
{kVK_F10, F10}, |
|||
{kVK_F12, F12}, |
|||
{kVK_F15, F15}, |
|||
{kVK_Help, Help}, |
|||
{kVK_Home, Home}, |
|||
{kVK_PageUp, PageUp}, |
|||
{kVK_ForwardDelete, Delete}, |
|||
{kVK_F4, F4}, |
|||
{kVK_End, End}, |
|||
{kVK_F2, F2}, |
|||
{kVK_PageDown, PageDown}, |
|||
{kVK_F1, F1}, |
|||
{kVK_LeftArrow, Left}, |
|||
{kVK_RightArrow, Right}, |
|||
{kVK_DownArrow, Down}, |
|||
{kVK_UpArrow, Up}, |
|||
{kVK_JIS_Kana, AvnKeyKanaMode}, |
|||
std::unordered_map<uint16_t, AvnKey> virtualKeyFromChar = |
|||
{ |
|||
// Alphabetic keys |
|||
{ 'A', AvnKeyA }, |
|||
{ 'B', AvnKeyB }, |
|||
{ 'C', AvnKeyC }, |
|||
{ 'D', AvnKeyD }, |
|||
{ 'E', AvnKeyE }, |
|||
{ 'F', AvnKeyF }, |
|||
{ 'G', AvnKeyG }, |
|||
{ 'H', AvnKeyH }, |
|||
{ 'I', AvnKeyI }, |
|||
{ 'J', AvnKeyJ }, |
|||
{ 'K', AvnKeyK }, |
|||
{ 'L', AvnKeyL }, |
|||
{ 'M', AvnKeyM }, |
|||
{ 'N', AvnKeyN }, |
|||
{ 'O', AvnKeyO }, |
|||
{ 'P', AvnKeyP }, |
|||
{ 'Q', AvnKeyQ }, |
|||
{ 'R', AvnKeyR }, |
|||
{ 'S', AvnKeyS }, |
|||
{ 'T', AvnKeyT }, |
|||
{ 'U', AvnKeyU }, |
|||
{ 'V', AvnKeyV }, |
|||
{ 'W', AvnKeyW }, |
|||
{ 'X', AvnKeyX }, |
|||
{ 'Y', AvnKeyY }, |
|||
{ 'Z', AvnKeyZ }, |
|||
{ 'a', AvnKeyA }, |
|||
{ 'b', AvnKeyB }, |
|||
{ 'c', AvnKeyC }, |
|||
{ 'd', AvnKeyD }, |
|||
{ 'e', AvnKeyE }, |
|||
{ 'f', AvnKeyF }, |
|||
{ 'g', AvnKeyG }, |
|||
{ 'h', AvnKeyH }, |
|||
{ 'i', AvnKeyI }, |
|||
{ 'j', AvnKeyJ }, |
|||
{ 'k', AvnKeyK }, |
|||
{ 'l', AvnKeyL }, |
|||
{ 'm', AvnKeyM }, |
|||
{ 'n', AvnKeyN }, |
|||
{ 'o', AvnKeyO }, |
|||
{ 'p', AvnKeyP }, |
|||
{ 'q', AvnKeyQ }, |
|||
{ 'r', AvnKeyR }, |
|||
{ 's', AvnKeyS }, |
|||
{ 't', AvnKeyT }, |
|||
{ 'u', AvnKeyU }, |
|||
{ 'v', AvnKeyV }, |
|||
{ 'w', AvnKeyW }, |
|||
{ 'x', AvnKeyX }, |
|||
{ 'y', AvnKeyY }, |
|||
{ 'z', AvnKeyZ }, |
|||
|
|||
// Punctuation: US specific mappings (same as Chromium) |
|||
{ ';', AvnKeyOem1 }, |
|||
{ ':', AvnKeyOem1 }, |
|||
{ '=', AvnKeyOemPlus }, |
|||
{ '+', AvnKeyOemPlus }, |
|||
{ ',', AvnKeyOemComma }, |
|||
{ '<', AvnKeyOemComma }, |
|||
{ '-', AvnKeyOemMinus }, |
|||
{ '_', AvnKeyOemMinus }, |
|||
{ '.', AvnKeyOemPeriod }, |
|||
{ '>', AvnKeyOemPeriod }, |
|||
{ '/', AvnKeyOem2 }, |
|||
{ '?', AvnKeyOem2 }, |
|||
{ '`', AvnKeyOem3 }, |
|||
{ '~', AvnKeyOem3 }, |
|||
{ '[', AvnKeyOem4 }, |
|||
{ '{', AvnKeyOem4 }, |
|||
{ '\\', AvnKeyOem5 }, |
|||
{ '|', AvnKeyOem5 }, |
|||
{ ']', AvnKeyOem6 }, |
|||
{ '}', AvnKeyOem6 }, |
|||
{ '\'', AvnKeyOem7 }, |
|||
{ '"', AvnKeyOem7 }, |
|||
|
|||
// Apple function keys |
|||
// https://developer.apple.com/documentation/appkit/1535851-function-key_unicode_values |
|||
{ NSDeleteFunctionKey, AvnKeyDelete }, |
|||
{ NSUpArrowFunctionKey, AvnKeyUp }, |
|||
{ NSLeftArrowFunctionKey, AvnKeyLeft }, |
|||
{ NSRightArrowFunctionKey, AvnKeyRight }, |
|||
{ NSPageUpFunctionKey, AvnKeyPageUp }, |
|||
{ NSPageDownFunctionKey, AvnKeyPageDown }, |
|||
{ NSHomeFunctionKey, AvnKeyHome }, |
|||
{ NSEndFunctionKey, AvnKeyEnd }, |
|||
{ NSClearLineFunctionKey, AvnKeyClear }, |
|||
{ NSExecuteFunctionKey, AvnKeyExecute }, |
|||
{ NSHelpFunctionKey, AvnKeyHelp }, |
|||
{ NSInsertFunctionKey, AvnKeyInsert }, |
|||
{ NSMenuFunctionKey, AvnKeyApps }, |
|||
{ NSPauseFunctionKey, AvnKeyPause }, |
|||
{ NSPrintFunctionKey, AvnKeyPrint }, |
|||
{ NSPrintScreenFunctionKey, AvnKeyPrintScreen }, |
|||
{ NSScrollLockFunctionKey, AvnKeyScroll }, |
|||
{ NSF1FunctionKey, AvnKeyF1 }, |
|||
{ NSF2FunctionKey, AvnKeyF2 }, |
|||
{ NSF3FunctionKey, AvnKeyF3 }, |
|||
{ NSF4FunctionKey, AvnKeyF4 }, |
|||
{ NSF5FunctionKey, AvnKeyF5 }, |
|||
{ NSF6FunctionKey, AvnKeyF6 }, |
|||
{ NSF7FunctionKey, AvnKeyF7 }, |
|||
{ NSF8FunctionKey, AvnKeyF8 }, |
|||
{ NSF9FunctionKey, AvnKeyF9 }, |
|||
{ NSF10FunctionKey, AvnKeyF10 }, |
|||
{ NSF11FunctionKey, AvnKeyF11 }, |
|||
{ NSF12FunctionKey, AvnKeyF12 }, |
|||
{ NSF13FunctionKey, AvnKeyF13 }, |
|||
{ NSF14FunctionKey, AvnKeyF14 }, |
|||
{ NSF15FunctionKey, AvnKeyF15 }, |
|||
{ NSF16FunctionKey, AvnKeyF16 }, |
|||
{ NSF17FunctionKey, AvnKeyF17 }, |
|||
{ NSF18FunctionKey, AvnKeyF18 }, |
|||
{ NSF19FunctionKey, AvnKeyF19 }, |
|||
{ NSF20FunctionKey, AvnKeyF20 }, |
|||
{ NSF21FunctionKey, AvnKeyF21 }, |
|||
{ NSF22FunctionKey, AvnKeyF22 }, |
|||
{ NSF23FunctionKey, AvnKeyF23 }, |
|||
{ NSF24FunctionKey, AvnKeyF24 } |
|||
}; |
|||
|
|||
static std::map<AvnKey, int> BuildAvnKeyMap () |
|||
typedef std::array<AvnPhysicalKey, 0x7F> PhysicalKeyArray; |
|||
|
|||
static PhysicalKeyArray BuildPhysicalKeyFromScanCode() |
|||
{ |
|||
std::map<AvnKey, int> result; |
|||
|
|||
for( auto it = s_KeyMap.begin(); it != s_KeyMap.end(); ++it ) |
|||
PhysicalKeyArray result {}; |
|||
|
|||
for (auto& keyInfo : keyInfos) |
|||
{ |
|||
int key = it->first; |
|||
AvnKey value = it->second; |
|||
|
|||
result[value] = key; |
|||
result[keyInfo.scanCode] = keyInfo.physicalKey; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
PhysicalKeyArray physicalKeyFromScanCode = BuildPhysicalKeyFromScanCode(); |
|||
|
|||
static std::unordered_map<AvnPhysicalKey, AvnKey, std::hash<int>> BuildQwertyVirtualKeyFromPhysicalKey() |
|||
{ |
|||
std::unordered_map<AvnPhysicalKey, AvnKey, std::hash<int>> result; |
|||
result.reserve(sizeof(keyInfos) / sizeof(keyInfos[0])); |
|||
|
|||
for (auto& keyInfo : keyInfos) |
|||
{ |
|||
result[keyInfo.physicalKey] = keyInfo.qwertyKey; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
std::unordered_map<AvnPhysicalKey, AvnKey, std::hash<int>> qwertyVirtualKeyFromPhysicalKey = BuildQwertyVirtualKeyFromPhysicalKey(); |
|||
|
|||
static std::unordered_map<AvnKey, uint16_t, std::hash<int>> BuildMenuCharFromVirtualKey() |
|||
{ |
|||
std::unordered_map<AvnKey, uint16_t, std::hash<int>> result; |
|||
result.reserve(100); |
|||
|
|||
for (auto& keyInfo : keyInfos) |
|||
{ |
|||
if (keyInfo.menuChar != 0) |
|||
result[keyInfo.qwertyKey] = keyInfo.menuChar; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
// Converts AvnKeys to Ansi VirtualKeys |
|||
std::map<AvnKey, int> s_AvnKeyMap = BuildAvnKeyMap(); |
|||
std::unordered_map<AvnKey, uint16_t, std::hash<int>> menuCharFromVirtualKey = BuildMenuCharFromVirtualKey(); |
|||
|
|||
static bool IsNumpadOrNumericKey(AvnPhysicalKey physicalKey) |
|||
{ |
|||
return (physicalKey >= AvnPhysicalKeyDigit0 && physicalKey <= AvnPhysicalKeyDigit9) |
|||
|| (physicalKey >= AvnPhysicalKeyNumLock && physicalKey <= AvnPhysicalKeyNumPadSubtract); |
|||
} |
|||
|
|||
AvnPhysicalKey PhysicalKeyFromScanCode(uint16_t scanCode) |
|||
{ |
|||
return scanCode < physicalKeyFromScanCode.size() ? physicalKeyFromScanCode[scanCode] : AvnPhysicalKeyNone; |
|||
} |
|||
|
|||
static bool IsAllowedAsciiChar(UniChar c) |
|||
{ |
|||
if (c < 0x20) |
|||
{ |
|||
switch (c) |
|||
{ |
|||
case kBackspaceCharCode: |
|||
case kReturnCharCode: |
|||
case kTabCharCode: |
|||
case kEscapeCharCode: |
|||
return true; |
|||
default: |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
if (c == kDeleteCharCode) |
|||
return false; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
static UniCharCount CharsFromScanCode(UInt16 scanCode, NSEventModifierFlags modifierFlags, UInt16 keyAction, UniChar* buffer, UniCharCount bufferSize) |
|||
{ |
|||
auto currentKeyboard = TISCopyCurrentKeyboardInputSource(); |
|||
if (!currentKeyboard) |
|||
return 0; |
|||
|
|||
auto layoutData = static_cast<CFDataRef>(TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData)); |
|||
if (!layoutData) |
|||
return 0; |
|||
|
|||
auto* keyboardLayout = reinterpret_cast<const UCKeyboardLayout*>(CFDataGetBytePtr(layoutData)); |
|||
|
|||
UInt32 deadKeyState = 0; |
|||
UniCharCount length = 0; |
|||
|
|||
int glyphModifiers = 0; |
|||
if (modifierFlags & NSEventModifierFlagShift) |
|||
glyphModifiers |= shiftKey; |
|||
if (modifierFlags & NSEventModifierFlagCapsLock) |
|||
glyphModifiers |= alphaLock; |
|||
if (modifierFlags & NSEventModifierFlagOption) |
|||
glyphModifiers |= optionKey; |
|||
|
|||
auto result = UCKeyTranslate( |
|||
keyboardLayout, |
|||
scanCode, |
|||
keyAction, |
|||
(glyphModifiers >> 8) & 0xFF, |
|||
LMGetKbdType(), |
|||
kUCKeyTranslateNoDeadKeysBit, |
|||
&deadKeyState, |
|||
bufferSize, |
|||
&length, |
|||
buffer); |
|||
|
|||
if (result != noErr) |
|||
return 0; |
|||
|
|||
if (deadKeyState) |
|||
{ |
|||
// translate a space with dead key state to get the dead key itself |
|||
result = UCKeyTranslate( |
|||
keyboardLayout, |
|||
kVK_Space, |
|||
keyAction, |
|||
0, |
|||
LMGetKbdType(), |
|||
kUCKeyTranslateNoDeadKeysBit, |
|||
&deadKeyState, |
|||
bufferSize, |
|||
&length, |
|||
buffer); |
|||
|
|||
if (result != noErr) |
|||
return 0; |
|||
} |
|||
|
|||
if (length == 1 && buffer[0] <= 0x7F && !IsAllowedAsciiChar(buffer[0])) |
|||
return 0; |
|||
|
|||
return length; |
|||
} |
|||
|
|||
AvnKey VirtualKeyFromScanCode(uint16_t scanCode, NSEventModifierFlags modifierFlags) |
|||
{ |
|||
auto physicalKey = PhysicalKeyFromScanCode(scanCode); |
|||
if (!IsNumpadOrNumericKey(physicalKey)) |
|||
{ |
|||
const UniCharCount charCount = 4; |
|||
UniChar chars[charCount]; |
|||
auto length = CharsFromScanCode(scanCode, modifierFlags, kUCKeyActionDown, chars, charCount); |
|||
if (length > 0) |
|||
{ |
|||
auto it = virtualKeyFromChar.find(chars[0]); |
|||
if (it != virtualKeyFromChar.end()) |
|||
return it->second; |
|||
} |
|||
} |
|||
|
|||
auto it = qwertyVirtualKeyFromPhysicalKey.find(physicalKey); |
|||
return it == qwertyVirtualKeyFromPhysicalKey.end() ? AvnKeyNone : it->second; |
|||
} |
|||
|
|||
NSString* KeySymbolFromScanCode(uint16_t scanCode, NSEventModifierFlags modifierFlags) |
|||
{ |
|||
auto physicalKey = PhysicalKeyFromScanCode(scanCode); |
|||
|
|||
const UniCharCount charCount = 4; |
|||
UniChar chars[charCount]; |
|||
auto length = CharsFromScanCode(scanCode, modifierFlags, kUCKeyActionDisplay, chars, charCount); |
|||
if (length > 0) |
|||
return [NSString stringWithCharacters:chars length:length]; |
|||
|
|||
auto it = qwertyVirtualKeyFromPhysicalKey.find(physicalKey); |
|||
if (it == qwertyVirtualKeyFromPhysicalKey.end()) |
|||
return nullptr; |
|||
|
|||
auto menuChar = MenuCharFromVirtualKey(it->second); |
|||
return menuChar == 0 || menuChar > 0x7E ? nullptr : [NSString stringWithCharacters:&menuChar length:1]; |
|||
} |
|||
|
|||
uint16_t MenuCharFromVirtualKey(AvnKey key) |
|||
{ |
|||
auto it = menuCharFromVirtualKey.find(key); |
|||
return it == menuCharFromVirtualKey.end() ? 0 : it->second; |
|||
} |
|||
|
|||
@ -1,12 +1,74 @@ |
|||
using System; |
|||
using Avalonia.Interactivity; |
|||
|
|||
namespace Avalonia.Input |
|||
namespace Avalonia.Input; |
|||
|
|||
/// <summary>
|
|||
/// Provides information specific to a keyboard event.
|
|||
/// </summary>
|
|||
public class KeyEventArgs : RoutedEventArgs |
|||
{ |
|||
public class KeyEventArgs : RoutedEventArgs |
|||
{ |
|||
public Key Key { get; init; } |
|||
/// <summary>
|
|||
/// <para>
|
|||
/// Gets the virtual-key for the associated event.<br/>
|
|||
/// A given physical key can result in different virtual keys depending on the current keyboard layout.<br/>
|
|||
/// This is the key that is generally referred to when creating keyboard shortcuts.
|
|||
/// </para>
|
|||
/// <para>
|
|||
/// For example, when pressing the key located at the <c>Z</c> position on standard US English QWERTY keyboard,
|
|||
/// this property returns:<br/>
|
|||
/// - <see cref="Input.Key.Z"/> for an English (QWERTY) layout<br/>
|
|||
/// - <see cref="Input.Key.W"/> for a French (AZERTY) layout<br/>
|
|||
/// - <see cref="Input.Key.Y"/> for a German (QWERTZ) layout<br/>
|
|||
/// - <see cref="Input.Key.Z"/> for a Russian (JCUKEN) layout
|
|||
/// </para>
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This property should be used for letter-related shortcuts only.<br/>
|
|||
/// Prefer using <see cref="PhysicalKey"/> if you need to refer to a key given its position on the keyboard (a
|
|||
/// common usage is moving the player with WASD-like keys in games), or <see cref="KeySymbol"/> if you want to know
|
|||
/// which character the key will output.<br/>
|
|||
/// Avoid using this for shortcuts related to punctuation keys, as they differ wildly depending on keyboard layouts.
|
|||
/// </remarks>
|
|||
/// <seealso cref="PhysicalKey"/>
|
|||
/// <seealso cref="KeySymbol"/>
|
|||
public Key Key { get; init; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the key modifiers for the associated event.
|
|||
/// </summary>
|
|||
public KeyModifiers KeyModifiers { get; init; } |
|||
|
|||
/// <summary>
|
|||
/// <para>
|
|||
/// Gets the physical key for the associated event.
|
|||
/// </para>
|
|||
/// <para>
|
|||
/// This value is independent of the current keyboard layout and usually correspond to the key printed on a standard
|
|||
/// US English QWERTY keyboard.
|
|||
/// </para>
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Use this property if you need to refer to a key given its position on the keyboard (a common usage is moving the
|
|||
/// player with WASD-like keys).
|
|||
/// </remarks>
|
|||
/// <seealso cref="Key"/>
|
|||
/// <seealso cref="KeySymbol"/>
|
|||
public PhysicalKey PhysicalKey { get; init; } |
|||
|
|||
public KeyModifiers KeyModifiers { get; init; } |
|||
} |
|||
/// <summary>
|
|||
/// <para>
|
|||
/// Gets the unicode symbol of the key, or null if none is applicable.
|
|||
/// </para>
|
|||
/// <para>
|
|||
/// For example, when pressing the key located at the <c>Z</c> position on standard US English QWERTY keyboard,
|
|||
/// this property returns:<br/>
|
|||
/// - <c>z</c> for an English (QWERTY) layout<br/>
|
|||
/// - <c>w</c> for a French (AZERTY) layout<br/>
|
|||
/// - <c>y</c> for a German (QWERTZ) layout<br/>
|
|||
/// - <c>я</c> for a Russian (JCUKEN) layout
|
|||
/// </para>
|
|||
/// </summary>
|
|||
/// <see cref="Key"/>
|
|||
/// <see cref="PhysicalKey"/>
|
|||
public string? KeySymbol { get; init; } |
|||
} |
|||
|
|||
@ -0,0 +1,26 @@ |
|||
namespace Avalonia.Input; |
|||
|
|||
internal static class KeySymbolHelper |
|||
{ |
|||
public static bool IsAllowedAsciiKeySymbol(char c) |
|||
{ |
|||
if (c < 0x20) |
|||
{ |
|||
switch (c) |
|||
{ |
|||
case '\b': // backspace
|
|||
case '\t': // tab
|
|||
case '\r': // return
|
|||
case (char)0x1B: // escape
|
|||
return true; |
|||
default: |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
if (c == 0x07) // delete
|
|||
return false; |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
@ -0,0 +1,944 @@ |
|||
#if AVALONIA_REMOTE_PROTOCOL
|
|||
namespace Avalonia.Remote.Protocol.Input; |
|||
#else
|
|||
namespace Avalonia.Input; |
|||
#endif
|
|||
|
|||
/// <summary>
|
|||
/// Represents a keyboard physical key.<br/>
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// The names follow the W3C codes: https://www.w3.org/TR/uievents-code/
|
|||
/// </remarks>
|
|||
public enum PhysicalKey |
|||
{ |
|||
/// <summary>
|
|||
/// Represents no key.
|
|||
/// </summary>
|
|||
None = 0, |
|||
|
|||
|
|||
// ###################
|
|||
// Writing System Keys
|
|||
// ###################
|
|||
|
|||
/// <summary>
|
|||
/// <c>`~</c> on a US keyboard.
|
|||
/// This is the <c>半角/全角/漢字</c> (hankaku/zenkaku/kanji) key on Japanese keyboards.
|
|||
/// </summary>
|
|||
Backquote = 1, |
|||
|
|||
/// <summary>
|
|||
/// Used for both the US <c>\|</c> (on the 101-key layout) and also for the key located between the <c>"</c> and
|
|||
/// <c>Enter</c> keys on row C of the 102-, 104- and 106-key layouts.
|
|||
/// <c>#~</c> on a UK (102) keyboard.
|
|||
/// </summary>
|
|||
Backslash = 2, |
|||
|
|||
/// <summary>
|
|||
/// <c>[{</c> on a US keyboard.
|
|||
/// </summary>
|
|||
BracketLeft = 3, |
|||
|
|||
/// <summary>
|
|||
/// <c>]}</c> on a US keyboard.
|
|||
/// </summary>
|
|||
BracketRight = 4, |
|||
|
|||
/// <summary>
|
|||
/// <c>,<</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Comma = 5, |
|||
|
|||
/// <summary>
|
|||
/// <c>0)</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Digit0 = 6, |
|||
|
|||
/// <summary>
|
|||
/// <c>1!</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Digit1 = 7, |
|||
|
|||
/// <summary>
|
|||
/// <c>2@</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Digit2 = 8, |
|||
|
|||
/// <summary>
|
|||
/// <c>3#</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Digit3 = 9, |
|||
|
|||
/// <summary>
|
|||
/// <c>4$</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Digit4 = 10, |
|||
|
|||
/// <summary>
|
|||
/// <c>5%</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Digit5 = 11, |
|||
|
|||
/// <summary>
|
|||
/// <c>6^</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Digit6 = 12, |
|||
|
|||
/// <summary>
|
|||
/// <c>7&</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Digit7 = 13, |
|||
|
|||
/// <summary>
|
|||
/// <c>8*</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Digit8 = 14, |
|||
|
|||
/// <summary>
|
|||
/// <c>9(</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Digit9 = 15, |
|||
|
|||
/// <summary>
|
|||
/// <c>=+</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Equal = 16, |
|||
|
|||
/// <summary>
|
|||
/// Located between the left <c>Shift</c> and <c>Z</c> keys.
|
|||
/// <c>\|</c> on a UK keyboard.
|
|||
/// </summary>
|
|||
IntlBackslash = 17, |
|||
|
|||
/// <summary>
|
|||
/// Located between the <c>/</c> and right <c>Shift</c> keys.
|
|||
/// <c>\ろ</c> (ro) on a Japanese keyboard.
|
|||
/// </summary>
|
|||
IntlRo = 18, |
|||
|
|||
/// <summary>
|
|||
/// Located between the <c>=</c> and <c>Backspace</c> keys.
|
|||
/// <c>¥</c> (yen) on a Japanese keyboard.
|
|||
/// <c>\/</c> on a Russian keyboard.
|
|||
/// </summary>
|
|||
IntlYen = 19, |
|||
|
|||
/// <summary>
|
|||
/// <c>a</c> on a US keyboard.
|
|||
/// <c>q</c> on an AZERTY (e.g., French) keyboard.
|
|||
/// </summary>
|
|||
A = 20, |
|||
|
|||
/// <summary>
|
|||
/// <c>b</c> on a US keyboard.
|
|||
/// </summary>
|
|||
B = 21, |
|||
|
|||
/// <summary>
|
|||
/// <c>c</c> on a US keyboard.
|
|||
/// </summary>
|
|||
C = 22, |
|||
|
|||
/// <summary>
|
|||
/// <c>d</c> on a US keyboard.
|
|||
/// </summary>
|
|||
D = 23, |
|||
|
|||
/// <summary>
|
|||
/// <c>e</c> on a US keyboard.
|
|||
/// </summary>
|
|||
E = 24, |
|||
|
|||
/// <summary>
|
|||
/// <c>f</c> on a US keyboard.
|
|||
/// </summary>
|
|||
F = 25, |
|||
|
|||
/// <summary>
|
|||
/// <c>g</c> on a US keyboard.
|
|||
/// </summary>
|
|||
G = 26, |
|||
|
|||
/// <summary>
|
|||
/// <c>h</c> on a US keyboard.
|
|||
/// </summary>
|
|||
H = 27, |
|||
|
|||
/// <summary>
|
|||
/// <c>i</c> on a US keyboard.
|
|||
/// </summary>
|
|||
I = 28, |
|||
|
|||
/// <summary>
|
|||
/// <c>j</c> on a US keyboard.
|
|||
/// </summary>
|
|||
J = 29, |
|||
|
|||
/// <summary>
|
|||
/// <c>k</c> on a US keyboard.
|
|||
/// </summary>
|
|||
K = 30, |
|||
|
|||
/// <summary>
|
|||
/// <c>l</c> on a US keyboard.
|
|||
/// </summary>
|
|||
L = 31, |
|||
|
|||
/// <summary>
|
|||
/// <c>m</c> on a US keyboard.
|
|||
/// </summary>
|
|||
M = 32, |
|||
|
|||
/// <summary>
|
|||
/// <c>n</c> on a US keyboard.
|
|||
/// </summary>
|
|||
N = 33, |
|||
|
|||
/// <summary>
|
|||
/// <c>o</c> on a US keyboard.
|
|||
/// </summary>
|
|||
O = 34, |
|||
|
|||
/// <summary>
|
|||
/// <c>p</c> on a US keyboard.
|
|||
/// </summary>
|
|||
P = 35, |
|||
|
|||
/// <summary>
|
|||
/// <c>q</c> on a US keyboard.
|
|||
/// <c>a</c> on an AZERTY (e.g., French) keyboard.
|
|||
/// </summary>
|
|||
Q = 36, |
|||
|
|||
/// <summary>
|
|||
/// <c>r</c> on a US keyboard.
|
|||
/// </summary>
|
|||
R = 37, |
|||
|
|||
/// <summary>
|
|||
/// <c>s</c> on a US keyboard.
|
|||
/// </summary>
|
|||
S = 38, |
|||
|
|||
/// <summary>
|
|||
/// <c>t</c> on a US keyboard.
|
|||
/// </summary>
|
|||
T = 39, |
|||
|
|||
/// <summary>
|
|||
/// <c>u</c> on a US keyboard.
|
|||
/// </summary>
|
|||
U = 40, |
|||
|
|||
/// <summary>
|
|||
/// <c>v</c> on a US keyboard.
|
|||
/// </summary>
|
|||
V = 41, |
|||
|
|||
/// <summary>
|
|||
/// <c>w</c> on a US keyboard.
|
|||
/// <c>z</c> on an AZERTY (e.g., French) keyboard.
|
|||
/// </summary>
|
|||
W = 42, |
|||
|
|||
/// <summary>
|
|||
/// <c>x</c> on a US keyboard.
|
|||
/// </summary>
|
|||
X = 43, |
|||
|
|||
/// <summary>
|
|||
/// <c>y</c> on a US keyboard.
|
|||
/// <c>z</c> on a QWERTZ (e.g., German) keyboard.
|
|||
/// </summary>
|
|||
Y = 44, |
|||
|
|||
/// <summary>
|
|||
/// <c>z</c> on a US keyboard.
|
|||
/// <c>w</c> on an AZERTY (e.g., French) keyboard.
|
|||
/// <c>y</c> on a QWERTZ (e.g., German) keyboard.
|
|||
/// </summary>
|
|||
Z = 45, |
|||
|
|||
/// <summary>
|
|||
/// <c>-_</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Minus = 46, |
|||
|
|||
/// <summary>
|
|||
/// <c>.></c> on a US keyboard.
|
|||
/// </summary>
|
|||
Period = 47, |
|||
|
|||
/// <summary>
|
|||
/// <c>'"</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Quote = 48, |
|||
|
|||
/// <summary>
|
|||
/// <c>;:</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Semicolon = 49, |
|||
|
|||
/// <summary>
|
|||
/// <c>/?</c> on a US keyboard.
|
|||
/// </summary>
|
|||
Slash = 50, |
|||
|
|||
|
|||
// ###############
|
|||
// Functional keys
|
|||
// ###############
|
|||
|
|||
/// <summary>
|
|||
/// <c>Alt</c>, <c>Option</c> or <c>⌥</c>.
|
|||
/// </summary>
|
|||
AltLeft = 51, |
|||
|
|||
/// <summary>
|
|||
/// <c>Alt</c>, <c>Option</c> or <c>⌥</c>.
|
|||
/// This is labelled <c>AltGr</c> key on many keyboard layouts.
|
|||
/// </summary>
|
|||
AltRight = 52, |
|||
|
|||
/// <summary>
|
|||
/// <c>Backspace</c> or <c>⌫</c>.
|
|||
/// Labelled <c>Delete</c> on Apple keyboards.
|
|||
/// </summary>
|
|||
Backspace = 53, |
|||
|
|||
/// <summary>
|
|||
/// <c>CapsLock</c> or <c>⇪</c>.
|
|||
/// </summary>
|
|||
CapsLock = 54, |
|||
|
|||
/// <summary>
|
|||
/// The application context menu key, which is typically found between the right <c>Meta</c> key
|
|||
/// and the right <c>Control</c> key.
|
|||
/// </summary>
|
|||
ContextMenu = 55, |
|||
|
|||
/// <summary>
|
|||
/// <c>Control</c> or <c>⌃</c>.
|
|||
/// </summary>
|
|||
ControlLeft = 56, |
|||
|
|||
/// <summary>
|
|||
/// <c>Control</c> or <c>⌃</c>.
|
|||
/// </summary>
|
|||
ControlRight = 57, |
|||
|
|||
/// <summary>
|
|||
/// <c>Enter</c> or <c>↵</c>.
|
|||
/// Labelled <c>Return</c> on Apple keyboards.
|
|||
/// </summary>
|
|||
Enter = 58, |
|||
|
|||
/// <summary>
|
|||
/// The <c>⊞</c> (Windows), <c>⌘</c>, <c>Command</c> or other OS symbol key.
|
|||
/// </summary>
|
|||
MetaLeft = 59, |
|||
|
|||
/// <summary>
|
|||
/// The <c>⊞</c> (Windows), <c>⌘</c>, <c>Command</c> or other OS symbol key.
|
|||
/// </summary>
|
|||
MetaRight = 60, |
|||
|
|||
/// <summary>
|
|||
/// <c>Shift</c> or <c>⇧</c>.
|
|||
/// </summary>
|
|||
ShiftLeft = 61, |
|||
|
|||
/// <summary>
|
|||
/// <c>Shift</c> or <c>⇧</c>.
|
|||
/// </summary>
|
|||
ShiftRight = 62, |
|||
|
|||
/// <summary>
|
|||
/// <c> </c> (space).
|
|||
/// </summary>
|
|||
Space = 63, |
|||
|
|||
/// <summary>
|
|||
/// <c>Tab</c> or <c>⇥</c>.
|
|||
/// </summary>
|
|||
Tab = 64, |
|||
|
|||
/// <summary>
|
|||
/// Japanese: <c>変換</c> (henkan).
|
|||
/// </summary>
|
|||
Convert = 65, |
|||
|
|||
/// <summary>
|
|||
/// Japanese: <c>カタカナ/ひらがな/ローマ字</c> (katakana/hiragana/romaji).
|
|||
/// </summary>
|
|||
KanaMode = 66, |
|||
|
|||
/// <summary>
|
|||
/// Korean: HangulMode <c>한/영</c> (han/yeong).
|
|||
/// Japanese (Mac keyboard): <c>かな</c> (kana).
|
|||
/// </summary>
|
|||
Lang1 = 67, |
|||
|
|||
/// <summary>
|
|||
/// Korean: Hanja <c>한자</c> (hanja).
|
|||
/// Japanese (Mac keyboard): <c>英数</c> (eisu).
|
|||
/// </summary>
|
|||
Lang2 = 68, |
|||
|
|||
/// <summary>
|
|||
/// Japanese (word-processing keyboard): Katakana.
|
|||
/// </summary>
|
|||
Lang3 = 69, |
|||
|
|||
/// <summary>
|
|||
/// Japanese (word-processing keyboard): Hiragana.
|
|||
/// </summary>
|
|||
Lang4 = 70, |
|||
|
|||
/// <summary>
|
|||
/// Japanese (word-processing keyboard): Zenkaku/Hankaku.
|
|||
/// </summary>
|
|||
Lang5 = 71, |
|||
|
|||
/// <summary>
|
|||
/// Japanese: <c>無変換</c> (muhenkan).
|
|||
/// </summary>
|
|||
NonConvert = 72, |
|||
|
|||
|
|||
// ###################
|
|||
// Control Pad Section
|
|||
// ###################
|
|||
|
|||
/// <summary>
|
|||
/// <c>⌦</c>. The forward delete key.
|
|||
/// Note that on Apple keyboards, the key labelled <c>Delete</c> on the main part of the keyboard is
|
|||
/// <see cref="Backspace"/>.
|
|||
/// </summary>
|
|||
Delete = 73, |
|||
|
|||
/// <summary>
|
|||
/// <c>End</c> or <c>↘</c>.
|
|||
/// </summary>
|
|||
End = 74, |
|||
|
|||
/// <summary>
|
|||
/// <c>Help</c>.
|
|||
/// Not present on standard PC keyboards.
|
|||
/// </summary>
|
|||
Help = 75, |
|||
|
|||
/// <summary>
|
|||
/// <c>Home</c> or <c>↖</c>.
|
|||
/// </summary>
|
|||
Home = 76, |
|||
|
|||
/// <summary>
|
|||
/// <c>Insert</c> or <c>Ins</c>.
|
|||
/// Not present on Apple keyboards.
|
|||
/// </summary>
|
|||
Insert = 77, |
|||
|
|||
/// <summary>
|
|||
/// <c>Page Down</c>, <c>PgDn</c> or <c>⇟</c>.
|
|||
/// </summary>
|
|||
PageDown = 78, |
|||
|
|||
/// <summary>
|
|||
/// <c>Page Up</c>, <c>PgUp</c> or <c>⇞</c>.
|
|||
/// </summary>
|
|||
PageUp = 79, |
|||
|
|||
|
|||
// #################
|
|||
// Arrow Pad Section
|
|||
// #################
|
|||
|
|||
/// <summary>
|
|||
/// <c>↓</c>.
|
|||
/// </summary>
|
|||
ArrowDown = 80, |
|||
|
|||
/// <summary>
|
|||
/// <c>←</c>.
|
|||
/// </summary>
|
|||
ArrowLeft = 81, |
|||
|
|||
/// <summary>
|
|||
/// <c>→</c>.
|
|||
/// </summary>
|
|||
ArrowRight = 82, |
|||
|
|||
/// <summary>
|
|||
/// <c>↑</c>.
|
|||
/// </summary>
|
|||
ArrowUp = 83, |
|||
|
|||
|
|||
// ######################
|
|||
// Numeric Keypad Section
|
|||
// ######################
|
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>Num Lock</c>.
|
|||
/// On the Mac, this is used for the numpad <c>Clear</c> key.
|
|||
/// </summary>
|
|||
NumLock = 84, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>0 Ins</c> on a keyboard.
|
|||
/// <c>0</c> on a phone or remote control.
|
|||
/// </summary>
|
|||
NumPad0 = 85, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>1 End</c> on a keyboard.
|
|||
/// <c>1</c> or <c>1 QZ</c> on a phone or remote control.
|
|||
/// </summary>
|
|||
NumPad1 = 86, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>2 ↓</c> on a keyboard.
|
|||
/// <c>2 ABC</c> on a phone or remote control.
|
|||
/// </summary>
|
|||
NumPad2 = 87, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>3 PgDn</c> on a keyboard.
|
|||
/// <c>3 DEF</c> on a phone or remote control.
|
|||
/// </summary>
|
|||
NumPad3 = 88, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>4 ←</c> on a keyboard.
|
|||
/// <c>4 GHI</c> on a phone or remote control.
|
|||
/// </summary>
|
|||
NumPad4 = 89, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>5</c> on a keyboard.
|
|||
/// <c>5 JKL</c> on a phone or remote control.
|
|||
/// </summary>
|
|||
NumPad5 = 90, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>6 →</c> on a keyboard.
|
|||
/// <c>6 MNO</c> on a phone or remote control.
|
|||
/// </summary>
|
|||
NumPad6 = 91, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>7 Home</c> on a keyboard.
|
|||
/// <c>7 PQRS</c> or <c>7 PRS</c> on a phone or remote control.
|
|||
/// </summary>
|
|||
NumPad7 = 92, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>8 ↑</c> on a keyboard.
|
|||
/// <c>8 TUV</c> on a phone or remote control.
|
|||
/// </summary>
|
|||
NumPad8 = 93, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>9 PgUp</c> on a keyboard.
|
|||
/// <c>9 WXYZ</c> or <c>9 WXY</c> on a phone or remote control.
|
|||
/// </summary>
|
|||
NumPad9 = 94, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>+</c>.
|
|||
/// </summary>
|
|||
NumPadAdd = 95, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>C</c> or <c>AC</c> (All Clear).
|
|||
/// Also for use with numpads that have a <c>Clear</c> key that is separate from the <c>NumLock</c> key.
|
|||
/// On the Mac, the numpad <c>Clear</c> key is <see cref="NumLock"/>.
|
|||
/// </summary>
|
|||
NumPadClear = 96, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>,</c> (thousands separator).
|
|||
/// For locales where the thousands separator is a "." (e.g., Brazil), this key may generate a <c>.</c>.
|
|||
/// </summary>
|
|||
NumPadComma = 97, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>. Del</c>.
|
|||
/// For locales where the decimal separator is "," (e.g., Brazil), this key may generate a <c>,</c>.
|
|||
/// </summary>
|
|||
NumPadDecimal = 98, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>/</c>.
|
|||
/// </summary>
|
|||
NumPadDivide = 99, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>Enter</c>.
|
|||
/// </summary>
|
|||
NumPadEnter = 100, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>=</c>.
|
|||
/// </summary>
|
|||
NumPadEqual = 101, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>*</c> on a keyboard.
|
|||
/// For use with numpads that provide mathematical operations (<c>+</c>, <c>-</c>, <c>*</c> and <c>/</c>).
|
|||
/// </summary>
|
|||
NumPadMultiply = 102, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>(</c>.
|
|||
/// Found on the Microsoft Natural Keyboard.
|
|||
/// </summary>
|
|||
NumPadParenLeft = 103, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>)</c>.
|
|||
/// Found on the Microsoft Natural Keyboard.
|
|||
/// </summary>
|
|||
NumPadParenRight = 104, |
|||
|
|||
/// <summary>
|
|||
/// Numeric keypad <c>-</c>.
|
|||
/// </summary>
|
|||
NumPadSubtract = 105, |
|||
|
|||
|
|||
// ################
|
|||
// Function Section
|
|||
// ################
|
|||
|
|||
/// <summary>
|
|||
/// <c>Esc</c> or <c>⎋</c>.
|
|||
/// </summary>
|
|||
Escape = 106, |
|||
|
|||
/// <summary>
|
|||
/// <c>F1</c>.
|
|||
/// </summary>
|
|||
F1 = 107, |
|||
|
|||
/// <summary>
|
|||
/// <c>F2</c>.
|
|||
/// </summary>
|
|||
F2 = 108, |
|||
|
|||
/// <summary>
|
|||
/// <c>F3</c>.
|
|||
/// </summary>
|
|||
F3 = 109, |
|||
|
|||
/// <summary>
|
|||
/// <c>F4</c>.
|
|||
/// </summary>
|
|||
F4 = 110, |
|||
|
|||
/// <summary>
|
|||
/// <c>F5</c>.
|
|||
/// </summary>
|
|||
F5 = 111, |
|||
|
|||
/// <summary>
|
|||
/// <c>F6</c>.
|
|||
/// </summary>
|
|||
F6 = 112, |
|||
|
|||
/// <summary>
|
|||
/// <c>F7</c>.
|
|||
/// </summary>
|
|||
F7 = 113, |
|||
|
|||
/// <summary>
|
|||
/// <c>F8</c>.
|
|||
/// </summary>
|
|||
F8 = 114, |
|||
|
|||
/// <summary>
|
|||
/// <c>F9</c>.
|
|||
/// </summary>
|
|||
F9 = 115, |
|||
|
|||
/// <summary>
|
|||
/// <c>F10</c>.
|
|||
/// </summary>
|
|||
F10 = 116, |
|||
|
|||
/// <summary>
|
|||
/// <c>F11</c>.
|
|||
/// </summary>
|
|||
F11 = 117, |
|||
|
|||
/// <summary>
|
|||
/// <c>F12</c>.
|
|||
/// </summary>
|
|||
F12 = 118, |
|||
|
|||
/// <summary>
|
|||
/// <c>F13</c>.
|
|||
/// </summary>
|
|||
F13 = 119, |
|||
|
|||
/// <summary>
|
|||
/// <c>F14</c>.
|
|||
/// </summary>
|
|||
F14 = 120, |
|||
|
|||
/// <summary>
|
|||
/// <c>F15</c>.
|
|||
/// </summary>
|
|||
F15 = 121, |
|||
|
|||
/// <summary>
|
|||
/// <c>F16</c>.
|
|||
/// </summary>
|
|||
F16 = 122, |
|||
|
|||
/// <summary>
|
|||
/// <c>F17</c>.
|
|||
/// </summary>
|
|||
F17 = 123, |
|||
|
|||
/// <summary>
|
|||
/// <c>F18</c>.
|
|||
/// </summary>
|
|||
F18 = 124, |
|||
|
|||
/// <summary>
|
|||
/// <c>F19</c>.
|
|||
/// </summary>
|
|||
F19 = 125, |
|||
|
|||
/// <summary>
|
|||
/// <c>F20</c>.
|
|||
/// </summary>
|
|||
F20 = 126, |
|||
|
|||
/// <summary>
|
|||
/// <c>F21</c>.
|
|||
/// </summary>
|
|||
F21 = 127, |
|||
|
|||
/// <summary>
|
|||
/// <c>F22</c>.
|
|||
/// </summary>
|
|||
F22 = 128, |
|||
|
|||
/// <summary>
|
|||
/// <c>F23</c>.
|
|||
/// </summary>
|
|||
F23 = 129, |
|||
|
|||
/// <summary>
|
|||
/// <c>F24</c>.
|
|||
/// </summary>
|
|||
F24 = 130, |
|||
|
|||
/// <summary>
|
|||
/// <c>PrtScr SysRq</c> or <c>Print Screen</c>.
|
|||
/// </summary>
|
|||
PrintScreen = 131, |
|||
|
|||
/// <summary>
|
|||
/// <c>Scroll Lock</c>.
|
|||
/// </summary>
|
|||
ScrollLock = 132, |
|||
|
|||
/// <summary>
|
|||
/// <c>Pause Break</c>.
|
|||
/// </summary>
|
|||
Pause = 133, |
|||
|
|||
|
|||
// ##########
|
|||
// Media Keys
|
|||
// ##########
|
|||
|
|||
/// <summary>
|
|||
/// Browser <c>Back</c>.
|
|||
/// Some laptops place this key to the left of the <c>↑</c> key.
|
|||
/// </summary>
|
|||
BrowserBack = 134, |
|||
|
|||
/// <summary>
|
|||
/// Browser <c>Favorites</c>.
|
|||
/// </summary>
|
|||
BrowserFavorites = 135, |
|||
|
|||
/// <summary>
|
|||
/// Browser <c>Forward</c>.
|
|||
/// Some laptops place this key to the right of the <c>↑</c> key.
|
|||
/// </summary>
|
|||
BrowserForward = 136, |
|||
|
|||
/// <summary>
|
|||
/// Browser <c>Home</c>.
|
|||
/// </summary>
|
|||
BrowserHome = 137, |
|||
|
|||
/// <summary>
|
|||
/// Browser <c>Refresh</c>.
|
|||
/// </summary>
|
|||
BrowserRefresh = 138, |
|||
|
|||
/// <summary>
|
|||
/// Browser <c>Search</c>.
|
|||
/// </summary>
|
|||
BrowserSearch = 139, |
|||
|
|||
/// <summary>
|
|||
/// Browser <c>Stop</c>.
|
|||
/// </summary>
|
|||
BrowserStop = 140, |
|||
|
|||
/// <summary>
|
|||
/// <c>Eject</c> or <c>⏏</c>.
|
|||
/// This key is placed in the function section on some Apple keyboards.
|
|||
/// </summary>
|
|||
Eject = 141, |
|||
|
|||
/// <summary>
|
|||
/// <c>App 1</c>.
|
|||
/// Sometimes labelled <c>My Computer</c> on the keyboard.
|
|||
/// </summary>
|
|||
LaunchApp1 = 142, |
|||
|
|||
/// <summary>
|
|||
/// <c>App 2</c>.
|
|||
/// Sometimes labelled <c>Calculator</c> on the keyboard.
|
|||
/// </summary>
|
|||
LaunchApp2 = 143, |
|||
|
|||
/// <summary>
|
|||
/// <c>Mail</c>.
|
|||
/// </summary>
|
|||
LaunchMail = 144, |
|||
|
|||
/// <summary>
|
|||
/// Media <c>Play/Pause</c> or <c>⏵⏸</c>.
|
|||
/// </summary>
|
|||
MediaPlayPause = 145, |
|||
|
|||
/// <summary>
|
|||
/// Media <c>Select</c>.
|
|||
/// </summary>
|
|||
MediaSelect = 146, |
|||
|
|||
/// <summary>
|
|||
/// Media <c>Stop</c> or <c>⏹</c>.
|
|||
/// </summary>
|
|||
MediaStop = 147, |
|||
|
|||
/// <summary>
|
|||
/// Media <c>Next</c> or <c>⏭</c>.
|
|||
/// </summary>
|
|||
MediaTrackNext = 148, |
|||
|
|||
/// <summary>
|
|||
/// Media <c>Previous</c> or <c>⏮</c>.
|
|||
/// </summary>
|
|||
MediaTrackPrevious = 149, |
|||
|
|||
/// <summary>
|
|||
/// <c>Power</c>.
|
|||
/// </summary>
|
|||
Power = 150, |
|||
|
|||
/// <summary>
|
|||
/// <c>Sleep</c>.
|
|||
/// </summary>
|
|||
Sleep = 151, |
|||
|
|||
/// <summary>
|
|||
/// <c>Volume Down</c>.
|
|||
/// </summary>
|
|||
AudioVolumeDown = 152, |
|||
|
|||
/// <summary>
|
|||
/// <c>Mute</c>.
|
|||
/// </summary>
|
|||
AudioVolumeMute = 153, |
|||
|
|||
/// <summary>
|
|||
/// <c>Volume Up</c>.
|
|||
/// </summary>
|
|||
AudioVolumeUp = 154, |
|||
|
|||
/// <summary>
|
|||
/// <c>Wake Up</c>.
|
|||
/// </summary>
|
|||
WakeUp = 155, |
|||
|
|||
|
|||
// ###########
|
|||
// Legacy Keys
|
|||
// ###########
|
|||
|
|||
/// <summary>
|
|||
/// <c>Again</c>.
|
|||
/// Legacy.
|
|||
/// Found on Sun’s USB keyboard.
|
|||
/// </summary>
|
|||
Again = 156, |
|||
|
|||
/// <summary>
|
|||
/// <c>Copy</c>.
|
|||
/// Legacy.
|
|||
/// Found on Sun’s USB keyboard.
|
|||
/// </summary>
|
|||
Copy = 157, |
|||
|
|||
/// <summary>
|
|||
/// <c>Cut</c>.
|
|||
/// Legacy.
|
|||
/// Found on Sun’s USB keyboard.
|
|||
/// </summary>
|
|||
Cut = 158, |
|||
|
|||
/// <summary>
|
|||
/// <c>Find</c>.
|
|||
/// Legacy.
|
|||
/// Found on Sun’s USB keyboard.
|
|||
/// </summary>
|
|||
Find = 159, |
|||
|
|||
/// <summary>
|
|||
/// <c>Open</c>.
|
|||
/// Legacy.
|
|||
/// Found on Sun’s USB keyboard.
|
|||
/// </summary>
|
|||
Open = 160, |
|||
|
|||
/// <summary>
|
|||
/// <c>Paste</c>.
|
|||
/// Legacy.
|
|||
/// Found on Sun’s USB keyboard.
|
|||
/// </summary>
|
|||
Paste = 161, |
|||
|
|||
/// <summary>
|
|||
/// <c>Props</c>.
|
|||
/// Legacy.
|
|||
/// Found on Sun’s USB keyboard.
|
|||
/// </summary>
|
|||
Props = 162, |
|||
|
|||
/// <summary>
|
|||
/// <c>Select</c>.
|
|||
/// Legacy.
|
|||
/// Found on Sun’s USB keyboard.
|
|||
/// </summary>
|
|||
Select = 163, |
|||
|
|||
/// <summary>
|
|||
/// <c>Undo</c>.
|
|||
/// Legacy.
|
|||
/// Found on Sun’s USB keyboard.
|
|||
/// </summary>
|
|||
Undo = 164 |
|||
|
|||
} |
|||
@ -0,0 +1,394 @@ |
|||
namespace Avalonia.Input; |
|||
|
|||
/// <summary>
|
|||
/// Contains extension methods related to <see cref="PhysicalKey"/>.
|
|||
/// </summary>
|
|||
public static class PhysicalKeyExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Maps a physical key to a corresponding key, if possible, on a QWERTY keyboard.
|
|||
/// </summary>
|
|||
/// <param name="physicalKey">the physical key to map.</param>
|
|||
/// <returns>The key corresponding to <paramref name="physicalKey"/>, or <see cref="Key.None"/>.</returns>
|
|||
public static Key ToQwertyKey(this PhysicalKey physicalKey) |
|||
=> physicalKey switch |
|||
{ |
|||
PhysicalKey.None => Key.None, |
|||
|
|||
// Writing System Keys
|
|||
PhysicalKey.Backquote => Key.Oem3, |
|||
PhysicalKey.Backslash => Key.Oem5, |
|||
PhysicalKey.BracketLeft => Key.Oem4, |
|||
PhysicalKey.BracketRight => Key.Oem6, |
|||
PhysicalKey.Comma => Key.OemComma, |
|||
PhysicalKey.Digit0 => Key.D0, |
|||
PhysicalKey.Digit1 => Key.D1, |
|||
PhysicalKey.Digit2 => Key.D2, |
|||
PhysicalKey.Digit3 => Key.D3, |
|||
PhysicalKey.Digit4 => Key.D4, |
|||
PhysicalKey.Digit5 => Key.D5, |
|||
PhysicalKey.Digit6 => Key.D6, |
|||
PhysicalKey.Digit7 => Key.D7, |
|||
PhysicalKey.Digit8 => Key.D8, |
|||
PhysicalKey.Digit9 => Key.D9, |
|||
PhysicalKey.Equal => Key.OemMinus, |
|||
PhysicalKey.IntlBackslash => Key.Oem102, |
|||
PhysicalKey.IntlRo => Key.Oem102, |
|||
PhysicalKey.IntlYen => Key.Oem5, |
|||
PhysicalKey.A => Key.A, |
|||
PhysicalKey.B => Key.B, |
|||
PhysicalKey.C => Key.C, |
|||
PhysicalKey.D => Key.D, |
|||
PhysicalKey.E => Key.E, |
|||
PhysicalKey.F => Key.F, |
|||
PhysicalKey.G => Key.G, |
|||
PhysicalKey.H => Key.H, |
|||
PhysicalKey.I => Key.I, |
|||
PhysicalKey.J => Key.J, |
|||
PhysicalKey.K => Key.K, |
|||
PhysicalKey.L => Key.L, |
|||
PhysicalKey.M => Key.M, |
|||
PhysicalKey.N => Key.N, |
|||
PhysicalKey.O => Key.O, |
|||
PhysicalKey.P => Key.P, |
|||
PhysicalKey.Q => Key.Q, |
|||
PhysicalKey.R => Key.R, |
|||
PhysicalKey.S => Key.S, |
|||
PhysicalKey.T => Key.T, |
|||
PhysicalKey.U => Key.U, |
|||
PhysicalKey.V => Key.V, |
|||
PhysicalKey.W => Key.W, |
|||
PhysicalKey.X => Key.X, |
|||
PhysicalKey.Y => Key.Y, |
|||
PhysicalKey.Z => Key.Z, |
|||
PhysicalKey.Minus => Key.OemMinus, |
|||
PhysicalKey.Period => Key.OemPeriod, |
|||
PhysicalKey.Quote => Key.Oem7, |
|||
PhysicalKey.Semicolon => Key.Oem1, |
|||
PhysicalKey.Slash => Key.Oem2, |
|||
|
|||
// Functional Keys
|
|||
PhysicalKey.AltLeft => Key.LeftAlt, |
|||
PhysicalKey.AltRight => Key.RightAlt, |
|||
PhysicalKey.Backspace => Key.Back, |
|||
PhysicalKey.CapsLock => Key.CapsLock, |
|||
PhysicalKey.ContextMenu => Key.Apps, |
|||
PhysicalKey.ControlLeft => Key.LeftCtrl, |
|||
PhysicalKey.ControlRight => Key.RightCtrl, |
|||
PhysicalKey.Enter => Key.Enter, |
|||
PhysicalKey.MetaLeft => Key.LWin, |
|||
PhysicalKey.MetaRight => Key.RWin, |
|||
PhysicalKey.ShiftLeft => Key.LeftShift, |
|||
PhysicalKey.ShiftRight => Key.RightShift, |
|||
PhysicalKey.Space => Key.Space, |
|||
PhysicalKey.Tab => Key.Tab, |
|||
PhysicalKey.Convert => Key.ImeConvert, |
|||
PhysicalKey.KanaMode => Key.KanaMode, |
|||
PhysicalKey.Lang1 => Key.HangulMode, |
|||
PhysicalKey.Lang2 => Key.HanjaMode, |
|||
PhysicalKey.Lang3 => Key.DbeKatakana, |
|||
PhysicalKey.Lang4 => Key.DbeHiragana, |
|||
PhysicalKey.Lang5 => Key.OemAuto, |
|||
PhysicalKey.NonConvert => Key.ImeNonConvert, |
|||
|
|||
// Control Pad Section
|
|||
PhysicalKey.Delete => Key.Delete, |
|||
PhysicalKey.End => Key.End, |
|||
PhysicalKey.Help => Key.Help, |
|||
PhysicalKey.Home => Key.Home, |
|||
PhysicalKey.Insert => Key.Insert, |
|||
PhysicalKey.PageDown => Key.PageDown, |
|||
PhysicalKey.PageUp => Key.PageUp, |
|||
|
|||
// Arrow Pad Section
|
|||
PhysicalKey.ArrowDown => Key.Down, |
|||
PhysicalKey.ArrowLeft => Key.Left, |
|||
PhysicalKey.ArrowRight => Key.Right, |
|||
PhysicalKey.ArrowUp => Key.Up, |
|||
|
|||
// Numpad Section
|
|||
PhysicalKey.NumLock => Key.NumLock, |
|||
PhysicalKey.NumPad0 => Key.NumPad0, |
|||
PhysicalKey.NumPad1 => Key.NumPad1, |
|||
PhysicalKey.NumPad2 => Key.NumPad2, |
|||
PhysicalKey.NumPad3 => Key.NumPad3, |
|||
PhysicalKey.NumPad4 => Key.NumPad4, |
|||
PhysicalKey.NumPad5 => Key.NumPad5, |
|||
PhysicalKey.NumPad6 => Key.NumPad6, |
|||
PhysicalKey.NumPad7 => Key.NumPad7, |
|||
PhysicalKey.NumPad8 => Key.NumPad8, |
|||
PhysicalKey.NumPad9 => Key.NumPad9, |
|||
PhysicalKey.NumPadAdd => Key.Add, |
|||
PhysicalKey.NumPadClear => Key.Clear, |
|||
PhysicalKey.NumPadComma => Key.AbntC2, |
|||
PhysicalKey.NumPadDecimal => Key.Decimal, |
|||
PhysicalKey.NumPadDivide => Key.Divide, |
|||
PhysicalKey.NumPadEnter => Key.Enter, |
|||
PhysicalKey.NumPadEqual => Key.OemPlus, |
|||
PhysicalKey.NumPadMultiply => Key.Multiply, |
|||
PhysicalKey.NumPadParenLeft => Key.Oem4, |
|||
PhysicalKey.NumPadParenRight => Key.Oem6, |
|||
PhysicalKey.NumPadSubtract => Key.Subtract, |
|||
|
|||
// Function Section
|
|||
PhysicalKey.Escape => Key.Escape, |
|||
PhysicalKey.F1 => Key.F1, |
|||
PhysicalKey.F2 => Key.F2, |
|||
PhysicalKey.F3 => Key.F3, |
|||
PhysicalKey.F4 => Key.F4, |
|||
PhysicalKey.F5 => Key.F5, |
|||
PhysicalKey.F6 => Key.F6, |
|||
PhysicalKey.F7 => Key.F7, |
|||
PhysicalKey.F8 => Key.F8, |
|||
PhysicalKey.F9 => Key.F9, |
|||
PhysicalKey.F10 => Key.F10, |
|||
PhysicalKey.F11 => Key.F11, |
|||
PhysicalKey.F12 => Key.F12, |
|||
PhysicalKey.F13 => Key.F13, |
|||
PhysicalKey.F14 => Key.F14, |
|||
PhysicalKey.F15 => Key.F15, |
|||
PhysicalKey.F16 => Key.F16, |
|||
PhysicalKey.F17 => Key.F17, |
|||
PhysicalKey.F18 => Key.F18, |
|||
PhysicalKey.F19 => Key.F19, |
|||
PhysicalKey.F20 => Key.F20, |
|||
PhysicalKey.F21 => Key.F21, |
|||
PhysicalKey.F22 => Key.F22, |
|||
PhysicalKey.F23 => Key.F23, |
|||
PhysicalKey.F24 => Key.F24, |
|||
PhysicalKey.PrintScreen => Key.PrintScreen, |
|||
PhysicalKey.ScrollLock => Key.Scroll, |
|||
PhysicalKey.Pause => Key.Pause, |
|||
|
|||
// Media Keys
|
|||
PhysicalKey.BrowserBack => Key.BrowserBack, |
|||
PhysicalKey.BrowserFavorites => Key.BrowserFavorites, |
|||
PhysicalKey.BrowserForward => Key.BrowserForward, |
|||
PhysicalKey.BrowserHome => Key.BrowserHome, |
|||
PhysicalKey.BrowserRefresh => Key.BrowserRefresh, |
|||
PhysicalKey.BrowserSearch => Key.BrowserSearch, |
|||
PhysicalKey.BrowserStop => Key.BrowserStop, |
|||
PhysicalKey.Eject => Key.None, |
|||
PhysicalKey.LaunchApp1 => Key.LaunchApplication1, |
|||
PhysicalKey.LaunchApp2 => Key.LaunchApplication2, |
|||
PhysicalKey.LaunchMail => Key.LaunchMail, |
|||
PhysicalKey.MediaPlayPause => Key.MediaPlayPause, |
|||
PhysicalKey.MediaSelect => Key.SelectMedia, |
|||
PhysicalKey.MediaStop => Key.MediaStop, |
|||
PhysicalKey.MediaTrackNext => Key.MediaNextTrack, |
|||
PhysicalKey.MediaTrackPrevious => Key.MediaPreviousTrack, |
|||
PhysicalKey.Power => Key.None, |
|||
PhysicalKey.Sleep => Key.Sleep, |
|||
PhysicalKey.AudioVolumeDown => Key.VolumeDown, |
|||
PhysicalKey.AudioVolumeMute => Key.VolumeMute, |
|||
PhysicalKey.AudioVolumeUp => Key.VolumeUp, |
|||
PhysicalKey.WakeUp => Key.None, |
|||
|
|||
// Legacy Keys
|
|||
PhysicalKey.Again => Key.None, |
|||
PhysicalKey.Copy => Key.OemCopy, |
|||
PhysicalKey.Cut => Key.None, |
|||
PhysicalKey.Find => Key.None, |
|||
PhysicalKey.Open => Key.None, |
|||
PhysicalKey.Paste => Key.None, |
|||
PhysicalKey.Props => Key.None, |
|||
PhysicalKey.Select => Key.Select, |
|||
PhysicalKey.Undo => Key.None, |
|||
|
|||
_ => Key.None |
|||
}; |
|||
|
|||
/// <summary>
|
|||
/// Maps a physical key to a corresponding key symbol, if possible, on a QWERTY keyboard.
|
|||
/// </summary>
|
|||
/// <param name="physicalKey">the physical key to map.</param>
|
|||
/// <param name="useShiftModifier">Indicates whether the Shift key is considered pressed.</param>
|
|||
/// <returns>The key corresponding to <paramref name="physicalKey"/>, or <see cref="Key.None"/>.</returns>
|
|||
public static string? ToQwertyKeySymbol(this PhysicalKey physicalKey, bool useShiftModifier = false) |
|||
=> physicalKey switch |
|||
{ |
|||
PhysicalKey.None => null, |
|||
|
|||
// Writing System Keys
|
|||
PhysicalKey.Backquote => useShiftModifier ? "~" : "`", |
|||
PhysicalKey.Backslash => useShiftModifier ? "|" : "\\", |
|||
PhysicalKey.BracketLeft => useShiftModifier ? "{" : "[", |
|||
PhysicalKey.BracketRight => useShiftModifier ? "}" : "]", |
|||
PhysicalKey.Comma => useShiftModifier ? "<" : ",", |
|||
PhysicalKey.Digit0 => useShiftModifier ? ")" : "0", |
|||
PhysicalKey.Digit1 => useShiftModifier ? "!" : "1", |
|||
PhysicalKey.Digit2 => useShiftModifier ? "@" : "2", |
|||
PhysicalKey.Digit3 => useShiftModifier ? "#" : "3", |
|||
PhysicalKey.Digit4 => useShiftModifier ? "$" : "4", |
|||
PhysicalKey.Digit5 => useShiftModifier ? "%" : "5", |
|||
PhysicalKey.Digit6 => useShiftModifier ? "^" : "6", |
|||
PhysicalKey.Digit7 => useShiftModifier ? "&" : "7", |
|||
PhysicalKey.Digit8 => useShiftModifier ? "*" : "8", |
|||
PhysicalKey.Digit9 => useShiftModifier ? "(" : "9", |
|||
PhysicalKey.Equal => useShiftModifier ? "+" : "=", |
|||
PhysicalKey.IntlBackslash => useShiftModifier ? "|" : "\\", |
|||
PhysicalKey.IntlRo => null, |
|||
PhysicalKey.IntlYen => null, |
|||
PhysicalKey.A => useShiftModifier ? "A" : "a", |
|||
PhysicalKey.B => useShiftModifier ? "B" : "b", |
|||
PhysicalKey.C => useShiftModifier ? "C" : "c", |
|||
PhysicalKey.D => useShiftModifier ? "D" : "d", |
|||
PhysicalKey.E => useShiftModifier ? "E" : "e", |
|||
PhysicalKey.F => useShiftModifier ? "F" : "f", |
|||
PhysicalKey.G => useShiftModifier ? "G" : "g", |
|||
PhysicalKey.H => useShiftModifier ? "H" : "h", |
|||
PhysicalKey.I => useShiftModifier ? "I" : "i", |
|||
PhysicalKey.J => useShiftModifier ? "J" : "j", |
|||
PhysicalKey.K => useShiftModifier ? "K" : "k", |
|||
PhysicalKey.L => useShiftModifier ? "L" : "l", |
|||
PhysicalKey.M => useShiftModifier ? "M" : "m", |
|||
PhysicalKey.N => useShiftModifier ? "N" : "n", |
|||
PhysicalKey.O => useShiftModifier ? "O" : "o", |
|||
PhysicalKey.P => useShiftModifier ? "P" : "p", |
|||
PhysicalKey.Q => useShiftModifier ? "Q" : "q", |
|||
PhysicalKey.R => useShiftModifier ? "R" : "r", |
|||
PhysicalKey.S => useShiftModifier ? "S" : "s", |
|||
PhysicalKey.T => useShiftModifier ? "T" : "t", |
|||
PhysicalKey.U => useShiftModifier ? "U" : "u", |
|||
PhysicalKey.V => useShiftModifier ? "V" : "v", |
|||
PhysicalKey.W => useShiftModifier ? "W" : "w", |
|||
PhysicalKey.X => useShiftModifier ? "X" : "x", |
|||
PhysicalKey.Y => useShiftModifier ? "Y" : "y", |
|||
PhysicalKey.Z => useShiftModifier ? "Z" : "z", |
|||
PhysicalKey.Minus => useShiftModifier ? "_" : "-", |
|||
PhysicalKey.Period => useShiftModifier ? ">" : ".", |
|||
PhysicalKey.Quote => useShiftModifier ? "\"" : "'", |
|||
PhysicalKey.Semicolon => useShiftModifier ? ":" : ";", |
|||
PhysicalKey.Slash => useShiftModifier ? "?" : "/", |
|||
|
|||
// Functional Keys
|
|||
PhysicalKey.AltLeft => null, |
|||
PhysicalKey.AltRight => null, |
|||
PhysicalKey.Backspace => "\b", |
|||
PhysicalKey.CapsLock => null, |
|||
PhysicalKey.ContextMenu => null, |
|||
PhysicalKey.ControlLeft => null, |
|||
PhysicalKey.ControlRight => null, |
|||
PhysicalKey.Enter => "\r", |
|||
PhysicalKey.MetaLeft => null, |
|||
PhysicalKey.MetaRight => null, |
|||
PhysicalKey.ShiftLeft => null, |
|||
PhysicalKey.ShiftRight => null, |
|||
PhysicalKey.Space => " ", |
|||
PhysicalKey.Tab => "\t", |
|||
PhysicalKey.Convert => null, |
|||
PhysicalKey.KanaMode => null, |
|||
PhysicalKey.Lang1 => null, |
|||
PhysicalKey.Lang2 => null, |
|||
PhysicalKey.Lang3 => null, |
|||
PhysicalKey.Lang4 => null, |
|||
PhysicalKey.Lang5 => null, |
|||
PhysicalKey.NonConvert => null, |
|||
|
|||
// Control Pad Section
|
|||
PhysicalKey.Delete => null, |
|||
PhysicalKey.End => null, |
|||
PhysicalKey.Help => null, |
|||
PhysicalKey.Home => null, |
|||
PhysicalKey.Insert => null, |
|||
PhysicalKey.PageDown => null, |
|||
PhysicalKey.PageUp => null, |
|||
|
|||
// Arrow Pad Section
|
|||
PhysicalKey.ArrowDown => null, |
|||
PhysicalKey.ArrowLeft => null, |
|||
PhysicalKey.ArrowRight => null, |
|||
PhysicalKey.ArrowUp => null, |
|||
|
|||
// Numpad Section
|
|||
PhysicalKey.NumLock => null, |
|||
PhysicalKey.NumPad0 => "0", |
|||
PhysicalKey.NumPad1 => "1", |
|||
PhysicalKey.NumPad2 => "2", |
|||
PhysicalKey.NumPad3 => "3", |
|||
PhysicalKey.NumPad4 => "4", |
|||
PhysicalKey.NumPad5 => "5", |
|||
PhysicalKey.NumPad6 => "6", |
|||
PhysicalKey.NumPad7 => "7", |
|||
PhysicalKey.NumPad8 => "8", |
|||
PhysicalKey.NumPad9 => "9", |
|||
PhysicalKey.NumPadAdd => "+", |
|||
PhysicalKey.NumPadClear => null, |
|||
PhysicalKey.NumPadComma => ",", |
|||
PhysicalKey.NumPadDecimal => ".", |
|||
PhysicalKey.NumPadDivide => "/", |
|||
PhysicalKey.NumPadEnter => "\r", |
|||
PhysicalKey.NumPadEqual => "=", |
|||
PhysicalKey.NumPadMultiply => "*", |
|||
PhysicalKey.NumPadParenLeft => "(", |
|||
PhysicalKey.NumPadParenRight => ")", |
|||
PhysicalKey.NumPadSubtract => "-", |
|||
|
|||
// Function Section
|
|||
PhysicalKey.Escape => "\u001B", |
|||
PhysicalKey.F1 => null, |
|||
PhysicalKey.F2 => null, |
|||
PhysicalKey.F3 => null, |
|||
PhysicalKey.F4 => null, |
|||
PhysicalKey.F5 => null, |
|||
PhysicalKey.F6 => null, |
|||
PhysicalKey.F7 => null, |
|||
PhysicalKey.F8 => null, |
|||
PhysicalKey.F9 => null, |
|||
PhysicalKey.F10 => null, |
|||
PhysicalKey.F11 => null, |
|||
PhysicalKey.F12 => null, |
|||
PhysicalKey.F13 => null, |
|||
PhysicalKey.F14 => null, |
|||
PhysicalKey.F15 => null, |
|||
PhysicalKey.F16 => null, |
|||
PhysicalKey.F17 => null, |
|||
PhysicalKey.F18 => null, |
|||
PhysicalKey.F19 => null, |
|||
PhysicalKey.F20 => null, |
|||
PhysicalKey.F21 => null, |
|||
PhysicalKey.F22 => null, |
|||
PhysicalKey.F23 => null, |
|||
PhysicalKey.F24 => null, |
|||
PhysicalKey.PrintScreen => null, |
|||
PhysicalKey.ScrollLock => null, |
|||
PhysicalKey.Pause => null, |
|||
|
|||
// Media Keys
|
|||
PhysicalKey.BrowserBack => null, |
|||
PhysicalKey.BrowserFavorites => null, |
|||
PhysicalKey.BrowserForward => null, |
|||
PhysicalKey.BrowserHome => null, |
|||
PhysicalKey.BrowserRefresh => null, |
|||
PhysicalKey.BrowserSearch => null, |
|||
PhysicalKey.BrowserStop => null, |
|||
PhysicalKey.Eject => null, |
|||
PhysicalKey.LaunchApp1 => null, |
|||
PhysicalKey.LaunchApp2 => null, |
|||
PhysicalKey.LaunchMail => null, |
|||
PhysicalKey.MediaPlayPause => null, |
|||
PhysicalKey.MediaSelect => null, |
|||
PhysicalKey.MediaStop => null, |
|||
PhysicalKey.MediaTrackNext => null, |
|||
PhysicalKey.MediaTrackPrevious => null, |
|||
PhysicalKey.Power => null, |
|||
PhysicalKey.Sleep => null, |
|||
PhysicalKey.AudioVolumeDown => null, |
|||
PhysicalKey.AudioVolumeMute => null, |
|||
PhysicalKey.AudioVolumeUp => null, |
|||
PhysicalKey.WakeUp => null, |
|||
|
|||
// Legacy Keys
|
|||
PhysicalKey.Again => null, |
|||
PhysicalKey.Copy => null, |
|||
PhysicalKey.Cut => null, |
|||
PhysicalKey.Find => null, |
|||
PhysicalKey.Open => null, |
|||
PhysicalKey.Paste => null, |
|||
PhysicalKey.Props => null, |
|||
PhysicalKey.Select => null, |
|||
PhysicalKey.Undo => null, |
|||
|
|||
_ => null |
|||
}; |
|||
} |
|||
@ -1,2 +0,0 @@ |
|||
#!/bin/sh |
|||
dotnet msbuild /t:Clean,GenerateSharpGenBindings |
|||
@ -0,0 +1,435 @@ |
|||
using System.Collections.Generic; |
|||
using Avalonia.Input; |
|||
|
|||
namespace Avalonia.Browser |
|||
{ |
|||
internal static class KeyInterop |
|||
{ |
|||
// https://www.w3.org/TR/uievents-code/
|
|||
// https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values
|
|||
// This list has the same order as the PhysicalKey enum.
|
|||
private static readonly Dictionary<string, PhysicalKey> s_physicalKeyFromDomCode = new() |
|||
{ |
|||
{ "Unidentified", PhysicalKey.None }, |
|||
|
|||
// Writing System Keys
|
|||
{ "Backquote", PhysicalKey.Backquote }, |
|||
{ "Backslash", PhysicalKey.Backslash }, |
|||
{ "BracketLeft", PhysicalKey.BracketLeft }, |
|||
{ "BracketRight", PhysicalKey.BracketRight }, |
|||
{ "Comma", PhysicalKey.Comma }, |
|||
{ "Digit0", PhysicalKey.Digit0 }, |
|||
{ "Digit1", PhysicalKey.Digit1 }, |
|||
{ "Digit2", PhysicalKey.Digit2 }, |
|||
{ "Digit3", PhysicalKey.Digit3 }, |
|||
{ "Digit4", PhysicalKey.Digit4 }, |
|||
{ "Digit5", PhysicalKey.Digit5 }, |
|||
{ "Digit6", PhysicalKey.Digit6 }, |
|||
{ "Digit7", PhysicalKey.Digit7 }, |
|||
{ "Digit8", PhysicalKey.Digit8 }, |
|||
{ "Digit9", PhysicalKey.Digit9 }, |
|||
{ "Equal", PhysicalKey.Equal }, |
|||
{ "IntlBackslash", PhysicalKey.IntlBackslash }, |
|||
{ "IntlRo", PhysicalKey.IntlRo }, |
|||
{ "IntlYen", PhysicalKey.IntlYen }, |
|||
{ "KeyA", PhysicalKey.A }, |
|||
{ "KeyB", PhysicalKey.B }, |
|||
{ "KeyC", PhysicalKey.C }, |
|||
{ "KeyD", PhysicalKey.D }, |
|||
{ "KeyE", PhysicalKey.E }, |
|||
{ "KeyF", PhysicalKey.F }, |
|||
{ "KeyG", PhysicalKey.G }, |
|||
{ "KeyH", PhysicalKey.H }, |
|||
{ "KeyI", PhysicalKey.I }, |
|||
{ "KeyJ", PhysicalKey.J }, |
|||
{ "KeyK", PhysicalKey.K }, |
|||
{ "KeyL", PhysicalKey.L }, |
|||
{ "KeyM", PhysicalKey.M }, |
|||
{ "KeyN", PhysicalKey.N }, |
|||
{ "KeyO", PhysicalKey.O }, |
|||
{ "KeyP", PhysicalKey.P }, |
|||
{ "KeyQ", PhysicalKey.Q }, |
|||
{ "KeyR", PhysicalKey.R }, |
|||
{ "KeyS", PhysicalKey.S }, |
|||
{ "KeyT", PhysicalKey.T }, |
|||
{ "KeyU", PhysicalKey.U }, |
|||
{ "KeyV", PhysicalKey.V }, |
|||
{ "KeyW", PhysicalKey.W }, |
|||
{ "KeyX", PhysicalKey.X }, |
|||
{ "KeyY", PhysicalKey.Y }, |
|||
{ "KeyZ", PhysicalKey.Z }, |
|||
{ "Minus", PhysicalKey.Minus }, |
|||
{ "Period", PhysicalKey.Period }, |
|||
{ "Quote", PhysicalKey.Quote }, |
|||
{ "Semicolon", PhysicalKey.Semicolon }, |
|||
{ "Slash", PhysicalKey.Slash }, |
|||
|
|||
// Functional Keys
|
|||
{ "AltLeft", PhysicalKey.AltLeft }, |
|||
{ "AltRight", PhysicalKey.AltRight }, |
|||
{ "Backspace", PhysicalKey.Backspace }, |
|||
{ "CapsLock", PhysicalKey.CapsLock }, |
|||
{ "ContextMenu", PhysicalKey.ContextMenu }, |
|||
{ "ControlLeft", PhysicalKey.ControlLeft }, |
|||
{ "ControlRight", PhysicalKey.ControlRight }, |
|||
{ "Enter", PhysicalKey.Enter }, |
|||
{ "MetaLeft", PhysicalKey.MetaLeft }, |
|||
{ "OSLeft", PhysicalKey.MetaLeft }, |
|||
{ "MetaRight", PhysicalKey.MetaRight }, |
|||
{ "OSRight", PhysicalKey.MetaRight }, |
|||
{ "ShiftLeft", PhysicalKey.ShiftLeft }, |
|||
{ "ShiftRight", PhysicalKey.ShiftRight }, |
|||
{ "Space", PhysicalKey.Space }, |
|||
{ "Tab", PhysicalKey.Tab }, |
|||
{ "Convert", PhysicalKey.Convert }, |
|||
{ "KanaMode", PhysicalKey.KanaMode }, |
|||
{ "Lang1", PhysicalKey.Lang1 }, |
|||
{ "Lang2", PhysicalKey.Lang2 }, |
|||
{ "Lang3", PhysicalKey.Lang3 }, |
|||
{ "Lang4", PhysicalKey.Lang4 }, |
|||
{ "Lang5", PhysicalKey.Lang5 }, |
|||
{ "NonConvert", PhysicalKey.NonConvert }, |
|||
|
|||
// Control Pad Section
|
|||
{ "Delete", PhysicalKey.Delete }, |
|||
{ "End", PhysicalKey.End }, |
|||
{ "Help", PhysicalKey.Help }, |
|||
{ "Home", PhysicalKey.Home }, |
|||
{ "Insert", PhysicalKey.Insert }, |
|||
{ "PageDown", PhysicalKey.PageDown }, |
|||
{ "PageUp", PhysicalKey.PageUp }, |
|||
|
|||
// Arrow Pad Section
|
|||
{ "ArrowDown", PhysicalKey.ArrowDown }, |
|||
{ "ArrowLeft", PhysicalKey.ArrowLeft }, |
|||
{ "ArrowRight", PhysicalKey.ArrowRight }, |
|||
{ "ArrowUp", PhysicalKey.ArrowUp }, |
|||
|
|||
// Numpad Section
|
|||
{ "NumLock", PhysicalKey.NumLock }, |
|||
{ "Numpad0", PhysicalKey.NumPad0 }, |
|||
{ "Numpad1", PhysicalKey.NumPad1 }, |
|||
{ "Numpad2", PhysicalKey.NumPad2 }, |
|||
{ "Numpad3", PhysicalKey.NumPad3 }, |
|||
{ "Numpad4", PhysicalKey.NumPad4 }, |
|||
{ "Numpad5", PhysicalKey.NumPad5 }, |
|||
{ "Numpad6", PhysicalKey.NumPad6 }, |
|||
{ "Numpad7", PhysicalKey.NumPad7 }, |
|||
{ "Numpad8", PhysicalKey.NumPad8 }, |
|||
{ "Numpad9", PhysicalKey.NumPad9 }, |
|||
{ "NumpadAdd", PhysicalKey.NumPadAdd }, |
|||
{ "NumpadClear", PhysicalKey.NumPadClear }, |
|||
{ "NumpadComma", PhysicalKey.NumPadComma }, |
|||
{ "NumpadDecimal", PhysicalKey.NumPadDecimal }, |
|||
{ "NumpadDivide", PhysicalKey.NumPadDivide }, |
|||
{ "NumpadEnter", PhysicalKey.NumPadEnter }, |
|||
{ "NumpadEqual", PhysicalKey.NumPadEqual }, |
|||
{ "NumpadMultiply", PhysicalKey.NumPadMultiply }, |
|||
{ "NumpadParenLeft", PhysicalKey.NumPadParenLeft }, |
|||
{ "NumpadParenRight", PhysicalKey.NumPadParenRight }, |
|||
{ "NumpadSubtract", PhysicalKey.NumPadSubtract }, |
|||
|
|||
// Function Section
|
|||
{ "Escape", PhysicalKey.Escape }, |
|||
{ "F1", PhysicalKey.F1 }, |
|||
{ "F2", PhysicalKey.F2 }, |
|||
{ "F3", PhysicalKey.F3 }, |
|||
{ "F4", PhysicalKey.F4 }, |
|||
{ "F5", PhysicalKey.F5 }, |
|||
{ "F6", PhysicalKey.F6 }, |
|||
{ "F7", PhysicalKey.F7 }, |
|||
{ "F8", PhysicalKey.F8 }, |
|||
{ "F9", PhysicalKey.F9 }, |
|||
{ "F10", PhysicalKey.F10 }, |
|||
{ "F11", PhysicalKey.F11 }, |
|||
{ "F12", PhysicalKey.F12 }, |
|||
{ "F13", PhysicalKey.F13 }, |
|||
{ "F14", PhysicalKey.F14 }, |
|||
{ "F15", PhysicalKey.F15 }, |
|||
{ "F16", PhysicalKey.F16 }, |
|||
{ "F17", PhysicalKey.F17 }, |
|||
{ "F18", PhysicalKey.F18 }, |
|||
{ "F19", PhysicalKey.F19 }, |
|||
{ "F20", PhysicalKey.F20 }, |
|||
{ "F21", PhysicalKey.F21 }, |
|||
{ "F22", PhysicalKey.F22 }, |
|||
{ "F23", PhysicalKey.F23 }, |
|||
{ "F24", PhysicalKey.F24 }, |
|||
{ "PrintScreen", PhysicalKey.PrintScreen }, |
|||
{ "ScrollLock", PhysicalKey.ScrollLock }, |
|||
{ "Pause", PhysicalKey.Pause }, |
|||
|
|||
// Media Keys
|
|||
{ "BrowserBack", PhysicalKey.BrowserBack }, |
|||
{ "BrowserFavorites", PhysicalKey.BrowserFavorites }, |
|||
{ "BrowserForward", PhysicalKey.BrowserForward }, |
|||
{ "BrowserHome", PhysicalKey.BrowserHome }, |
|||
{ "BrowserRefresh", PhysicalKey.BrowserRefresh }, |
|||
{ "BrowserSearch", PhysicalKey.BrowserSearch }, |
|||
{ "BrowserStop", PhysicalKey.BrowserStop }, |
|||
{ "Abort", PhysicalKey.BrowserStop }, |
|||
{ "Eject", PhysicalKey.Eject }, |
|||
{ "LaunchApp1", PhysicalKey.LaunchApp1 }, |
|||
{ "LaunchApp2", PhysicalKey.LaunchApp2 }, |
|||
{ "LaunchMail", PhysicalKey.LaunchMail }, |
|||
{ "MediaPlayPause", PhysicalKey.MediaPlayPause }, |
|||
{ "MediaSelect", PhysicalKey.MediaSelect }, |
|||
{ "MediaStop", PhysicalKey.MediaStop }, |
|||
{ "MediaTrackNext", PhysicalKey.MediaTrackNext }, |
|||
{ "MediaTrackPrevious", PhysicalKey.MediaTrackPrevious }, |
|||
{ "Power", PhysicalKey.Power }, |
|||
{ "Sleep", PhysicalKey.Sleep }, |
|||
{ "AudioVolumeDown", PhysicalKey.AudioVolumeDown }, |
|||
{ "VolumeDown", PhysicalKey.AudioVolumeDown }, |
|||
{ "AudioVolumeMute", PhysicalKey.AudioVolumeMute }, |
|||
{ "VolumeMute", PhysicalKey.AudioVolumeMute }, |
|||
{ "AudioVolumeUp", PhysicalKey.AudioVolumeUp }, |
|||
{ "VolumeUp", PhysicalKey.AudioVolumeUp }, |
|||
{ "WakeUp", PhysicalKey.WakeUp }, |
|||
|
|||
// Legacy Keys
|
|||
{ "Copy", PhysicalKey.Copy }, |
|||
{ "Cut", PhysicalKey.Cut }, |
|||
{ "Find", PhysicalKey.Find }, |
|||
{ "Open", PhysicalKey.Open }, |
|||
{ "Paste", PhysicalKey.Paste }, |
|||
{ "Props", PhysicalKey.Props }, |
|||
{ "Select", PhysicalKey.Select }, |
|||
{ "Undo", PhysicalKey.Undo } |
|||
}; |
|||
|
|||
public static PhysicalKey PhysicalKeyFromDomCode(string? domCode) |
|||
=> !string.IsNullOrEmpty(domCode) && s_physicalKeyFromDomCode.TryGetValue(domCode, out var physicalKey) ? |
|||
physicalKey : |
|||
PhysicalKey.None; |
|||
|
|||
// https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values
|
|||
private static readonly Dictionary<string, Key> s_keyFromDomKey = new() |
|||
{ |
|||
// Alphabetic keys
|
|||
{ "A", Key.A }, |
|||
{ "B", Key.B }, |
|||
{ "C", Key.C }, |
|||
{ "D", Key.D }, |
|||
{ "E", Key.E }, |
|||
{ "F", Key.F }, |
|||
{ "G", Key.G }, |
|||
{ "H", Key.H }, |
|||
{ "I", Key.I }, |
|||
{ "J", Key.J }, |
|||
{ "K", Key.K }, |
|||
{ "L", Key.L }, |
|||
{ "M", Key.M }, |
|||
{ "N", Key.N }, |
|||
{ "O", Key.O }, |
|||
{ "P", Key.P }, |
|||
{ "Q", Key.Q }, |
|||
{ "R", Key.R }, |
|||
{ "S", Key.S }, |
|||
{ "T", Key.T }, |
|||
{ "U", Key.U }, |
|||
{ "V", Key.V }, |
|||
{ "W", Key.W }, |
|||
{ "X", Key.X }, |
|||
{ "Y", Key.Y }, |
|||
{ "Z", Key.Z }, |
|||
{ "a", Key.A }, |
|||
{ "b", Key.B }, |
|||
{ "c", Key.C }, |
|||
{ "d", Key.D }, |
|||
{ "e", Key.E }, |
|||
{ "f", Key.F }, |
|||
{ "g", Key.G }, |
|||
{ "h", Key.H }, |
|||
{ "i", Key.I }, |
|||
{ "j", Key.J }, |
|||
{ "k", Key.K }, |
|||
{ "l", Key.L }, |
|||
{ "m", Key.M }, |
|||
{ "n", Key.N }, |
|||
{ "o", Key.O }, |
|||
{ "p", Key.P }, |
|||
{ "q", Key.Q }, |
|||
{ "r", Key.R }, |
|||
{ "s", Key.S }, |
|||
{ "t", Key.T }, |
|||
{ "u", Key.U }, |
|||
{ "v", Key.V }, |
|||
{ "w", Key.W }, |
|||
{ "x", Key.X }, |
|||
{ "y", Key.Y }, |
|||
{ "z", Key.Z }, |
|||
|
|||
// Modifier keys (left/right keys are handled separately)
|
|||
{ "AltGr", Key.RightAlt }, |
|||
{ "CapsLock", Key.CapsLock }, |
|||
{ "NumLock", Key.NumLock }, |
|||
{ "ScrollLock", Key.Scroll }, |
|||
|
|||
// Whitespace keys
|
|||
{ "Enter", Key.Enter }, |
|||
{ "Tab", Key.Tab }, |
|||
{ " ", Key.Space }, |
|||
|
|||
// Navigation keys
|
|||
{ "ArrowDown", Key.Down }, |
|||
{ "ArrowLeft", Key.Left }, |
|||
{ "ArrowRight", Key.Right }, |
|||
{ "ArrowUp", Key.Up }, |
|||
{ "End", Key.End }, |
|||
{ "Home", Key.Home }, |
|||
{ "PageDown", Key.PageDown }, |
|||
{ "PageUp", Key.PageUp }, |
|||
|
|||
// Editing keys
|
|||
{ "Backspace", Key.Back }, |
|||
{ "Clear", Key.Clear }, |
|||
{ "CrSel", Key.CrSel }, |
|||
{ "Delete", Key.Delete }, |
|||
{ "EraseEof", Key.EraseEof }, |
|||
{ "ExSel", Key.ExSel }, |
|||
{ "Insert", Key.Insert }, |
|||
|
|||
// UI keys
|
|||
{ "Accept", Key.ImeAccept }, |
|||
{ "Attn", Key.OemAttn }, |
|||
{ "Cancel", Key.Cancel }, |
|||
{ "ContextMenu", Key.Apps }, |
|||
{ "Escape", Key.Escape }, |
|||
{ "Execute", Key.Execute }, |
|||
{ "Finish", Key.OemFinish }, |
|||
{ "Help", Key.Help }, |
|||
{ "Pause", Key.Pause }, |
|||
{ "Play", Key.Play }, |
|||
{ "Select", Key.Select }, |
|||
{ "ZoomIn", Key.Zoom }, |
|||
|
|||
// Device keys
|
|||
{ "PrintScreen", Key.PrintScreen }, |
|||
|
|||
// IME keys
|
|||
{ "Convert", Key.ImeConvert }, |
|||
{ "FinalMode", Key.FinalMode }, |
|||
{ "ModeChange", Key.ImeModeChange }, |
|||
{ "NonConvert", Key.ImeNonConvert }, |
|||
{ "Process", Key.ImeProcessed }, |
|||
{ "HangulMode", Key.HangulMode }, |
|||
{ "HanjaMode", Key.HanjaMode }, |
|||
{ "JunjaMode", Key.JunjaMode }, |
|||
{ "Hankaku", Key.OemAuto }, |
|||
{ "Hiragana", Key.DbeHiragana }, |
|||
{ "KanaMode", Key.KanaMode }, |
|||
{ "KanjiMode", Key.KanjiMode }, |
|||
{ "Katakana", Key.DbeKatakana }, |
|||
{ "Romaji", Key.OemBackTab }, |
|||
{ "Zenkaku", Key.OemEnlw }, |
|||
|
|||
// Function keys
|
|||
{ "F1", Key.F1 }, |
|||
{ "F2", Key.F2 }, |
|||
{ "F3", Key.F3 }, |
|||
{ "F4", Key.F4 }, |
|||
{ "F5", Key.F5 }, |
|||
{ "F6", Key.F6 }, |
|||
{ "F7", Key.F7 }, |
|||
{ "F8", Key.F8 }, |
|||
{ "F9", Key.F9 }, |
|||
{ "F10", Key.F10 }, |
|||
{ "F11", Key.F11 }, |
|||
{ "F12", Key.F12 }, |
|||
{ "F13", Key.F13 }, |
|||
{ "F14", Key.F14 }, |
|||
{ "F15", Key.F15 }, |
|||
{ "F16", Key.F16 }, |
|||
{ "F17", Key.F17 }, |
|||
{ "F18", Key.F18 }, |
|||
{ "F19", Key.F19 }, |
|||
{ "F20", Key.F20 }, |
|||
|
|||
// Multimedia keys
|
|||
{ "MediaPlayPause", Key.MediaPlayPause }, |
|||
{ "MediaStop", Key.MediaStop }, |
|||
{ "MediaTrackNext", Key.MediaNextTrack }, |
|||
{ "MediaTrackPrevious", Key.MediaPreviousTrack }, |
|||
|
|||
// Audio control keys
|
|||
{ "AudioVolumeDown", Key.VolumeDown }, |
|||
{ "AudioVolumeMute", Key.VolumeMute }, |
|||
{ "AudioVolumeUp", Key.VolumeUp }, |
|||
|
|||
// Application selector keys
|
|||
{ "LaunchCalculator", Key.LaunchApplication2 }, |
|||
{ "LaunchMail", Key.LaunchMail }, |
|||
{ "LaunchMyComputer", Key.LaunchApplication1 }, |
|||
{ "LaunchApplication1", Key.LaunchApplication1 }, |
|||
{ "LaunchApplication2", Key.LaunchApplication2 }, |
|||
|
|||
// Browser control keys
|
|||
{ "BrowserBack", Key.BrowserBack }, |
|||
{ "BrowserFavorites", Key.BrowserFavorites }, |
|||
{ "BrowserForward", Key.BrowserForward }, |
|||
{ "BrowserHome", Key.BrowserHome }, |
|||
{ "BrowserRefresh", Key.BrowserRefresh }, |
|||
{ "BrowserSearch", Key.BrowserSearch }, |
|||
{ "BrowserStop", Key.BrowserStop }, |
|||
|
|||
// Numeric keypad keys
|
|||
{ "Decimal", Key.Decimal }, |
|||
{ "Multiply", Key.Multiply }, |
|||
{ "Add", Key.Add }, |
|||
{ "Divide", Key.Divide }, |
|||
{ "Subtract", Key.Subtract }, |
|||
{ "Separator", Key.Separator }, |
|||
}; |
|||
|
|||
public static Key KeyFromDomKey(string? domKey, PhysicalKey physicalKey) |
|||
{ |
|||
if (string.IsNullOrEmpty(domKey)) |
|||
return Key.None; |
|||
|
|||
if (s_keyFromDomKey.TryGetValue(domKey, out var key)) |
|||
return key; |
|||
|
|||
key = domKey switch |
|||
{ |
|||
"Alt" => physicalKey == PhysicalKey.AltRight ? Key.RightAlt : Key.LeftAlt, |
|||
"Control" => physicalKey == PhysicalKey.ControlRight ? Key.RightCtrl : Key.LeftCtrl, |
|||
"Shift" => physicalKey == PhysicalKey.ShiftRight ? Key.RightShift : Key.LeftShift, |
|||
"Meta" => physicalKey == PhysicalKey.MetaRight ? Key.RWin : Key.LWin, |
|||
"0" => physicalKey == PhysicalKey.NumPad0 ? Key.NumPad0 : Key.D0, |
|||
"1" => physicalKey == PhysicalKey.NumPad1 ? Key.NumPad1 : Key.D1, |
|||
"2" => physicalKey == PhysicalKey.NumPad2 ? Key.NumPad2 : Key.D2, |
|||
"3" => physicalKey == PhysicalKey.NumPad3 ? Key.NumPad3 : Key.D3, |
|||
"4" => physicalKey == PhysicalKey.NumPad4 ? Key.NumPad4 : Key.D4, |
|||
"5" => physicalKey == PhysicalKey.NumPad5 ? Key.NumPad5 : Key.D5, |
|||
"6" => physicalKey == PhysicalKey.NumPad6 ? Key.NumPad6 : Key.D6, |
|||
"7" => physicalKey == PhysicalKey.NumPad7 ? Key.NumPad7 : Key.D7, |
|||
"8" => physicalKey == PhysicalKey.NumPad8 ? Key.NumPad8 : Key.D8, |
|||
"9" => physicalKey == PhysicalKey.NumPad9 ? Key.NumPad9 : Key.D9, |
|||
"+" => physicalKey == PhysicalKey.NumPadAdd ? Key.Add : Key.OemPlus, |
|||
"-" => physicalKey == PhysicalKey.NumPadSubtract ? Key.Subtract : Key.OemMinus, |
|||
"*" => physicalKey == PhysicalKey.NumPadMultiply ? Key.Multiply : Key.None, |
|||
"/" => physicalKey == PhysicalKey.NumPadDivide ? Key.Divide : Key.None, |
|||
_ => Key.None |
|||
}; |
|||
|
|||
if (key != Key.None) |
|||
return key; |
|||
|
|||
return physicalKey.ToQwertyKey(); |
|||
} |
|||
|
|||
public static string? KeySymbolFromDomKey(string? domKey) |
|||
{ |
|||
if (string.IsNullOrEmpty(domKey)) |
|||
return null; |
|||
|
|||
return domKey.Length switch |
|||
{ |
|||
1 => domKey, |
|||
2 when char.IsSurrogatePair(domKey[0], domKey[1]) => domKey, |
|||
_ => null |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
@ -1,129 +0,0 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
using Avalonia.Input; |
|||
|
|||
namespace Avalonia.Browser |
|||
{ |
|||
internal static class Keycodes |
|||
{ |
|||
public static Dictionary<string, Key> KeyCodes = new() |
|||
{ |
|||
{ "Escape", Key.Escape }, |
|||
{ "Digit1", Key.D1 }, |
|||
{ "Digit2", Key.D2 }, |
|||
{ "Digit3", Key.D3 }, |
|||
{ "Digit4", Key.D4 }, |
|||
{ "Digit5", Key.D5 }, |
|||
{ "Digit6", Key.D6 }, |
|||
{ "Digit7", Key.D7 }, |
|||
{ "Digit8", Key.D8 }, |
|||
{ "Digit9", Key.D9 }, |
|||
{ "Digit0", Key.D0 }, |
|||
{ "Minus", Key.OemMinus }, |
|||
//{ "Equal" , Key. },
|
|||
{ "Backspace", Key.Back }, |
|||
{ "Tab", Key.Tab }, |
|||
{ "KeyQ", Key.Q }, |
|||
{ "KeyW", Key.W }, |
|||
{ "KeyE", Key.E }, |
|||
{ "KeyR", Key.R }, |
|||
{ "KeyT", Key.T }, |
|||
{ "KeyY", Key.Y }, |
|||
{ "KeyU", Key.U }, |
|||
{ "KeyI", Key.I }, |
|||
{ "KeyO", Key.O }, |
|||
{ "KeyP", Key.P }, |
|||
{ "BracketLeft", Key.OemOpenBrackets }, |
|||
{ "BracketRight", Key.OemCloseBrackets }, |
|||
{ "Enter", Key.Enter }, |
|||
{ "ControlLeft", Key.LeftCtrl }, |
|||
{ "KeyA", Key.A }, |
|||
{ "KeyS", Key.S }, |
|||
{ "KeyD", Key.D }, |
|||
{ "KeyF", Key.F }, |
|||
{ "KeyG", Key.G }, |
|||
{ "KeyH", Key.H }, |
|||
{ "KeyJ", Key.J }, |
|||
{ "KeyK", Key.K }, |
|||
{ "KeyL", Key.L }, |
|||
{ "Semicolon", Key.OemSemicolon }, |
|||
{ "Quote", Key.OemQuotes }, |
|||
//{ "Backquote" , Key. },
|
|||
{ "ShiftLeft", Key.LeftShift }, |
|||
{ "Backslash", Key.OemBackslash }, |
|||
{ "KeyZ", Key.Z }, |
|||
{ "KeyX", Key.X }, |
|||
{ "KeyC", Key.C }, |
|||
{ "KeyV", Key.V }, |
|||
{ "KeyB", Key.B }, |
|||
{ "KeyN", Key.N }, |
|||
{ "KeyM", Key.M }, |
|||
{ "Comma", Key.OemComma }, |
|||
{ "Period", Key.OemPeriod }, |
|||
//{ "Slash" , Key. },
|
|||
{ "ShiftRight", Key.RightShift }, |
|||
{ "NumpadMultiply", Key.Multiply }, |
|||
{ "AltLeft", Key.LeftAlt }, |
|||
{ "Space", Key.Space }, |
|||
{ "CapsLock", Key.CapsLock }, |
|||
{ "F1", Key.F1 }, |
|||
{ "F2", Key.F2 }, |
|||
{ "F3", Key.F3 }, |
|||
{ "F4", Key.F4 }, |
|||
{ "F5", Key.F5 }, |
|||
{ "F6", Key.F6 }, |
|||
{ "F7", Key.F7 }, |
|||
{ "F8", Key.F8 }, |
|||
{ "F9", Key.F9 }, |
|||
{ "F10", Key.F10 }, |
|||
{ "NumLock", Key.NumLock }, |
|||
{ "ScrollLock", Key.Scroll }, |
|||
{ "Numpad7", Key.NumPad7 }, |
|||
{ "Numpad8", Key.NumPad8 }, |
|||
{ "Numpad9", Key.NumPad9 }, |
|||
{ "NumpadSubtract", Key.Subtract }, |
|||
{ "Numpad4", Key.NumPad4 }, |
|||
{ "Numpad5", Key.NumPad5 }, |
|||
{ "Numpad6", Key.NumPad6 }, |
|||
{ "NumpadAdd", Key.Add }, |
|||
{ "Numpad1", Key.NumPad1 }, |
|||
{ "Numpad2", Key.NumPad2 }, |
|||
{ "Numpad3", Key.NumPad3 }, |
|||
{ "Numpad0", Key.NumPad0 }, |
|||
{ "NumpadDecimal", Key.Decimal }, |
|||
{ "Unidentified", Key.NoName }, |
|||
//{ "IntlBackslash" , Key.bac },
|
|||
{ "F11", Key.F11 }, |
|||
{ "F12", Key.F12 }, |
|||
//{ "IntlRo" , Key.Ro },
|
|||
//{ "Unidentified" , Key. },
|
|||
{ "Convert", Key.ImeConvert }, |
|||
{ "KanaMode", Key.KanaMode }, |
|||
{ "NonConvert", Key.ImeNonConvert }, |
|||
//{ "Unidentified" , Key. },
|
|||
{ "NumpadEnter", Key.Enter }, |
|||
{ "ControlRight", Key.RightCtrl }, |
|||
{ "NumpadDivide", Key.Divide }, |
|||
{ "PrintScreen", Key.PrintScreen }, |
|||
{ "AltRight", Key.RightAlt }, |
|||
//{ "Unidentified" , Key. },
|
|||
{ "Home", Key.Home }, |
|||
{ "ArrowUp", Key.Up }, |
|||
{ "PageUp", Key.PageUp }, |
|||
{ "ArrowLeft", Key.Left }, |
|||
{ "ArrowRight", Key.Right }, |
|||
{ "End", Key.End }, |
|||
{ "ArrowDown", Key.Down }, |
|||
{ "PageDown", Key.PageDown }, |
|||
{ "Insert", Key.Insert }, |
|||
{ "Delete", Key.Delete }, |
|||
//{ "Unidentified" , Key. },
|
|||
{ "AudioVolumeMute", Key.VolumeMute }, |
|||
{ "AudioVolumeDown", Key.VolumeDown }, |
|||
{ "AudioVolumeUp", Key.VolumeUp }, |
|||
//{ "NumpadEqual" , Key. },
|
|||
{ "Pause", Key.Pause }, |
|||
{ "NumpadComma", Key.OemComma } |
|||
}; |
|||
} |
|||
} |
|||
@ -1,92 +1,50 @@ |
|||
using Avalonia.Controls; |
|||
using Avalonia.Input; |
|||
using Avalonia.Utilities; |
|||
using Avalonia.Win32.Interop; |
|||
using static Avalonia.Win32.Interop.UnmanagedMethods; |
|||
using static Avalonia.Win32.Interop.UnmanagedMethods.VirtualKeyStates; |
|||
|
|||
namespace Avalonia.Win32.Input |
|||
{ |
|||
internal class WindowsKeyboardDevice : KeyboardDevice |
|||
internal sealed class WindowsKeyboardDevice : KeyboardDevice |
|||
{ |
|||
private readonly byte[] _keyStates = new byte[256]; |
|||
public new static WindowsKeyboardDevice Instance { get; } = new(); |
|||
|
|||
public new static WindowsKeyboardDevice Instance { get; } = new WindowsKeyboardDevice(); |
|||
|
|||
public RawInputModifiers Modifiers |
|||
public unsafe RawInputModifiers Modifiers |
|||
{ |
|||
get |
|||
{ |
|||
UpdateKeyStates(); |
|||
RawInputModifiers result = 0; |
|||
|
|||
if (IsDown(Key.LeftAlt) || IsDown(Key.RightAlt)) |
|||
fixed (byte* keyStates = stackalloc byte[256]) |
|||
{ |
|||
result |= RawInputModifiers.Alt; |
|||
} |
|||
GetKeyboardState(keyStates); |
|||
|
|||
if (IsDown(Key.LeftCtrl) || IsDown(Key.RightCtrl)) |
|||
{ |
|||
result |= RawInputModifiers.Control; |
|||
} |
|||
var result = RawInputModifiers.None; |
|||
|
|||
if (IsDown(Key.LeftShift) || IsDown(Key.RightShift)) |
|||
{ |
|||
result |= RawInputModifiers.Shift; |
|||
} |
|||
if (((keyStates[(int)VK_LMENU] | keyStates[(int)VK_RMENU]) & 0x80) != 0) |
|||
{ |
|||
result |= RawInputModifiers.Alt; |
|||
} |
|||
|
|||
if (IsDown(Key.LWin) || IsDown(Key.RWin)) |
|||
{ |
|||
result |= RawInputModifiers.Meta; |
|||
} |
|||
if (((keyStates[(int)VK_LCONTROL] | keyStates[(int)VK_RCONTROL]) & 0x80) != 0) |
|||
{ |
|||
result |= RawInputModifiers.Control; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
if (((keyStates[(int)VK_LSHIFT] | keyStates[(int)VK_RSHIFT]) & 0x80) != 0) |
|||
{ |
|||
result |= RawInputModifiers.Shift; |
|||
} |
|||
|
|||
public void WindowActivated(Window window) |
|||
{ |
|||
SetFocusedElement(window, NavigationMethod.Unspecified, KeyModifiers.None); |
|||
} |
|||
if (((keyStates[(int)VK_LWIN] | keyStates[(int)VK_RWIN]) & 0x80) != 0) |
|||
{ |
|||
result |= RawInputModifiers.Meta; |
|||
} |
|||
|
|||
public string StringFromVirtualKey(uint virtualKey) |
|||
{ |
|||
var result = StringBuilderCache.Acquire(256); |
|||
int length = UnmanagedMethods.ToUnicode( |
|||
virtualKey, |
|||
0, |
|||
_keyStates, |
|||
result, |
|||
256, |
|||
0); |
|||
return StringBuilderCache.GetStringAndRelease(result); |
|||
} |
|||
|
|||
private void UpdateKeyStates() |
|||
{ |
|||
UnmanagedMethods.GetKeyboardState(_keyStates); |
|||
} |
|||
|
|||
private bool IsDown(Key key) |
|||
{ |
|||
return (GetKeyStates(key) & KeyStates.Down) != 0; |
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
|
|||
private KeyStates GetKeyStates(Key key) |
|||
private WindowsKeyboardDevice() |
|||
{ |
|||
int vk = KeyInterop.VirtualKeyFromKey(key); |
|||
byte state = _keyStates[vk]; |
|||
KeyStates result = 0; |
|||
|
|||
if ((state & 0x80) != 0) |
|||
{ |
|||
result |= KeyStates.Down; |
|||
} |
|||
|
|||
if ((state & 0x01) != 0) |
|||
{ |
|||
result |= KeyStates.Toggled; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
|
|||
Loading…
Reference in new issue