/*************************************************************************/ /* keyboard.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "keyboard.h" #include "os/os.h" struct _KeyCodeText { int code; const char *text; }; static const _KeyCodeText _keycodes[] = { /* clang-format off */ {KEY_ESCAPE ,"Escape"}, {KEY_TAB ,"Tab"}, {KEY_BACKTAB ,"BackTab"}, {KEY_BACKSPACE ,"BackSpace"}, {KEY_ENTER ,"Enter"}, {KEY_KP_ENTER ,"Kp Enter"}, {KEY_INSERT ,"Insert"}, {KEY_DELETE ,"Delete"}, {KEY_PAUSE ,"Pause"}, {KEY_PRINT ,"Print"}, {KEY_SYSREQ ,"SysReq"}, {KEY_CLEAR ,"Clear"}, {KEY_HOME ,"Home"}, {KEY_END ,"End"}, {KEY_LEFT ,"Left"}, {KEY_UP ,"Up"}, {KEY_RIGHT ,"Right"}, {KEY_DOWN ,"Down"}, {KEY_PAGEUP ,"PageUp"}, {KEY_PAGEDOWN ,"PageDown"}, {KEY_SHIFT ,"Shift"}, {KEY_CONTROL ,"Control"}, #ifdef OSX_ENABLED {KEY_META ,"Command"}, #else {KEY_META ,"Meta"}, #endif {KEY_ALT ,"Alt"}, {KEY_CAPSLOCK ,"CapsLock"}, {KEY_NUMLOCK ,"NumLock"}, {KEY_SCROLLLOCK ,"ScrollLock"}, {KEY_F1 ,"F1"}, {KEY_F2 ,"F2"}, {KEY_F3 ,"F3"}, {KEY_F4 ,"F4"}, {KEY_F5 ,"F5"}, {KEY_F6 ,"F6"}, {KEY_F7 ,"F7"}, {KEY_F8 ,"F8"}, {KEY_F9 ,"F9"}, {KEY_F10 ,"F10"}, {KEY_F11 ,"F11"}, {KEY_F12 ,"F12"}, {KEY_F13 ,"F13"}, {KEY_F14 ,"F14"}, {KEY_F15 ,"F15"}, {KEY_F16 ,"F16"}, {KEY_KP_MULTIPLY ,"Kp Multiply"}, {KEY_KP_DIVIDE ,"Kp Divide"}, {KEY_KP_SUBTRACT ,"Kp Subtract"}, {KEY_KP_PERIOD ,"Kp Period"}, {KEY_KP_ADD ,"Kp Add"}, {KEY_KP_0 ,"Kp 0"}, {KEY_KP_1 ,"Kp 1"}, {KEY_KP_2 ,"Kp 2"}, {KEY_KP_3 ,"Kp 3"}, {KEY_KP_4 ,"Kp 4"}, {KEY_KP_5 ,"Kp 5"}, {KEY_KP_6 ,"Kp 6"}, {KEY_KP_7 ,"Kp 7"}, {KEY_KP_8 ,"Kp 8"}, {KEY_KP_9 ,"Kp 9"}, {KEY_SUPER_L ,"Super L"}, {KEY_SUPER_R ,"Super R"}, {KEY_MENU ,"Menu"}, {KEY_HYPER_L ,"Hyper L"}, {KEY_HYPER_R ,"Hyper R"}, {KEY_HELP ,"Help"}, {KEY_DIRECTION_L ,"Direction L"}, {KEY_DIRECTION_R ,"Direction R"}, {KEY_BACK ,"Back"}, {KEY_FORWARD ,"Forward"}, {KEY_STOP ,"Stop"}, {KEY_REFRESH ,"Refresh"}, {KEY_VOLUMEDOWN ,"VolumeDown"}, {KEY_VOLUMEMUTE ,"VolumeMute"}, {KEY_VOLUMEUP ,"VolumeUp"}, {KEY_BASSBOOST ,"BassBoost"}, {KEY_BASSUP ,"BassUp"}, {KEY_BASSDOWN ,"BassDown"}, {KEY_TREBLEUP ,"TrebleUp"}, {KEY_TREBLEDOWN ,"TrebleDown"}, {KEY_MEDIAPLAY ,"MediaPlay"}, {KEY_MEDIASTOP ,"MediaStop"}, {KEY_MEDIAPREVIOUS ,"MediaPrevious"}, {KEY_MEDIANEXT ,"MediaNext"}, {KEY_MEDIARECORD ,"MediaRecord"}, {KEY_HOMEPAGE ,"HomePage"}, {KEY_FAVORITES ,"Favorites"}, {KEY_SEARCH ,"Search"}, {KEY_STANDBY ,"StandBy"}, {KEY_LAUNCHMAIL ,"LaunchMail"}, {KEY_LAUNCHMEDIA ,"LaunchMedia"}, {KEY_LAUNCH0 ,"Launch0"}, {KEY_LAUNCH1 ,"Launch1"}, {KEY_LAUNCH2 ,"Launch2"}, {KEY_LAUNCH3 ,"Launch3"}, {KEY_LAUNCH4 ,"Launch4"}, {KEY_LAUNCH5 ,"Launch5"}, {KEY_LAUNCH6 ,"Launch6"}, {KEY_LAUNCH7 ,"Launch7"}, {KEY_LAUNCH8 ,"Launch8"}, {KEY_LAUNCH9 ,"Launch9"}, {KEY_LAUNCHA ,"LaunchA"}, {KEY_LAUNCHB ,"LaunchB"}, {KEY_LAUNCHC ,"LaunchC"}, {KEY_LAUNCHD ,"LaunchD"}, {KEY_LAUNCHE ,"LaunchE"}, {KEY_LAUNCHF ,"LaunchF"}, {KEY_UNKNOWN ,"Unknown"}, {KEY_SPACE ,"Space"}, {KEY_EXCLAM ,"Exclam"}, {KEY_QUOTEDBL ,"QuoteDbl"}, {KEY_NUMBERSIGN ,"NumberSign"}, {KEY_DOLLAR ,"Dollar"}, {KEY_PERCENT ,"Percent"}, {KEY_AMPERSAND ,"Ampersand"}, {KEY_APOSTROPHE ,"Apostrophe"}, {KEY_PARENLEFT ,"ParenLeft"}, {KEY_PARENRIGHT ,"ParenRight"}, {KEY_ASTERISK ,"Asterisk"}, {KEY_PLUS ,"Plus"}, {KEY_COMMA ,"Comma"}, {KEY_MINUS ,"Minus"}, {KEY_PERIOD ,"Period"}, {KEY_SLASH ,"Slash"}, {KEY_0 ,"0"}, {KEY_1 ,"1"}, {KEY_2 ,"2"}, {KEY_3 ,"3"}, {KEY_4 ,"4"}, {KEY_5 ,"5"}, {KEY_6 ,"6"}, {KEY_7 ,"7"}, {KEY_8 ,"8"}, {KEY_9 ,"9"}, {KEY_COLON ,"Colon"}, {KEY_SEMICOLON ,"Semicolon"}, {KEY_LESS ,"Less"}, {KEY_EQUAL ,"Equal"}, {KEY_GREATER ,"Greater"}, {KEY_QUESTION ,"Question"}, {KEY_AT ,"At"}, {KEY_A ,"A"}, {KEY_B ,"B"}, {KEY_C ,"C"}, {KEY_D ,"D"}, {KEY_E ,"E"}, {KEY_F ,"F"}, {KEY_G ,"G"}, {KEY_H ,"H"}, {KEY_I ,"I"}, {KEY_J ,"J"}, {KEY_K ,"K"}, {KEY_L ,"L"}, {KEY_M ,"M"}, {KEY_N ,"N"}, {KEY_O ,"O"}, {KEY_P ,"P"}, {KEY_Q ,"Q"}, {KEY_R ,"R"}, {KEY_S ,"S"}, {KEY_T ,"T"}, {KEY_U ,"U"}, {KEY_V ,"V"}, {KEY_W ,"W"}, {KEY_X ,"X"}, {KEY_Y ,"Y"}, {KEY_Z ,"Z"}, {KEY_BRACKETLEFT ,"BracketLeft"}, {KEY_BACKSLASH ,"BackSlash"}, {KEY_BRACKETRIGHT ,"BracketRight"}, {KEY_ASCIICIRCUM ,"AsciiCircum"}, {KEY_UNDERSCORE ,"UnderScore"}, {KEY_QUOTELEFT ,"QuoteLeft"}, {KEY_BRACELEFT ,"BraceLeft"}, {KEY_BAR ,"Bar"}, {KEY_BRACERIGHT ,"BraceRight"}, {KEY_ASCIITILDE ,"AsciiTilde"}, {KEY_NOBREAKSPACE ,"NoBreakSpace"}, {KEY_EXCLAMDOWN ,"ExclamDown"}, {KEY_CENT ,"Cent"}, {KEY_STERLING ,"Sterling"}, {KEY_CURRENCY ,"Currency"}, {KEY_YEN ,"Yen"}, {KEY_BROKENBAR ,"BrokenBar"}, {KEY_SECTION ,"Section"}, {KEY_DIAERESIS ,"Diaeresis"}, {KEY_COPYRIGHT ,"Copyright"}, {KEY_ORDFEMININE ,"Ordfeminine"}, {KEY_GUILLEMOTLEFT ,"GuillemotLeft"}, {KEY_NOTSIGN ,"NotSign"}, {KEY_HYPHEN ,"Hyphen"}, {KEY_REGISTERED ,"Registered"}, {KEY_MACRON ,"Macron"}, {KEY_DEGREE ,"Degree"}, {KEY_PLUSMINUS ,"PlusMinus"}, {KEY_TWOSUPERIOR ,"TwoSuperior"}, {KEY_THREESUPERIOR ,"ThreeSuperior"}, {KEY_ACUTE ,"Acute"}, {KEY_MU ,"Mu"}, {KEY_PARAGRAPH ,"Paragraph"}, {KEY_PERIODCENTERED ,"PeriodCentered"}, {KEY_CEDILLA ,"Cedilla"}, {KEY_ONESUPERIOR ,"OneSuperior"}, {KEY_MASCULINE ,"Masculine"}, {KEY_GUILLEMOTRIGHT ,"GuillemotRight"}, {KEY_ONEQUARTER ,"OneQuarter"}, {KEY_ONEHALF ,"OneHalf"}, {KEY_THREEQUARTERS ,"ThreeQuarters"}, {KEY_QUESTIONDOWN ,"QuestionDown"}, {KEY_AGRAVE ,"Agrave"}, {KEY_AACUTE ,"Aacute"}, {KEY_ACIRCUMFLEX ,"AcircumFlex"}, {KEY_ATILDE ,"Atilde"}, {KEY_ADIAERESIS ,"Adiaeresis"}, {KEY_ARING ,"Aring"}, {KEY_AE ,"Ae"}, {KEY_CCEDILLA ,"Ccedilla"}, {KEY_EGRAVE ,"Egrave"}, {KEY_EACUTE ,"Eacute"}, {KEY_ECIRCUMFLEX ,"Ecircumflex"}, {KEY_EDIAERESIS ,"Ediaeresis"}, {KEY_IGRAVE ,"Igrave"}, {KEY_IACUTE ,"Iacute"}, {KEY_ICIRCUMFLEX ,"Icircumflex"}, {KEY_IDIAERESIS ,"Idiaeresis"}, {KEY_ETH ,"Eth"}, {KEY_NTILDE ,"Ntilde"}, {KEY_OGRAVE ,"Ograve"}, {KEY_OACUTE ,"Oacute"}, {KEY_OCIRCUMFLEX ,"Ocircumflex"}, {KEY_OTILDE ,"Otilde"}, {KEY_ODIAERESIS ,"Odiaeresis"}, {KEY_MULTIPLY ,"Multiply"}, {KEY_OOBLIQUE ,"Ooblique"}, {KEY_UGRAVE ,"Ugrave"}, {KEY_UACUTE ,"Uacute"}, {KEY_UCIRCUMFLEX ,"Ucircumflex"}, {KEY_UDIAERESIS ,"Udiaeresis"}, {KEY_YACUTE ,"Yacute"}, {KEY_THORN ,"Thorn"}, {KEY_SSHARP ,"Ssharp"}, {KEY_DIVISION ,"Division"}, {KEY_YDIAERESIS ,"Ydiaeresis"}, {0 ,0} /* clang-format on */ }; bool keycode_has_unicode(uint32_t p_keycode) { switch (p_keycode) { case KEY_ESCAPE: case KEY_TAB: case KEY_BACKTAB: case KEY_BACKSPACE: case KEY_ENTER: case KEY_KP_ENTER: case KEY_INSERT: case KEY_DELETE: case KEY_PAUSE: case KEY_PRINT: case KEY_SYSREQ: case KEY_CLEAR: case KEY_HOME: case KEY_END: case KEY_LEFT: case KEY_UP: case KEY_RIGHT: case KEY_DOWN: case KEY_PAGEUP: case KEY_PAGEDOWN: case KEY_SHIFT: case KEY_CONTROL: case KEY_META: case KEY_ALT: case KEY_CAPSLOCK: case KEY_NUMLOCK: case KEY_SCROLLLOCK: case KEY_F1: case KEY_F2: case KEY_F3: case KEY_F4: case KEY_F5: case KEY_F6: case KEY_F7: case KEY_F8: case KEY_F9: case KEY_F10: case KEY_F11: case KEY_F12: case KEY_F13: case KEY_F14: case KEY_F15: case KEY_F16: case KEY_SUPER_L: case KEY_SUPER_R: case KEY_MENU: case KEY_HYPER_L: case KEY_HYPER_R: case KEY_HELP: case KEY_DIRECTION_L: case KEY_DIRECTION_R: case KEY_BACK: case KEY_FORWARD: case KEY_STOP: case KEY_REFRESH: case KEY_VOLUMEDOWN: case KEY_VOLUMEMUTE: case KEY_VOLUMEUP: case KEY_BASSBOOST: case KEY_BASSUP: case KEY_BASSDOWN: case KEY_TREBLEUP: case KEY_TREBLEDOWN: case KEY_MEDIAPLAY: case KEY_MEDIASTOP: case KEY_MEDIAPREVIOUS: case KEY_MEDIANEXT: case KEY_MEDIARECORD: case KEY_HOMEPAGE: case KEY_FAVORITES: case KEY_SEARCH: case KEY_STANDBY: case KEY_OPENURL: case KEY_LAUNCHMAIL: case KEY_LAUNCHMEDIA: case KEY_LAUNCH0: case KEY_LAUNCH1: case KEY_LAUNCH2: case KEY_LAUNCH3: case KEY_LAUNCH4: case KEY_LAUNCH5: case KEY_LAUNCH6: case KEY_LAUNCH7: case KEY_LAUNCH8: case KEY_LAUNCH9: case KEY_LAUNCHA: case KEY_LAUNCHB: case KEY_LAUNCHC: case KEY_LAUNCHD: case KEY_LAUNCHE: case KEY_LAUNCHF: return false; } return true; } String keycode_get_string(uint32_t p_code) { String codestr; if (p_code & KEY_MASK_SHIFT) { codestr += find_keycode_name(KEY_SHIFT); codestr += "+"; } if (p_code & KEY_MASK_ALT) { codestr += find_keycode_name(KEY_ALT); codestr += "+"; } if (p_code & KEY_MASK_CTRL) { codestr += find_keycode_name(KEY_CONTROL); codestr += "+"; } if (p_code & KEY_MASK_META) { codestr += find_keycode_name(KEY_META); codestr += "+"; } p_code &= KEY_CODE_MASK; const _KeyCodeText *kct = &_keycodes[0]; while (kct->text) { if (kct->code == (int)p_code) { codestr += kct->text; return codestr; } kct++; } codestr += String::chr(p_code); return codestr; } int find_keycode(const String &p_code) { const _KeyCodeText *kct = &_keycodes[0]; while (kct->text) { if (p_code.nocasecmp_to(kct->text) == 0) { return kct->code; } kct++; } return 0; } const char *find_keycode_name(int p_keycode) { const _KeyCodeText *kct = &_keycodes[0]; while (kct->text) { if (kct->code == p_keycode) { return kct->text; } kct++; } return ""; } struct _KeyCodeReplace { int from; int to; }; static const _KeyCodeReplace _keycode_replace_qwertz[] = { { KEY_Y, KEY_Z }, { KEY_Z, KEY_Y }, { 0, 0 } }; static const _KeyCodeReplace _keycode_replace_azerty[] = { { KEY_W, KEY_Z }, { KEY_Z, KEY_W }, { KEY_A, KEY_Q }, { KEY_Q, KEY_A }, { KEY_SEMICOLON, KEY_M }, { KEY_M, KEY_SEMICOLON }, { 0, 0 } }; static const _KeyCodeReplace _keycode_replace_qzerty[] = { { KEY_W, KEY_Z }, { KEY_Z, KEY_W }, { KEY_SEMICOLON, KEY_M }, { KEY_M, KEY_SEMICOLON }, { 0, 0 } }; static const _KeyCodeReplace _keycode_replace_dvorak[] = { { KEY_UNDERSCORE, KEY_BRACELEFT }, { KEY_EQUAL, KEY_BRACERIGHT }, { KEY_Q, KEY_APOSTROPHE }, { KEY_W, KEY_COMMA }, { KEY_E, KEY_PERIOD }, { KEY_R, KEY_P }, { KEY_T, KEY_Y }, { KEY_Y, KEY_F }, { KEY_U, KEY_G }, { KEY_I, KEY_C }, { KEY_O, KEY_R }, { KEY_P, KEY_L }, { KEY_BRACELEFT, KEY_SLASH }, { KEY_BRACERIGHT, KEY_EQUAL }, { KEY_A, KEY_A }, { KEY_S, KEY_O }, { KEY_D, KEY_E }, { KEY_F, KEY_U }, { KEY_G, KEY_I }, { KEY_H, KEY_D }, { KEY_J, KEY_H }, { KEY_K, KEY_T }, { KEY_L, KEY_N }, { KEY_SEMICOLON, KEY_S }, { KEY_APOSTROPHE, KEY_UNDERSCORE }, { KEY_Z, KEY_SEMICOLON }, { KEY_X, KEY_Q }, { KEY_C, KEY_J }, { KEY_V, KEY_K }, { KEY_B, KEY_X }, { KEY_N, KEY_B }, { KEY_M, KEY_M }, { KEY_COMMA, KEY_W }, { KEY_PERIOD, KEY_V }, { KEY_SLASH, KEY_Z }, { 0, 0 } }; static const _KeyCodeReplace _keycode_replace_neo[] = { { 0, 0 } }; static const _KeyCodeReplace _keycode_replace_colemak[] = { { KEY_E, KEY_F }, { KEY_R, KEY_P }, { KEY_T, KEY_G }, { KEY_Y, KEY_J }, { KEY_U, KEY_L }, { KEY_I, KEY_U }, { KEY_O, KEY_Y }, { KEY_P, KEY_SEMICOLON }, { KEY_S, KEY_R }, { KEY_D, KEY_S }, { KEY_F, KEY_T }, { KEY_G, KEY_D }, { KEY_J, KEY_N }, { KEY_K, KEY_E }, { KEY_L, KEY_I }, { KEY_SEMICOLON, KEY_O }, { KEY_N, KEY_K }, { 0, 0 } }; int keycode_get_count() { const _KeyCodeText *kct = &_keycodes[0]; int count = 0; while (kct->text) { count++; kct++; } return count; } int keycode_get_value_by_index(int p_index) { return _keycodes[p_index].code; } const char *keycode_get_name_by_index(int p_index) { return _keycodes[p_index].text; } int latin_keyboard_keycode_convert(int p_keycode) { const _KeyCodeReplace *kcr = NULL; switch (OS::get_singleton()->get_latin_keyboard_variant()) { case OS::LATIN_KEYBOARD_QWERTY: return p_keycode; break; case OS::LATIN_KEYBOARD_QWERTZ: kcr = _keycode_replace_qwertz; break; case OS::LATIN_KEYBOARD_AZERTY: kcr = _keycode_replace_azerty; break; case OS::LATIN_KEYBOARD_QZERTY: kcr = _keycode_replace_qzerty; break; case OS::LATIN_KEYBOARD_DVORAK: kcr = _keycode_replace_dvorak; break; case OS::LATIN_KEYBOARD_NEO: kcr = _keycode_replace_neo; break; case OS::LATIN_KEYBOARD_COLEMAK: kcr = _keycode_replace_colemak; break; default: return p_keycode; } if (!kcr) { return p_keycode; } while (kcr->from) { if (kcr->from == p_keycode) return kcr->to; kcr++; } return p_keycode; }