/* # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg # # This program is free software distributed under the GPL version 2. # See http://openslx.org/COPYING # # If you have any feedback please consult http://openslx.org/feedback and # send your suggestions, praise, or complaints to feedback@openslx.org # # General information about OpenSLX can be found at http://openslx.org/ # -------------------------------------------------------------------------- # x11FakeKeyboardHandler.h: # - Handle keyboard events on X11 - interface # -------------------------------------------------------------------------- */ #include #include #include // Qt headers need to be included before X11 headers #include #include // #include #include #include #include #include #include #include #include #include "x11InputUtils.h" #include "x11FakeKeyboardHandler.h" //////////////////////// INPUT EVENT TRANSLATION ///////////////////////////////// typedef unsigned char xmodifier_type; char modifiernames[][8] = { "SHIFT", "LOCK", "CONTROL", "MOD1", "MOD2", "MOD3", "MOD4", "MOD5" }; QString modifiers_to_string(xmodifier_type mods) { QString s; for(int i = 0; i < 8; i++) { if(mods & (1< lookup_table_type; typedef lookup_table_type::const_iterator lookup_table_const_iterator; typedef lookup_table_type::iterator lookup_table_iterator; lookup_table_type keysyms; void initialize_keysyms() { keysyms[Qt::Key_Escape] = XK_Escape; keysyms[Qt::Key_Tab] = XK_Tab; // keysyms[Qt::Key_Backtab] = XK_Backtab; keysyms[Qt::Key_Backspace] = XK_BackSpace; keysyms[Qt::Key_Return] = XK_Return; keysyms[Qt::Key_Enter] = XK_KP_Enter; keysyms[Qt::Key_Insert] = XK_Insert; keysyms[Qt::Key_Delete] = XK_Delete; keysyms[Qt::Key_Pause] = XK_Pause; keysyms[Qt::Key_Print] = XK_Print; keysyms[Qt::Key_SysReq] = XK_Sys_Req; keysyms[Qt::Key_Clear] = XK_Clear; keysyms[Qt::Key_Home] = XK_Home; keysyms[Qt::Key_End] = XK_End; keysyms[Qt::Key_Left] = XK_Left; keysyms[Qt::Key_Up] = XK_Up; keysyms[Qt::Key_Right] = XK_Right; keysyms[Qt::Key_Down] = XK_Down; keysyms[Qt::Key_PageUp] = XK_Page_Up; keysyms[Qt::Key_PageDown] = XK_Page_Down; keysyms[Qt::Key_Shift] = XK_Shift_L; keysyms[Qt::Key_Control] = XK_Control_L; keysyms[Qt::Key_Meta] = XK_Meta_L; keysyms[Qt::Key_Alt] = XK_Alt_L; keysyms[Qt::Key_CapsLock] = XK_Caps_Lock; keysyms[Qt::Key_NumLock] = XK_Num_Lock; keysyms[Qt::Key_ScrollLock] = XK_Scroll_Lock; keysyms[Qt::Key_F1] = XK_F1; keysyms[Qt::Key_F2] = XK_F2; keysyms[Qt::Key_F3] = XK_F3; keysyms[Qt::Key_F4] = XK_F4; keysyms[Qt::Key_F5] = XK_F5; keysyms[Qt::Key_F6] = XK_F6; keysyms[Qt::Key_F7] = XK_F7; keysyms[Qt::Key_F8] = XK_F8; keysyms[Qt::Key_F9] = XK_F9; keysyms[Qt::Key_F10] = XK_F10; keysyms[Qt::Key_F11] = XK_F11; keysyms[Qt::Key_F12] = XK_F12; keysyms[Qt::Key_F13] = XK_F13; keysyms[Qt::Key_F14] = XK_F14; keysyms[Qt::Key_F15] = XK_F15; keysyms[Qt::Key_F16] = XK_F16; keysyms[Qt::Key_F17] = XK_F17; keysyms[Qt::Key_F18] = XK_F18; keysyms[Qt::Key_F19] = XK_F19; keysyms[Qt::Key_F20] = XK_F20; keysyms[Qt::Key_F21] = XK_F21; keysyms[Qt::Key_F22] = XK_F22; keysyms[Qt::Key_F23] = XK_F23; keysyms[Qt::Key_F24] = XK_F24; keysyms[Qt::Key_F25] = XK_F25; keysyms[Qt::Key_F26] = XK_F26; keysyms[Qt::Key_F27] = XK_F27; keysyms[Qt::Key_F28] = XK_F28; keysyms[Qt::Key_F29] = XK_F29; keysyms[Qt::Key_F30] = XK_F30; keysyms[Qt::Key_F31] = XK_F31; keysyms[Qt::Key_F32] = XK_F32; keysyms[Qt::Key_F33] = XK_F33; keysyms[Qt::Key_F34] = XK_F34; keysyms[Qt::Key_F35] = XK_F35; keysyms[Qt::Key_Super_L] = XK_Super_L; keysyms[Qt::Key_Super_R] = XK_Super_R; keysyms[Qt::Key_Menu] = XK_Menu; keysyms[Qt::Key_Hyper_L] = XK_Hyper_L; keysyms[Qt::Key_Hyper_R] = XK_Hyper_R; keysyms[Qt::Key_Help] = XK_Help; // keysyms[Qt::Key_Direction_L] = XK_Direction_L; // keysyms[Qt::Key_Direction_R] = XK_Direction_R; keysyms[Qt::Key_Space] = XK_space; keysyms[Qt::Key_Exclam] = XK_exclam; keysyms[Qt::Key_QuoteDbl] = XK_quotedbl; keysyms[Qt::Key_NumberSign] = XK_numbersign; keysyms[Qt::Key_Dollar] = XK_dollar; keysyms[Qt::Key_Percent] = XK_percent; keysyms[Qt::Key_Ampersand] = XK_ampersand; keysyms[Qt::Key_Apostrophe] = XK_apostrophe; keysyms[Qt::Key_ParenLeft] = XK_parenleft; keysyms[Qt::Key_ParenRight] = XK_parenright; keysyms[Qt::Key_Asterisk] = XK_asterisk; keysyms[Qt::Key_Plus] = XK_plus; keysyms[Qt::Key_Comma] = XK_comma; keysyms[Qt::Key_Minus] = XK_minus; keysyms[Qt::Key_Period] = XK_period; keysyms[Qt::Key_Slash] = XK_slash; keysyms[Qt::Key_0] = XK_0; keysyms[Qt::Key_1] = XK_1; keysyms[Qt::Key_2] = XK_2; keysyms[Qt::Key_3] = XK_3; keysyms[Qt::Key_4] = XK_4; keysyms[Qt::Key_5] = XK_5; keysyms[Qt::Key_6] = XK_6; keysyms[Qt::Key_7] = XK_7; keysyms[Qt::Key_8] = XK_8; keysyms[Qt::Key_9] = XK_9; keysyms[Qt::Key_Colon] = XK_colon; keysyms[Qt::Key_Semicolon] = XK_semicolon; keysyms[Qt::Key_Less] = XK_less; keysyms[Qt::Key_Equal] = XK_equal; keysyms[Qt::Key_Greater] = XK_greater; keysyms[Qt::Key_Question] = XK_question; keysyms[Qt::Key_At] = XK_at; keysyms[Qt::Key_A] = XK_A; keysyms[Qt::Key_B] = XK_B; keysyms[Qt::Key_C] = XK_C; keysyms[Qt::Key_D] = XK_D; keysyms[Qt::Key_E] = XK_E; keysyms[Qt::Key_F] = XK_F; keysyms[Qt::Key_G] = XK_G; keysyms[Qt::Key_H] = XK_H; keysyms[Qt::Key_I] = XK_I; keysyms[Qt::Key_J] = XK_J; keysyms[Qt::Key_K] = XK_K; keysyms[Qt::Key_L] = XK_L; keysyms[Qt::Key_M] = XK_M; keysyms[Qt::Key_N] = XK_N; keysyms[Qt::Key_O] = XK_O; keysyms[Qt::Key_P] = XK_P; keysyms[Qt::Key_Q] = XK_Q; keysyms[Qt::Key_R] = XK_R; keysyms[Qt::Key_S] = XK_S; keysyms[Qt::Key_T] = XK_T; keysyms[Qt::Key_U] = XK_U; keysyms[Qt::Key_V] = XK_V; keysyms[Qt::Key_W] = XK_W; keysyms[Qt::Key_X] = XK_X; keysyms[Qt::Key_Y] = XK_Y; keysyms[Qt::Key_Z] = XK_Z; keysyms[Qt::Key_BracketLeft] = XK_bracketleft; keysyms[Qt::Key_Backslash] = XK_backslash; keysyms[Qt::Key_BracketRight] = XK_bracketright; keysyms[Qt::Key_AsciiCircum] = XK_asciicircum; keysyms[Qt::Key_Underscore] = XK_underscore; keysyms[Qt::Key_QuoteLeft] = XK_quoteleft; keysyms[Qt::Key_BraceLeft] = XK_braceleft; keysyms[Qt::Key_Bar] = XK_bar; keysyms[Qt::Key_BraceRight] = XK_braceright; keysyms[Qt::Key_AsciiTilde] = XK_asciitilde; keysyms[Qt::Key_nobreakspace] = XK_nobreakspace; keysyms[Qt::Key_exclamdown] = XK_exclamdown; keysyms[Qt::Key_cent] = XK_cent; keysyms[Qt::Key_sterling] = XK_sterling; keysyms[Qt::Key_currency] = XK_currency; keysyms[Qt::Key_yen] = XK_yen; keysyms[Qt::Key_brokenbar] = XK_brokenbar; keysyms[Qt::Key_section] = XK_section; keysyms[Qt::Key_diaeresis] = XK_diaeresis; keysyms[Qt::Key_copyright] = XK_copyright; keysyms[Qt::Key_ordfeminine] = XK_ordfeminine; keysyms[Qt::Key_guillemotleft] = XK_guillemotleft; keysyms[Qt::Key_notsign] = XK_notsign; keysyms[Qt::Key_hyphen] = XK_hyphen; keysyms[Qt::Key_registered] = XK_registered; keysyms[Qt::Key_macron] = XK_macron; keysyms[Qt::Key_degree] = XK_degree; keysyms[Qt::Key_plusminus] = XK_plusminus; keysyms[Qt::Key_twosuperior] = XK_twosuperior; keysyms[Qt::Key_threesuperior] = XK_threesuperior; keysyms[Qt::Key_acute] = XK_acute; keysyms[Qt::Key_mu] = XK_mu; keysyms[Qt::Key_paragraph] = XK_paragraph; keysyms[Qt::Key_periodcentered] = XK_periodcentered; keysyms[Qt::Key_cedilla] = XK_cedilla; keysyms[Qt::Key_onesuperior] = XK_onesuperior; keysyms[Qt::Key_masculine] = XK_masculine; keysyms[Qt::Key_guillemotright] = XK_guillemotright; keysyms[Qt::Key_onequarter] = XK_onequarter; keysyms[Qt::Key_onehalf] = XK_onehalf; keysyms[Qt::Key_threequarters] = XK_threequarters; keysyms[Qt::Key_questiondown] = XK_questiondown; keysyms[Qt::Key_Agrave] = XK_Agrave; keysyms[Qt::Key_Aacute] = XK_Aacute; keysyms[Qt::Key_Acircumflex] = XK_Acircumflex; keysyms[Qt::Key_Atilde] = XK_Atilde; keysyms[Qt::Key_Adiaeresis] = XK_Adiaeresis; keysyms[Qt::Key_Aring] = XK_Aring; keysyms[Qt::Key_AE] = XK_AE; keysyms[Qt::Key_Ccedilla] = XK_Ccedilla; keysyms[Qt::Key_Egrave] = XK_Egrave; keysyms[Qt::Key_Eacute] = XK_Eacute; keysyms[Qt::Key_Ecircumflex] = XK_Ecircumflex; keysyms[Qt::Key_Ediaeresis] = XK_Ediaeresis; keysyms[Qt::Key_Igrave] = XK_Igrave; keysyms[Qt::Key_Iacute] = XK_Iacute; keysyms[Qt::Key_Icircumflex] = XK_Icircumflex; keysyms[Qt::Key_Idiaeresis] = XK_Idiaeresis; keysyms[Qt::Key_ETH] = XK_ETH; keysyms[Qt::Key_Ntilde] = XK_Ntilde; keysyms[Qt::Key_Ograve] = XK_Ograve; keysyms[Qt::Key_Oacute] = XK_Oacute; keysyms[Qt::Key_Ocircumflex] = XK_Ocircumflex; keysyms[Qt::Key_Otilde] = XK_Otilde; keysyms[Qt::Key_Odiaeresis] = XK_Odiaeresis; keysyms[Qt::Key_multiply] = XK_multiply; keysyms[Qt::Key_Ooblique] = XK_Ooblique; keysyms[Qt::Key_Ugrave] = XK_Ugrave; keysyms[Qt::Key_Uacute] = XK_Uacute; keysyms[Qt::Key_Ucircumflex] = XK_Ucircumflex; keysyms[Qt::Key_Udiaeresis] = XK_Udiaeresis; keysyms[Qt::Key_Yacute] = XK_Yacute; keysyms[Qt::Key_THORN] = XK_THORN; keysyms[Qt::Key_ssharp] = XK_ssharp; keysyms[Qt::Key_Agrave] = XK_Agrave; keysyms[Qt::Key_Aacute] = XK_Aacute; keysyms[Qt::Key_Acircumflex] = XK_Acircumflex; keysyms[Qt::Key_Atilde] = XK_Atilde; keysyms[Qt::Key_Adiaeresis] = XK_Adiaeresis; keysyms[Qt::Key_Aring] = XK_Aring; keysyms[Qt::Key_AE] = XK_AE; keysyms[Qt::Key_Ccedilla] = XK_Ccedilla; keysyms[Qt::Key_Egrave] = XK_Egrave; keysyms[Qt::Key_Eacute] = XK_Eacute; keysyms[Qt::Key_Ecircumflex] = XK_Ecircumflex; keysyms[Qt::Key_Ediaeresis] = XK_Ediaeresis; keysyms[Qt::Key_Igrave] = XK_Igrave; keysyms[Qt::Key_Iacute] = XK_Iacute; keysyms[Qt::Key_Icircumflex] = XK_Icircumflex; keysyms[Qt::Key_Idiaeresis] = XK_Idiaeresis; keysyms[Qt::Key_ETH] = XK_ETH; keysyms[Qt::Key_Ntilde] = XK_Ntilde; keysyms[Qt::Key_Ograve] = XK_Ograve; keysyms[Qt::Key_Oacute] = XK_Oacute; keysyms[Qt::Key_Ocircumflex] = XK_Ocircumflex; keysyms[Qt::Key_Otilde] = XK_Otilde; keysyms[Qt::Key_Odiaeresis] = XK_Odiaeresis; keysyms[Qt::Key_division] = XK_division; keysyms[Qt::Key_Ooblique] = XK_Ooblique; keysyms[Qt::Key_Ugrave] = XK_Ugrave; keysyms[Qt::Key_Uacute] = XK_Uacute; keysyms[Qt::Key_Ucircumflex] = XK_Ucircumflex; keysyms[Qt::Key_Udiaeresis] = XK_Udiaeresis; keysyms[Qt::Key_Yacute] = XK_Yacute; keysyms[Qt::Key_THORN] = XK_THORN; keysyms[Qt::Key_ydiaeresis] = XK_ydiaeresis; keysyms[Qt::Key_AltGr] = XK_ISO_Level3_Shift; keysyms[Qt::Key_Multi_key] = XK_Multi_key; keysyms[Qt::Key_Codeinput] = XK_Codeinput; keysyms[Qt::Key_SingleCandidate] = XK_SingleCandidate; keysyms[Qt::Key_MultipleCandidate] = XK_MultipleCandidate; keysyms[Qt::Key_PreviousCandidate] = XK_PreviousCandidate; keysyms[Qt::Key_Mode_switch] = XK_Mode_switch; // keysyms[Qt::Key_script_switch] = XK_script_switch; keysyms[Qt::Key_Kanji] = XK_Kanji; keysyms[Qt::Key_Muhenkan] = XK_Muhenkan; // keysyms[Qt::Key_Henkan_Mode] = XK_Henkan_Mode; keysyms[Qt::Key_Henkan] = XK_Henkan; keysyms[Qt::Key_Romaji] = XK_Romaji; keysyms[Qt::Key_Hiragana] = XK_Hiragana; keysyms[Qt::Key_Katakana] = XK_Katakana; keysyms[Qt::Key_Hiragana_Katakana] = XK_Hiragana_Katakana; keysyms[Qt::Key_Zenkaku] = XK_Zenkaku; keysyms[Qt::Key_Hankaku] = XK_Hankaku; keysyms[Qt::Key_Zenkaku_Hankaku] = XK_Zenkaku_Hankaku; keysyms[Qt::Key_Touroku] = XK_Touroku; keysyms[Qt::Key_Massyo] = XK_Massyo; keysyms[Qt::Key_Kana_Lock] = XK_Kana_Lock; keysyms[Qt::Key_Kana_Shift] = XK_Kana_Shift; keysyms[Qt::Key_Eisu_Shift] = XK_Eisu_Shift; keysyms[Qt::Key_Eisu_toggle] = XK_Eisu_toggle; // keysyms[Qt::Key_Kanji_Bangou] = XK_Kanji_Bangou; // keysyms[Qt::Key_Zen_Koho] = XK_Zen_Koho; // keysyms[Qt::Key_Mae_Koho] = XK_Mae_Koho; keysyms[Qt::Key_Hangul] = XK_Hangul; keysyms[Qt::Key_Hangul_Hanja] = XK_Hangul_Hanja; keysyms[Qt::Key_Hangul] = XK_Hangul; keysyms[Qt::Key_Hangul_Start] = XK_Hangul_Start; keysyms[Qt::Key_Hangul_End] = XK_Hangul_End; keysyms[Qt::Key_Hangul_Hanja] = XK_Hangul_Hanja; keysyms[Qt::Key_Hangul_Jamo] = XK_Hangul_Jamo; keysyms[Qt::Key_Hangul_Romaja] = XK_Hangul_Romaja; // keysyms[Qt::Key_Hangul_Codeinput] = XK_Hangul_Codeinput; keysyms[Qt::Key_Hangul_Jeonja] = XK_Hangul_Jeonja; keysyms[Qt::Key_Hangul_Banja] = XK_Hangul_Banja; keysyms[Qt::Key_Hangul_PreHanja] = XK_Hangul_PreHanja; keysyms[Qt::Key_Hangul_PostHanja] = XK_Hangul_PostHanja; // keysyms[Qt::Key_Hangul_SingleCandidate] = XK_Hangul_SingleCandidate; // keysyms[Qt::Key_Hangul_MultipleCandidate] = XK_Hangul_MultipleCandidate; // keysyms[Qt::Key_Hangul_PreviousCandidate] = XK_Hangul_PreviousCandidate; keysyms[Qt::Key_Hangul_Special] = XK_Hangul_Special; // keysyms[Qt::Key_Hangul_switch] = XK_Hangul_switch; keysyms[Qt::Key_Dead_Grave] = XK_dead_grave; keysyms[Qt::Key_Dead_Acute] = XK_dead_acute; keysyms[Qt::Key_Dead_Circumflex] = XK_dead_circumflex; keysyms[Qt::Key_Dead_Tilde] = XK_dead_tilde; keysyms[Qt::Key_Dead_Macron] = XK_dead_macron; keysyms[Qt::Key_Dead_Breve] = XK_dead_breve; keysyms[Qt::Key_Dead_Abovedot] = XK_dead_abovedot; keysyms[Qt::Key_Dead_Diaeresis] = XK_dead_diaeresis; keysyms[Qt::Key_Dead_Abovering] = XK_dead_abovering; keysyms[Qt::Key_Dead_Doubleacute] = XK_dead_doubleacute; keysyms[Qt::Key_Dead_Caron] = XK_dead_caron; keysyms[Qt::Key_Dead_Cedilla] = XK_dead_cedilla; keysyms[Qt::Key_Dead_Ogonek] = XK_dead_ogonek; keysyms[Qt::Key_Dead_Iota] = XK_dead_iota; keysyms[Qt::Key_Dead_Voiced_Sound] = XK_dead_voiced_sound; keysyms[Qt::Key_Dead_Semivoiced_Sound] = XK_dead_semivoiced_sound; keysyms[Qt::Key_Dead_Belowdot] = XK_dead_belowdot; keysyms[Qt::Key_Dead_Hook] = XK_dead_hook; keysyms[Qt::Key_Dead_Horn] = XK_dead_horn; // keysyms[Qt::Key_Back] = XK_Back; // keysyms[Qt::Key_Forward] = XK_Forward; // keysyms[Qt::Key_Stop] = XK_Stop; // keysyms[Qt::Key_Refresh] = XK_Refresh; // keysyms[Qt::Key_VolumeDown] = XK_VolumeDown; // keysyms[Qt::Key_VolumeMute] = XK_VolumeMute; // keysyms[Qt::Key_VolumeUp] = XK_VolumeUp; // keysyms[Qt::Key_BassBoost] = XK_BassBoost; // keysyms[Qt::Key_BassUp] = XK_BassUp; // keysyms[Qt::Key_BassDown] = XK_BassDown; // keysyms[Qt::Key_TrebleUp] = XK_TrebleUp; // keysyms[Qt::Key_TrebleDown] = XK_TrebleDown; // keysyms[Qt::Key_MediaPlay] = XK_MediaPlay; // keysyms[Qt::Key_MediaStop] = XK_MediaStop; // keysyms[Qt::Key_MediaPrevious] = XK_MediaPrevious; // keysyms[Qt::Key_MediaNext] = XK_MediaNext; // keysyms[Qt::Key_MediaRecord] = XK_MediaRecord; // keysyms[Qt::Key_HomePage] = XK_HomePage; // keysyms[Qt::Key_Favorites] = XK_Favorites; // keysyms[Qt::Key_Search] = XK_Search; // keysyms[Qt::Key_Standby] = XK_Standby; // keysyms[Qt::Key_OpenUrl] = XK_OpenUrl; // keysyms[Qt::Key_LaunchMail] = XK_LaunchMail; // keysyms[Qt::Key_LaunchMedia] = XK_LaunchMedia; // keysyms[Qt::Key_Launch0] = XK_Launch0; // keysyms[Qt::Key_Launch1] = XK_Launch1; // keysyms[Qt::Key_Launch2] = XK_Launch2; // keysyms[Qt::Key_Launch3] = XK_Launch3; // keysyms[Qt::Key_Launch4] = XK_Launch4; // keysyms[Qt::Key_Launch5] = XK_Launch5; // keysyms[Qt::Key_Launch6] = XK_Launch6; // keysyms[Qt::Key_Launch7] = XK_Launch7; // keysyms[Qt::Key_Launch8] = XK_Launch8; // keysyms[Qt::Key_Launch9] = XK_Launch9; // keysyms[Qt::Key_LaunchA] = XK_LaunchA; // keysyms[Qt::Key_LaunchB] = XK_LaunchB; // keysyms[Qt::Key_LaunchC] = XK_LaunchC; // keysyms[Qt::Key_LaunchD] = XK_LaunchD; // keysyms[Qt::Key_LaunchE] = XK_LaunchE; // keysyms[Qt::Key_LaunchF] = XK_LaunchF; // keysyms[Qt::Key_Display] = XK_Display; // keysyms[Qt::Key_MediaLast] = XK_MediaLast; keysyms[Qt::Key_Select] = XK_Select; // keysyms[Qt::Key_Yes] = XK_Yes; // keysyms[Qt::Key_No] = XK_No; keysyms[Qt::Key_Cancel] = XK_Cancel; // keysyms[Qt::Key_Printer] = XK_Printer; keysyms[Qt::Key_Execute] = XK_Execute; // keysyms[Qt::Key_Sleep] = XK_Sleep; // keysyms[Qt::Key_MediaPlay] = XK_MediaPlay; // keysyms[Qt::Key_Zoom] = XK_Zoom; // keysyms[Qt::Key_Jisho] = XK_Jisho; // keysyms[Qt::Key_Oyayubi_Left] = XK_Oyayubi_Left; // keysyms[Qt::Key_Oyayubi_Right] = XK_Oyayubi_Right; // keysyms[Qt::Key_Context1] = XK_Context1; // keysyms[Qt::Key_Context2] = XK_Context2; // keysyms[Qt::Key_Context3] = XK_Context3; // keysyms[Qt::Key_Context4] = XK_Context4; // keysyms[Qt::Key_Call] = XK_Call; // keysyms[Qt::Key_Hangup] = XK_Hangup; // keysyms[Qt::Key_Flip] = XK_Flip; keysyms[Qt::Key_unknown] = XK_VoidSymbol; } /* Store Keycodes for "normal" Latin1 keys: */ int basic_keycodes[0x100]; int basic_modifiers[0x100]; int modifier_keycodes[8]; Qt::KeyboardModifier modifier_meaning[8]; int xmodifier_from_qtmodifier(Qt::KeyboardModifier m) { for(int i = 0; i < 8; i++) { if(m == modifier_meaning[i]) return i; } return -1; } typedef std::map qt_to_xmodifier_type; typedef std::map x_to_qtmodifier_type; qt_to_xmodifier_type qt_to_xmodifier; x_to_qtmodifier_type x_to_qtmodifier; typedef std::multimap modifier_to_keycode_map; modifier_to_keycode_map modifier_to_keycode; typedef std::map keycode_to_modifier_map; keycode_to_modifier_map keycode_to_modifier; void initialize_basic_keycodes() { for(int i = 0; i < 8; i++) { modifier_keycodes[i] = -1; } for(int i = 0; i < 0x100; i++) { basic_keycodes[i] = -1; } Display* dpy = X11InputUtils::display(); int min_keycode, max_keycode; XDisplayKeycodes(dpy, &min_keycode, &max_keycode); int xkb_opcode, xkb_event, xkb_error, xkb_major, xkb_minor; bool xkb_present = XkbQueryExtension(dpy, &xkb_opcode, &xkb_event, &xkb_error, &xkb_major, &xkb_minor); if(xkb_present) { int keysyms_per_code; const int count = max_keycode - min_keycode + 1; KeySym* mapping = XGetKeyboardMapping(dpy, min_keycode, count, &keysyms_per_code); for(int i = 0; i < count; i++) { for(int j = 0; j < keysyms_per_code; j++) { const int idx = i * keysyms_per_code + j; const KeySym ks = mapping[idx]; const int keycode = min_keycode + i; if(ks >= ' ' && ks < 0x100) { if(ks == XK_at) { ConsoleLog writeLine(QString("Keycode %1 (%2) gives `@' with modifiers `%3', but it is really `%4'").arg(keycode).arg(XKeysymToString(XKeycodeToKeysym(dpy, keycode, 0))).arg(modifiers_to_string(j)).arg(XKeysymToString(XKeycodeToKeysym(dpy, keycode, j)))); } if(basic_keycodes[ks] != -1) continue; // already found basic_keycodes[ks] = keycode; basic_modifiers[ks] = j; } } } XFree(mapping); } else { for(int i = min_keycode; i <= max_keycode; i++) { for(int j = 0; j <= 0xff; j++) { KeySym ks = 0; unsigned int unconsumed; if(!XkbLookupKeySym(dpy, i, j, &unconsumed, &ks) || ks == NoSymbol) continue; if(ks && (ks < 0x100)) { // ConsoleLog writeLine(QString("Keycode %1 (%2) seems to give `%3' with modifiers `%4', of which `%5' are unconsumed") // .arg(i) // .arg(XKeysymToString(XKeycodeToKeysym(dpy, i, 0))) // .arg(XKeysymToString(ks)) // .arg(modifiers_to_string(j)) // .arg(modifiers_to_string(unconsumed))); if(basic_keycodes[ks] != -1) continue; basic_keycodes[ks] = i; basic_modifiers[ks] = unconsumed & j; } } } } // find out which keycodes cause the modifier state bits: XModifierKeymap* modkm; modkm = XGetModifierMapping(dpy); const int shift_kc = XKeysymToKeycode(dpy, XK_Shift_L); const int control_kc = XKeysymToKeycode(dpy, XK_Control_L); const int alt_kc = XKeysymToKeycode(dpy, XK_Alt_L); const int meta_kc = XKeysymToKeycode(dpy, XK_Meta_L); const int switch_kc = XKeysymToKeycode(dpy, XK_Mode_switch); for(int i = 0; i < 8; i++) { for(int j = 0; j < modkm->max_keypermod; j++) { const int idx = i * modkm->max_keypermod + j; const int kc = modkm->modifiermap[idx]; modifier_to_keycode.insert(std::make_pair((1< int_set_type; int_set_type pressed_modifier_keys; xmodifier_type current_modifiers; void trackModifiers(int keycode, bool down) { // is this a modifier key? const bool is_modifier = keycode_to_modifier.find(keycode) != keycode_to_modifier.end(); if(!is_modifier) { return; } if(down) { pressed_modifier_keys.insert(keycode); } else { pressed_modifier_keys.erase(keycode); } int_set_type::iterator i, end = pressed_modifier_keys.end(); xmodifier_type modifs = 0; for(i = pressed_modifier_keys.begin(); i != end; i++) { keycode_to_modifier_map::iterator found_kc = keycode_to_modifier.find(*i); if(found_kc != keycode_to_modifier.end()) { modifs |= (*found_kc).second; } } current_modifiers = modifs; ConsoleLog writeLine(QString("[trackModifiers] current modifiers: %1").arg(modifiers_to_string(modifs))); } typedef std::pair modifier_tweak_type; typedef std::vector tweak_sequence_type; void tweakModifiers(Display* dpy, xmodifier_type neededState, xmodifier_type actualState, tweak_sequence_type& tracker) { ConsoleLog writeLine(QString("tweakModifiers: Trying to get to `%1' from `%2'").arg(modifiers_to_string(neededState)).arg(modifiers_to_string(actualState))); for(int j = 0; j < 8; j++) { xmodifier_type i = 1<second == i) { kc = *iter; // release this key: ConsoleLog writeLine(QString(" releasing key %1").arg(kc)); XTestFakeKeyEvent(dpy, kc, 0, CurrentTime); tracker.push_back(std::make_pair(kc, false)); } } } if(kc == -1) { // strange, but we need to release some other key: // we don't know which one, so we abort this and hope for the best continue; } } } } void untweakModifiers(Display* dpy, tweak_sequence_type& tracker) { tweak_sequence_type::iterator i, end = tracker.end(); for(i = tracker.begin(); i != end; i++) { modifier_tweak_type& t = *i; XTestFakeKeyEvent(dpy, t.first, !t.second, CurrentTime); } } void X11FakeKeyboardHandler::initialize() { initialize_keysyms(); initialize_basic_keycodes(); pressed_modifier_keys.clear(); current_modifiers = 0; } void X11FakeKeyboardHandler::handle(InputEvent const& evt) { Display* dpy = X11InputUtils::display(); // find out which keysym caused this event: lookup_table_const_iterator i = keysyms.find(evt.qt_keysym()); if(i == keysyms.end()) { // Special cases. We don't know how to directly translate those, so we will try to emulate them. switch(evt.qt_keysym()) { case Qt::Key_Backtab: handle(InputEvent(evt.type(), evt.code(), evt.qt_modifiers() | Qt::ShiftModifier | Qt::Key_Tab)); break; default: ConsoleLog writeLine(QString("Unknown keysym received: %1").arg(evt.qt_keysym(), 8, 16)); } } else { KeySym ks = (*i).second; // is it a "normal" key? if(ks >= ' ' && ks < 0x100) { if(basic_keycodes[ks] != -1) { if(evt.isPress()) { // Try the simple way first: // Does the keycode with current modifiers yield the requested symbol? KeySym unmod_ks = XKeycodeToKeysym(dpy, basic_keycodes[ks], current_modifiers); ConsoleLog writeLine(QString("Pressing the key for %1 would yield %2 right now.").arg(XKeysymToString(ks)).arg(XKeysymToString(unmod_ks))); if(ks == XKeycodeToKeysym(dpy, basic_keycodes[ks], current_modifiers)) { XTestFakeKeyEvent(dpy, basic_keycodes[ks], 1, CurrentTime); } else { // what modifier keys do we need to press? xmodifier_type mods = translate_modifiers(evt.qt_modifiers()); // we may need to press additional modifiers to generate this keysym: // but, since we do not differentiate upper and lower case, // and instead let the sender handle those modifiers, // we need to AND ShiftModifier and LockModifier out. mods |= basic_modifiers[ks] & ~(1<