From 266eb5fb14c07e67aa211a5860e9abf3009136e3 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Mon, 4 Oct 2010 00:22:14 +0200 Subject: Implement first version of basic input event support --- src/input/x11FakeKeyboardHandler.cpp | 800 +++++++++++++++++++++++++++++++++++ 1 file changed, 800 insertions(+) create mode 100644 src/input/x11FakeKeyboardHandler.cpp (limited to 'src/input/x11FakeKeyboardHandler.cpp') diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp new file mode 100644 index 0000000..bb14b76 --- /dev/null +++ b/src/input/x11FakeKeyboardHandler.cpp @@ -0,0 +1,800 @@ +/* + # 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< #include #include +#include #include #include #include "x11InputUtils.h" @@ -502,14 +503,64 @@ void initialize_basic_keycodes() } else { + // Try to find out what device XTest will send events on: + int xkbDeviceId = XkbUseCoreKbd; + Atom xtestDeviceProp = XInternAtom(dpy, "XTEST Device", false); + int ndevinfos; + XIDeviceInfo* devinfos = XIQueryDevice(dpy, XIAllDevices, &ndevinfos); + if(devinfos) + { + for(int i = 0; i < ndevinfos && xkbDeviceId == XkbUseCoreKbd; i++) + { + XIDeviceInfo* devinfo = devinfos + i; + qDebug("Found device of type %d with name %s", devinfo->use, devinfo->name); + + // We want it to be a keyboard. + if(devinfo->use != XIMasterKeyboard && devinfo->use != XISlaveKeyboard) + continue; + + int nprops; + Atom* props = XIListProperties(dpy, devinfo->deviceid, &nprops); + if(props) + { + for(int j = 0; j < nprops && xkbDeviceId == XkbUseCoreKbd; j++) + { + Atom prop = props[j]; + if(prop == xtestDeviceProp) + { + // The device is the XTest Keyboard: + xkbDeviceId = devinfo->deviceid; + } + } + XFree(props); + } + } + XIFreeDeviceInfo(devinfos); + } + + // Okay, we know which device to query. Now get its keymap: + XkbDescPtr keybDesc = XkbGetKeyboard(dpy, XkbAllComponentsMask, xkbDeviceId); + if(!keybDesc) + { + qWarning("Unable to retrieve keyboard description for device %d. Falling back to unreliable global mapping", xkbDeviceId); + } + 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(keybDesc) + { + if(!XkbTranslateKeyCode(keybDesc, i, j, &unconsumed, &ks) || ks == NoSymbol) + continue; + } + else + { + if(!XkbLookupKeySym(dpy, i, j, &unconsumed, &ks) || ks == NoSymbol) + continue; + } if(ks && (ks < 0x100)) { @@ -527,6 +578,12 @@ void initialize_basic_keycodes() } } } + + // Free the keyboard description: + if(keybDesc) + { + XkbFreeKeyboard(keybDesc, XkbAllComponentsMask, true); + } } // find out which keycodes cause the modifier state bits: @@ -750,10 +807,18 @@ void X11FakeKeyboardHandler::handle(InputEvent const& evt) 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< class DefaultInputEventHandler { public: - static bool matches(InputEvent const& evt) { - if(Type != 0xffff) { + virtual bool matches(InputEvent const& evt, InputEventContext const*) { + if(Type != HANDLER_TYPE_DONT_CARE) { if(evt.type() != Type) return false; } - if(Code != 0xffff) { + if(Code != HANDLER_CODE_DONT_CARE) { if(evt.code() != Code) return false; } - if(Value != 0xffffffff) { + if(Value != HANDLER_VALUE_DONT_CARE) { if(evt.value() != Value) return false; } return true; } - static void initialize() + virtual void initialize() { } -}; -namespace policy { + virtual void handle(InputEvent const& evt, InputEventContext const*) = 0; -struct NoSecurityCheck { - static bool allow(InputEvent const&) { - return true; + static void describeInto(QList& description) + { } }; -struct PhysicalSeatSecurityCheck { - static bool allow(InputEvent const&) { - return /* TODO implement */ true; - } +namespace policy { + +enum SecurityFlags { + SEC_PHYSICAL_SEAT = 1, + SEC_PRIVILEGED_USER = 2 }; -struct AlwaysDenySecurityCheck { - static bool allow(InputEvent const&) { - return false; +bool allowPhysicalSeat(InputEvent const& evt, InputEventContext const* ctx); +bool allowPrivilegedUser(InputEvent const& evt, InputEventContext const* ctx); + +template +struct Security +{ + bool allow(InputEvent const& evt, InputEventContext const* ctx) + { + return true; } }; @@ -107,39 +138,43 @@ template class HandlerHelper { public: - static bool handle(InputEvent const& evt) { - if(!SecurityPolicy::allow(evt)) + bool handle(InputEvent const& evt, InputEventContext const* context = 0) { + if(!securityPolicy.allow(evt, context)) { return true; } - if(Delegate::matches(evt)) { - Delegate::handle(evt); + if(delegate.matches(evt, context)) { + delegate.handle(evt, context); return true; } else { return false; } } - static void initialize() + void initialize() { - Delegate::initialize(); + delegate.initialize(); } + +private: + Delegate delegate; + SecurityPolicy securityPolicy; }; template class HandlerHelper { public: - static bool handle(InputEvent const& evt) { + bool handle(InputEvent const& evt, InputEventContext const* context = 0) { return false; } - static void initialize() + void initialize() { } }; -template +template > struct Handler : public HandlerHelper { }; @@ -153,28 +188,31 @@ private: typedef typename boost::mpl::deref::type handler_type; + handler_type _handler; + next_in_chain _next; + public: - static void handle(InputEvent const& evt) { - if(!handler_type::handle(evt)) { - next_in_chain::handle(evt); + void handle(InputEvent const& evt, InputEventContext const* context = 0) { + if(!_handler.handle(evt, context)) { + _next.handle(evt, context); } } - static void initialize() { - handler_type::initialize(); - next_in_chain::initialize(); + void initialize() { + _handler.initialize(); + _next.initialize(); + } } }; template struct InputEventHandlerChainHelper { -public: - static void handle(InputEvent const&) { + void handle(InputEvent const&, InputEventContext const* context = 0) { // do nothing } - static void initialize() { + void initialize() { // do nothing } }; diff --git a/src/input/inputHandlerChain.h b/src/input/inputHandlerChain.h new file mode 100644 index 0000000..4bb9fe5 --- /dev/null +++ b/src/input/inputHandlerChain.h @@ -0,0 +1,34 @@ +/* + # 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/ + # -------------------------------------------------------------------------- + # inputHandlerChain.h: + # - Definition of the input handler chain + # -------------------------------------------------------------------------- + */ + +#ifndef INPUTHANDLERCHAIN_H_ +#define INPUTHANDLERCHAIN_H_ + +#include +#include "inputEventHandler.h" + +#include "x11FakeKeyboardHandler.h" +#include "x11FakeMouseHandler.h" + +typedef boost::mpl::list< + Handler >, + Handler >, + Handler > +>::type unprivileged_handler_list; + +typedef InputEventHandlerChain unprivileged_handler_chain; + +#endif /* INPUTHANDLERCHAIN_H_ */ diff --git a/src/input/unprivilegedHandlerChain.h b/src/input/unprivilegedHandlerChain.h deleted file mode 100644 index 734720a..0000000 --- a/src/input/unprivilegedHandlerChain.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - # 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/ - # -------------------------------------------------------------------------- - # inputHandlerChain.h: - # - Definition of the input handler chain - # -------------------------------------------------------------------------- - */ - -#ifndef INPUTHANDLERCHAIN_H_ -#define INPUTHANDLERCHAIN_H_ - -#include -#include "inputEventHandler.h" - -#include "x11FakeKeyboardHandler.h" -#include "x11FakeMouseHandler.h" - -typedef boost::mpl::list< - Handler >, - Handler >, - Handler > ->::type unprivileged_handler_list; - -typedef InputEventHandlerChain unprivileged_handler_chain; - -#endif /* INPUTHANDLERCHAIN_H_ */ diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp index 82cc437..3a0b864 100644 --- a/src/input/x11FakeKeyboardHandler.cpp +++ b/src/input/x11FakeKeyboardHandler.cpp @@ -20,6 +20,7 @@ // Qt headers need to be included before X11 headers #include #include +#include "x11FakeKeyboardHandler.h" // #include #include #include @@ -30,7 +31,6 @@ #include #include #include "x11InputUtils.h" -#include "x11FakeKeyboardHandler.h" //////////////////////// INPUT EVENT TRANSLATION ///////////////////////////////// @@ -766,7 +766,7 @@ void X11FakeKeyboardHandler::initialize() current_modifiers = 0; } -void X11FakeKeyboardHandler::handle(InputEvent const& evt) +void X11FakeKeyboardHandler::handle(InputEvent const& evt, InputEventContext const*) { Display* dpy = X11InputUtils::display(); diff --git a/src/input/x11FakeKeyboardHandler.h b/src/input/x11FakeKeyboardHandler.h index c888202..3dde7cc 100644 --- a/src/input/x11FakeKeyboardHandler.h +++ b/src/input/x11FakeKeyboardHandler.h @@ -22,8 +22,8 @@ class X11FakeKeyboardHandler : public DefaultInputEventHandler { public: - static void handle(InputEvent const&); - static void initialize(); + void handle(InputEvent const&, InputEventContext const* = 0); + void initialize(); }; #endif /* X11FAKEKEYBOARDHANDLER_H_ */ diff --git a/src/input/x11FakeMouseHandler.cpp b/src/input/x11FakeMouseHandler.cpp index 432e19f..58415d5 100644 --- a/src/input/x11FakeMouseHandler.cpp +++ b/src/input/x11FakeMouseHandler.cpp @@ -14,12 +14,12 @@ # -------------------------------------------------------------------------- */ +#include "x11FakeMouseHandler.h" // need to include before X headers #include #include #include "x11InputUtils.h" -#include "x11FakeMouseHandler.h" -void X11FakeMouseButtonHandler::handle(InputEvent const& evt) +void X11FakeMouseButtonHandler::handle(InputEvent const& evt, InputEventContext const*) { quint16 pressedButton = evt.pressedButton(); @@ -42,7 +42,7 @@ void X11FakeMouseButtonHandler::handle(InputEvent const& evt) XFlush(dpy); } -void X11FakeMouseMovementHandler::handle(InputEvent const& evt) +void X11FakeMouseMovementHandler::handle(InputEvent const& evt, InputEventContext const*) { ConsoleLog writeLine(QString("Received mouse motion event (%1,%2)").arg(evt.xCoord()).arg(evt.yCoord())); Display* dpy = X11InputUtils::display(); diff --git a/src/input/x11FakeMouseHandler.h b/src/input/x11FakeMouseHandler.h index 19ed29e..0e32256 100644 --- a/src/input/x11FakeMouseHandler.h +++ b/src/input/x11FakeMouseHandler.h @@ -22,13 +22,13 @@ class X11FakeMouseButtonHandler : public DefaultInputEventHandler { public: - static void handle(InputEvent const&); + void handle(InputEvent const&, InputEventContext const* = 0); }; class X11FakeMouseMovementHandler : public DefaultInputEventHandler { public: - static void handle(InputEvent const&); + void handle(InputEvent const&, InputEventContext const* = 0); }; #endif /* X11FAKEMOUSEHANDLER_H_ */ diff --git a/src/pvs.cpp b/src/pvs.cpp index e44d04d..911ed0d 100644 --- a/src/pvs.cpp +++ b/src/pvs.cpp @@ -16,7 +16,7 @@ #include "src/net/pvsServiceDiscovery.h" #include "src/net/pvsDiscoveredServer.h" #include "src/input/inputEvent.h" -#include "src/input/unprivilegedHandlerChain.h" +#include "src/input/inputHandlerChain.h" #include "src/input/x11InputUtils.h" // D-Bus @@ -643,11 +643,11 @@ void PVS::handleInputEvent(InputEvent const& evt) { std::string s = evt.toString(); ConsoleLog writeLine(QString("Received input event: %1").arg(s.c_str())); - unprivileged_handler_chain::handle(evt); + _inputEventHandlers.handle(evt); } void PVS::initializeInputEventHandling() { X11InputUtils::setDisplay(X11Info::display()); - unprivileged_handler_chain::initialize(); + _inputEventHandlers.initialize(); } diff --git a/src/pvs.h b/src/pvs.h index 8e94169..f4e53c0 100644 --- a/src/pvs.h +++ b/src/pvs.h @@ -24,6 +24,7 @@ #include "src/version.h" #include "src/util/consoleLogger.h" #include "src/util/clientGUIUtils.h" +#include "src/input/inputHandlerChain.h" class PVSServiceDiscovery; @@ -144,6 +145,7 @@ private: int _timerLockDelay; // input event handling: + unprivileged_handler_chain _inputEventHandlers; void handleInputEvent(InputEvent const& evt); void initializeInputEventHandling(); }; -- cgit v1.2.3-55-g7522 From 43038c98f8cc48cfded692ea44e02e93597da305 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Tue, 5 Oct 2010 19:04:36 +0200 Subject: Add hard requirement for XInput library. XInput2 will be preferred if its presence is detected. --- CMakeLists.txt | 7 +++++- src/input/CMakeLists.txt | 8 ++++++ src/input/x11FakeKeyboardHandler.cpp | 49 +++++++++++++++++++++++++++++++++--- 3 files changed, 59 insertions(+), 5 deletions(-) (limited to 'src/input/x11FakeKeyboardHandler.cpp') diff --git a/CMakeLists.txt b/CMakeLists.txt index ec688b5..dab8b1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,10 +31,14 @@ INCLUDE_DIRECTORIES( ${CMAKE_BINARY_DIR} ${X11_INCLUDE_DIR} ${X11_XTest_INCLUDE_PATH} + ${X11_Xinput_INCLUDE_PATH} ) IF(NOT X11_XTest_FOUND) - MESSAGE(FATAL_ERROR "Could not find X11 extension XTest. It is needed for PVS") + MESSAGE(FATAL_ERROR "Could not find X11 extension XTest or its developer files.") +ENDIF() +IF(NOT X11_Xinput_FOUND) + MESSAGE(FATAL_ERROR "Could not find X11 extension Xinput or its developer files.") ENDIF() ADD_SUBDIRECTORY(src/input) @@ -322,6 +326,7 @@ TARGET_LINK_LIBRARIES( pvs ${VNC_LIBRARIES} ${X11_LIBRARIES} ${X11_XTest_LIB} + ${X11_Xinput_LIB} pvsinput ) diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt index 29374e2..1a3b154 100644 --- a/src/input/CMakeLists.txt +++ b/src/input/CMakeLists.txt @@ -6,6 +6,14 @@ set(pvsinput_SRCS ) if(UNIX) + find_file(XINPUT2_HDR X11/extensions/XInput2.h) + if(XINPUT2_HDR) + set_property(SOURCE x11FakeKeyboardHandler.cpp + APPEND + PROPERTY COMPILE_DEFINITIONS HAVE_XINPUT2_H + ) + endif() + set(pvsprivinputd_SRCS pvsprivinputd.cpp pvsPrivInputHandler.cpp diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp index 3a0b864..e7a5826 100644 --- a/src/input/x11FakeKeyboardHandler.cpp +++ b/src/input/x11FakeKeyboardHandler.cpp @@ -27,7 +27,11 @@ #include #include #include -#include +#ifdef HAVE_XINPUT2_H +# include +#else +# include +#endif #include #include #include "x11InputUtils.h" @@ -457,6 +461,37 @@ modifier_to_keycode_map modifier_to_keycode; typedef std::map keycode_to_modifier_map; keycode_to_modifier_map keycode_to_modifier; +// We need to query the input devices, preferrable through XInput2, but +// if that is not available we will contend ourselves with XInput1: +#ifndef HAVE_XINPUT2_H +# define XIAllDevices 1 /* does not matter */ +# define XIDeviceInfo XDeviceInfo +# define XIQueryDevice(dpy, which, ninfos) XListInputDevices(dpy, ninfos) +# define XIFreeDeviceInfo(infos) XFreeDeviceList(infos) +# define XIMasterKeyboard IsXKeyboard +# define XISlaveKeyboard IsXExtensionKeyboard + static inline Atom* getDeviceProperties(Display* dpy, XIDeviceInfo* devinfo, int* nprops) + { + if(devinfo->use == IsXKeyboard) + { + // According to XOpenDevice(3X11) you cannot open the Core Keyboard. + *nprops = 0; + return 0; + } + + XDevice* dev = XOpenDevice(dpy, devinfo->id); + Atom* props = XListDeviceProperties(dpy, dev, nprops); + XCloseDevice(dpy, dev); + return props; + } +#else + static inline Atom* getDeviceProperties(Display* dpy, XIDeviceInfo* devinfo, int* nprops) + { + return XIListProperties(dpy, devinfo->deviceid, nprops); + } +#endif + + void initialize_basic_keycodes() { for(int i = 0; i < 8; i++) { @@ -504,23 +539,26 @@ void initialize_basic_keycodes() else { // Try to find out what device XTest will send events on: - int xkbDeviceId = XkbUseCoreKbd; + unsigned int xkbDeviceId = XkbUseCoreKbd; Atom xtestDeviceProp = XInternAtom(dpy, "XTEST Device", false); int ndevinfos; XIDeviceInfo* devinfos = XIQueryDevice(dpy, XIAllDevices, &ndevinfos); if(devinfos) { +#ifndef HAVE_INPUT2_H +# define deviceid id +#endif for(int i = 0; i < ndevinfos && xkbDeviceId == XkbUseCoreKbd; i++) { XIDeviceInfo* devinfo = devinfos + i; - qDebug("Found device of type %d with name %s", devinfo->use, devinfo->name); + qDebug("Found device %lu of type %d with name %s", (unsigned long)devinfo->deviceid, devinfo->use, devinfo->name); // We want it to be a keyboard. if(devinfo->use != XIMasterKeyboard && devinfo->use != XISlaveKeyboard) continue; int nprops; - Atom* props = XIListProperties(dpy, devinfo->deviceid, &nprops); + Atom* props = getDeviceProperties(dpy, devinfo, &nprops); if(props) { for(int j = 0; j < nprops && xkbDeviceId == XkbUseCoreKbd; j++) @@ -536,6 +574,9 @@ void initialize_basic_keycodes() } } XIFreeDeviceInfo(devinfos); +#ifdef deviceid /* XInput1 */ +# undef deviceid +#endif } // Okay, we know which device to query. Now get its keymap: -- cgit v1.2.3-55-g7522 From e753c26e49e47e24ab2417b775815bf035bd5baf Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Tue, 5 Oct 2010 23:00:14 +0200 Subject: Fix recognition of letters in keyboard handler --- src/input/x11FakeKeyboardHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/input/x11FakeKeyboardHandler.cpp') diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp index e7a5826..b1492e7 100644 --- a/src/input/x11FakeKeyboardHandler.cpp +++ b/src/input/x11FakeKeyboardHandler.cpp @@ -848,7 +848,7 @@ void X11FakeKeyboardHandler::handle(InputEvent const& evt, InputEventContext con xmodifier_type mods = translate_modifiers(evt.qt_modifiers()); // we may need to press additional modifiers to generate this keysym: - if(isalpha(ks)) + if(QChar(ks, 0).isLetter()) { // but, since we do not differentiate upper and lower case, // and instead let the sender handle those modifiers, -- cgit v1.2.3-55-g7522 From 76756513af78ff0c96cdbcad91727f26f48cc922 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Wed, 6 Oct 2010 00:05:54 +0200 Subject: Fix typo that prevents correct compilation when XInput2.h is present --- src/input/x11FakeKeyboardHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/input/x11FakeKeyboardHandler.cpp') diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp index b1492e7..0c32b66 100644 --- a/src/input/x11FakeKeyboardHandler.cpp +++ b/src/input/x11FakeKeyboardHandler.cpp @@ -545,7 +545,7 @@ void initialize_basic_keycodes() XIDeviceInfo* devinfos = XIQueryDevice(dpy, XIAllDevices, &ndevinfos); if(devinfos) { -#ifndef HAVE_INPUT2_H +#ifndef HAVE_XINPUT2_H # define deviceid id #endif for(int i = 0; i < ndevinfos && xkbDeviceId == XkbUseCoreKbd; i++) -- cgit v1.2.3-55-g7522