From fa1bc737d5fd81230c9fd990148ac021b71de344 Mon Sep 17 00:00:00 2001 From: binary1248 Date: Wed, 29 Jul 2015 13:58:48 +0200 Subject: [PATCH] Reverted to Xlib event handling since XCB event handling just breaks too many things. --- src/SFML/Window/Unix/Display.cpp | 187 ------- src/SFML/Window/Unix/Display.hpp | 17 - src/SFML/Window/Unix/InputImpl.cpp | 253 ++++----- src/SFML/Window/Unix/InputImpl.hpp | 6 - src/SFML/Window/Unix/WindowImplX11.cpp | 688 +++++-------------------- src/SFML/Window/Unix/WindowImplX11.hpp | 14 +- 6 files changed, 250 insertions(+), 915 deletions(-) diff --git a/src/SFML/Window/Unix/Display.cpp b/src/SFML/Window/Unix/Display.cpp index cf1357db..c57ae0fd 100644 --- a/src/SFML/Window/Unix/Display.cpp +++ b/src/SFML/Window/Unix/Display.cpp @@ -30,8 +30,6 @@ #include #include #include -#include -#include #include @@ -43,108 +41,6 @@ namespace typedef std::map AtomMap; AtomMap atoms; - - bool mapBuilt = false; - xcb_keycode_t firstKeycode = 255; - xcb_keycode_t lastKeycode = 0; - - // We use a simple array instead of a map => constant time lookup - // xcb_keycode_t can only contain 256 distinct values - xcb_keysym_t keysymMap[256]; - - xcb_keysym_t keysymToLower(xcb_keysym_t keysym) - { - switch(keysym >> 8) - { - // Latin 1 - case 0: - { - if ((keysym >= XK_A) && (keysym <= XK_Z)) - return keysym + (XK_a - XK_A); - else if ((keysym >= XK_Agrave) && (keysym <= XK_Odiaeresis)) - return keysym + (XK_agrave - XK_Agrave); - else if ((keysym >= XK_Ooblique) && (keysym <= XK_Thorn)) - return keysym + (XK_oslash - XK_Ooblique); - break; - } - - // Latin 2 - case 1: - { - if (keysym == XK_Aogonek) - return XK_aogonek; - else if (keysym >= XK_Lstroke && keysym <= XK_Sacute) - return keysym + (XK_lstroke - XK_Lstroke); - else if (keysym >= XK_Scaron && keysym <= XK_Zacute) - return keysym + (XK_scaron - XK_Scaron); - else if (keysym >= XK_Zcaron && keysym <= XK_Zabovedot) - return keysym + (XK_zcaron - XK_Zcaron); - else if (keysym >= XK_Racute && keysym <= XK_Tcedilla) - return keysym + (XK_racute - XK_Racute); - break; - } - - // Latin 3 - case 2: - { - if (keysym >= XK_Hstroke && keysym <= XK_Hcircumflex) - return keysym + (XK_hstroke - XK_Hstroke); - else if (keysym >= XK_Gbreve && keysym <= XK_Jcircumflex) - return keysym + (XK_gbreve - XK_Gbreve); - else if (keysym >= XK_Cabovedot && keysym <= XK_Scircumflex) - return keysym + (XK_cabovedot - XK_Cabovedot); - break; - } - - // Latin 4 - case 3: - { - if (keysym >= XK_Rcedilla && keysym <= XK_Tslash) - return keysym + (XK_rcedilla - XK_Rcedilla); - else if (keysym == XK_ENG) - return XK_eng; - else if (keysym >= XK_Amacron && keysym <= XK_Umacron) - return keysym + (XK_amacron - XK_Amacron); - break; - } - - // Cyrillic - case 6: - { - if (keysym >= XK_Serbian_DJE && keysym <= XK_Serbian_DZE) - return keysym - (XK_Serbian_DJE - XK_Serbian_dje); - else if (keysym >= XK_Cyrillic_YU && keysym <= XK_Cyrillic_HARDSIGN) - return keysym - (XK_Cyrillic_YU - XK_Cyrillic_yu); - break; - } - - // Greek - case 7: - { - if (keysym >= XK_Greek_ALPHAaccent && keysym <= XK_Greek_OMEGAaccent) - return keysym + (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); - else if (keysym >= XK_Greek_ALPHA && keysym <= XK_Greek_OMEGA) - return keysym + (XK_Greek_alpha - XK_Greek_ALPHA); - break; - } - - // Armenian - case 0x14: - { - if (keysym >= XK_Armenian_AYB && keysym <= XK_Armenian_fe) { - return (keysym | 1); - } - break; - } - - default: - { - break; - } - } - - return keysym; - } } namespace sf @@ -268,89 +164,6 @@ xcb_atom_t getAtom(const std::string& name, bool onlyIfExists) return reply->atom; } - -//////////////////////////////////////////////////////////// -const xcb_keysym_t* getKeysymMap() -{ - if (!mapBuilt) - buildKeysymMap(); - - return keysymMap; -} - - -//////////////////////////////////////////////////////////// -void buildKeysymMap() -{ - // Open a connection with the X server - xcb_connection_t* connection = sf::priv::OpenConnection(); - - firstKeycode = xcb_get_setup(connection)->min_keycode; - lastKeycode = xcb_get_setup(connection)->max_keycode; - - sf::priv::ScopedXcbPtr error(NULL); - - sf::priv::ScopedXcbPtr keyboardMapping(xcb_get_keyboard_mapping_reply( - connection, - xcb_get_keyboard_mapping( - connection, - firstKeycode, - lastKeycode - firstKeycode + 1 - ), - &error - )); - - sf::priv::CloseConnection(connection); - - if (error || !keyboardMapping) - { - sf::err() << "Failed to get keyboard mapping" << std::endl; - return; - } - - uint8_t keysymsPerKeycode = keyboardMapping->keysyms_per_keycode; - - if (!keysymsPerKeycode) - { - sf::err() << "Error: No keysyms per keycode" << std::endl; - return; - } - - const xcb_keysym_t* keysyms = xcb_get_keyboard_mapping_keysyms(keyboardMapping.get()); - - if (!keysyms) - { - sf::err() << "Failed to get keyboard mapping keysyms" << std::endl; - return; - } - - xcb_keycode_t range = lastKeycode - firstKeycode + 1; - - std::fill(keysymMap, keysymMap + 256, XK_VoidSymbol); - - for (xcb_keycode_t i = firstKeycode; ; ++i) - { - const xcb_keysym_t* keysym = &keysyms[(i - firstKeycode) * keysymsPerKeycode]; - - if ((keysymsPerKeycode == 1) || (keysym[1] == XCB_NO_SYMBOL)) - { - keysymMap[i] = keysymToLower(keysym[0]); - - if (i == lastKeycode) - break; - - continue; - } - - keysymMap[i] = keysym[0]; - - if (i == lastKeycode) - break; - } - - mapBuilt = true; -} - } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Unix/Display.hpp b/src/SFML/Window/Unix/Display.hpp index da29d510..2b33c964 100644 --- a/src/SFML/Window/Unix/Display.hpp +++ b/src/SFML/Window/Unix/Display.hpp @@ -116,23 +116,6 @@ xcb_window_t XCBDefaultRootWindow(xcb_connection_t* connection); //////////////////////////////////////////////////////////// xcb_atom_t getAtom(const std::string& name, bool onlyIfExists = false); -//////////////////////////////////////////////////////////// -/// \brief Get the keycode to keysym map -/// -/// Contains 255 values. Use the keycode as the index -/// into the array to retrieve its keysym. -/// -/// \return Keycode to keysym map -/// -//////////////////////////////////////////////////////////// -const xcb_keysym_t* getKeysymMap(); - -//////////////////////////////////////////////////////////// -/// \brief Build the keysym map -/// -//////////////////////////////////////////////////////////// -void buildKeysymMap(); - } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Unix/InputImpl.cpp b/src/SFML/Window/Unix/InputImpl.cpp index 2ccd63d1..149adb84 100644 --- a/src/SFML/Window/Unix/InputImpl.cpp +++ b/src/SFML/Window/Unix/InputImpl.cpp @@ -32,34 +32,6 @@ #include #include #include -#include - -//////////////////////////////////////////////////////////// -// Private data -//////////////////////////////////////////////////////////// -namespace -{ - bool mapBuilt = false; - - // We use a simple array instead of a map => constant time lookup - xcb_keycode_t keycodeMap[sf::Keyboard::KeyCount]; - - xcb_keycode_t getKeycode(xcb_keysym_t keysym) - { - const xcb_keysym_t* keysymMap = sf::priv::getKeysymMap(); - - for (xcb_keycode_t i = 0; ; ++i) - { - if (keysymMap[i] == keysym) - return i; - - if (i == 255) - break; - } - - return 255; - } -} namespace sf @@ -69,15 +41,125 @@ namespace priv //////////////////////////////////////////////////////////// bool InputImpl::isKeyPressed(Keyboard::Key key) { - if (!mapBuilt) - buildMap(); + // Get the corresponding X11 keysym + KeySym keysym = 0; + switch (key) + { + case Keyboard::A: keysym = XK_A; break; + case Keyboard::B: keysym = XK_B; break; + case Keyboard::C: keysym = XK_C; break; + case Keyboard::D: keysym = XK_D; break; + case Keyboard::E: keysym = XK_E; break; + case Keyboard::F: keysym = XK_F; break; + case Keyboard::G: keysym = XK_G; break; + case Keyboard::H: keysym = XK_H; break; + case Keyboard::I: keysym = XK_I; break; + case Keyboard::J: keysym = XK_J; break; + case Keyboard::K: keysym = XK_K; break; + case Keyboard::L: keysym = XK_L; break; + case Keyboard::M: keysym = XK_M; break; + case Keyboard::N: keysym = XK_N; break; + case Keyboard::O: keysym = XK_O; break; + case Keyboard::P: keysym = XK_P; break; + case Keyboard::Q: keysym = XK_Q; break; + case Keyboard::R: keysym = XK_R; break; + case Keyboard::S: keysym = XK_S; break; + case Keyboard::T: keysym = XK_T; break; + case Keyboard::U: keysym = XK_U; break; + case Keyboard::V: keysym = XK_V; break; + case Keyboard::W: keysym = XK_W; break; + case Keyboard::X: keysym = XK_X; break; + case Keyboard::Y: keysym = XK_Y; break; + case Keyboard::Z: keysym = XK_Z; break; + case Keyboard::Num0: keysym = XK_0; break; + case Keyboard::Num1: keysym = XK_1; break; + case Keyboard::Num2: keysym = XK_2; break; + case Keyboard::Num3: keysym = XK_3; break; + case Keyboard::Num4: keysym = XK_4; break; + case Keyboard::Num5: keysym = XK_5; break; + case Keyboard::Num6: keysym = XK_6; break; + case Keyboard::Num7: keysym = XK_7; break; + case Keyboard::Num8: keysym = XK_8; break; + case Keyboard::Num9: keysym = XK_9; break; + case Keyboard::Escape: keysym = XK_Escape; break; + case Keyboard::LControl: keysym = XK_Control_L; break; + case Keyboard::LShift: keysym = XK_Shift_L; break; + case Keyboard::LAlt: keysym = XK_Alt_L; break; + case Keyboard::LSystem: keysym = XK_Super_L; break; + case Keyboard::RControl: keysym = XK_Control_R; break; + case Keyboard::RShift: keysym = XK_Shift_R; break; + case Keyboard::RAlt: keysym = XK_Alt_R; break; + case Keyboard::RSystem: keysym = XK_Super_R; break; + case Keyboard::Menu: keysym = XK_Menu; break; + case Keyboard::LBracket: keysym = XK_bracketleft; break; + case Keyboard::RBracket: keysym = XK_bracketright; break; + case Keyboard::SemiColon: keysym = XK_semicolon; break; + case Keyboard::Comma: keysym = XK_comma; break; + case Keyboard::Period: keysym = XK_period; break; + case Keyboard::Quote: keysym = XK_dead_acute; break; + case Keyboard::Slash: keysym = XK_slash; break; + case Keyboard::BackSlash: keysym = XK_backslash; break; + case Keyboard::Tilde: keysym = XK_dead_grave; break; + case Keyboard::Equal: keysym = XK_equal; break; + case Keyboard::Dash: keysym = XK_minus; break; + case Keyboard::Space: keysym = XK_space; break; + case Keyboard::Return: keysym = XK_Return; break; + case Keyboard::BackSpace: keysym = XK_BackSpace; break; + case Keyboard::Tab: keysym = XK_Tab; break; + case Keyboard::PageUp: keysym = XK_Prior; break; + case Keyboard::PageDown: keysym = XK_Next; break; + case Keyboard::End: keysym = XK_End; break; + case Keyboard::Home: keysym = XK_Home; break; + case Keyboard::Insert: keysym = XK_Insert; break; + case Keyboard::Delete: keysym = XK_Delete; break; + case Keyboard::Add: keysym = XK_KP_Add; break; + case Keyboard::Subtract: keysym = XK_KP_Subtract; break; + case Keyboard::Multiply: keysym = XK_KP_Multiply; break; + case Keyboard::Divide: keysym = XK_KP_Divide; break; + case Keyboard::Left: keysym = XK_Left; break; + case Keyboard::Right: keysym = XK_Right; break; + case Keyboard::Up: keysym = XK_Up; break; + case Keyboard::Down: keysym = XK_Down; break; + case Keyboard::Numpad0: keysym = XK_KP_0; break; + case Keyboard::Numpad1: keysym = XK_KP_1; break; + case Keyboard::Numpad2: keysym = XK_KP_2; break; + case Keyboard::Numpad3: keysym = XK_KP_3; break; + case Keyboard::Numpad4: keysym = XK_KP_4; break; + case Keyboard::Numpad5: keysym = XK_KP_5; break; + case Keyboard::Numpad6: keysym = XK_KP_6; break; + case Keyboard::Numpad7: keysym = XK_KP_7; break; + case Keyboard::Numpad8: keysym = XK_KP_8; break; + case Keyboard::Numpad9: keysym = XK_KP_9; break; + case Keyboard::F1: keysym = XK_F1; break; + case Keyboard::F2: keysym = XK_F2; break; + case Keyboard::F3: keysym = XK_F3; break; + case Keyboard::F4: keysym = XK_F4; break; + case Keyboard::F5: keysym = XK_F5; break; + case Keyboard::F6: keysym = XK_F6; break; + case Keyboard::F7: keysym = XK_F7; break; + case Keyboard::F8: keysym = XK_F8; break; + case Keyboard::F9: keysym = XK_F9; break; + case Keyboard::F10: keysym = XK_F10; break; + case Keyboard::F11: keysym = XK_F11; break; + case Keyboard::F12: keysym = XK_F12; break; + case Keyboard::F13: keysym = XK_F13; break; + case Keyboard::F14: keysym = XK_F14; break; + case Keyboard::F15: keysym = XK_F15; break; + case Keyboard::Pause: keysym = XK_Pause; break; + default: keysym = 0; break; + } // Sanity checks if (key < 0 || key >= sf::Keyboard::KeyCount) return false; + // Open a connection with the X server + Display* display = OpenDisplay(); + // Convert to keycode - xcb_keycode_t keycode = keycodeMap[key]; + xcb_keycode_t keycode = XKeysymToKeycode(display, keysym); + + CloseDisplay(display); ScopedXcbPtr error(NULL); @@ -316,115 +398,6 @@ Vector2i InputImpl::getTouchPosition(unsigned int /*finger*/, const Window& /*re return Vector2i(); } - -//////////////////////////////////////////////////////////// -void InputImpl::buildMap() -{ - keycodeMap[sf::Keyboard::A] = getKeycode(XK_a); - keycodeMap[sf::Keyboard::B] = getKeycode(XK_b); - keycodeMap[sf::Keyboard::C] = getKeycode(XK_c); - keycodeMap[sf::Keyboard::D] = getKeycode(XK_d); - keycodeMap[sf::Keyboard::E] = getKeycode(XK_e); - keycodeMap[sf::Keyboard::F] = getKeycode(XK_f); - keycodeMap[sf::Keyboard::G] = getKeycode(XK_g); - keycodeMap[sf::Keyboard::H] = getKeycode(XK_h); - keycodeMap[sf::Keyboard::I] = getKeycode(XK_i); - keycodeMap[sf::Keyboard::J] = getKeycode(XK_j); - keycodeMap[sf::Keyboard::K] = getKeycode(XK_k); - keycodeMap[sf::Keyboard::L] = getKeycode(XK_l); - keycodeMap[sf::Keyboard::M] = getKeycode(XK_m); - keycodeMap[sf::Keyboard::N] = getKeycode(XK_n); - keycodeMap[sf::Keyboard::O] = getKeycode(XK_o); - keycodeMap[sf::Keyboard::P] = getKeycode(XK_p); - keycodeMap[sf::Keyboard::Q] = getKeycode(XK_q); - keycodeMap[sf::Keyboard::R] = getKeycode(XK_r); - keycodeMap[sf::Keyboard::S] = getKeycode(XK_s); - keycodeMap[sf::Keyboard::T] = getKeycode(XK_t); - keycodeMap[sf::Keyboard::U] = getKeycode(XK_u); - keycodeMap[sf::Keyboard::V] = getKeycode(XK_v); - keycodeMap[sf::Keyboard::W] = getKeycode(XK_w); - keycodeMap[sf::Keyboard::X] = getKeycode(XK_x); - keycodeMap[sf::Keyboard::Y] = getKeycode(XK_y); - keycodeMap[sf::Keyboard::Z] = getKeycode(XK_z); - keycodeMap[sf::Keyboard::Num0] = getKeycode(XK_KP_Insert); - keycodeMap[sf::Keyboard::Num1] = getKeycode(XK_KP_End); - keycodeMap[sf::Keyboard::Num2] = getKeycode(XK_KP_Down); - keycodeMap[sf::Keyboard::Num3] = getKeycode(XK_KP_Page_Down); - keycodeMap[sf::Keyboard::Num4] = getKeycode(XK_KP_Left); - keycodeMap[sf::Keyboard::Num5] = getKeycode(XK_KP_Begin); - keycodeMap[sf::Keyboard::Num6] = getKeycode(XK_KP_Right); - keycodeMap[sf::Keyboard::Num7] = getKeycode(XK_KP_Home); - keycodeMap[sf::Keyboard::Num8] = getKeycode(XK_KP_Up); - keycodeMap[sf::Keyboard::Num9] = getKeycode(XK_KP_Page_Up); - keycodeMap[sf::Keyboard::Escape] = getKeycode(XK_Escape); - keycodeMap[sf::Keyboard::LControl] = getKeycode(XK_Control_L); - keycodeMap[sf::Keyboard::LShift] = getKeycode(XK_Shift_L); - keycodeMap[sf::Keyboard::LAlt] = getKeycode(XK_Alt_L); - keycodeMap[sf::Keyboard::LSystem] = getKeycode(XK_Super_L); - keycodeMap[sf::Keyboard::RControl] = getKeycode(XK_Control_R); - keycodeMap[sf::Keyboard::RShift] = getKeycode(XK_Shift_R); - keycodeMap[sf::Keyboard::RAlt] = getKeycode(XK_Alt_R); - keycodeMap[sf::Keyboard::RSystem] = getKeycode(XK_Super_R); - keycodeMap[sf::Keyboard::Menu] = getKeycode(XK_Menu); - keycodeMap[sf::Keyboard::LBracket] = getKeycode(XK_bracketleft); - keycodeMap[sf::Keyboard::RBracket] = getKeycode(XK_bracketright); - keycodeMap[sf::Keyboard::SemiColon] = getKeycode(XK_semicolon); - keycodeMap[sf::Keyboard::Comma] = getKeycode(XK_comma); - keycodeMap[sf::Keyboard::Period] = getKeycode(XK_period); - keycodeMap[sf::Keyboard::Quote] = getKeycode(XK_apostrophe); - keycodeMap[sf::Keyboard::Slash] = getKeycode(XK_slash); - keycodeMap[sf::Keyboard::BackSlash] = getKeycode(XK_backslash); - keycodeMap[sf::Keyboard::Tilde] = getKeycode(XK_grave); - keycodeMap[sf::Keyboard::Equal] = getKeycode(XK_equal); - keycodeMap[sf::Keyboard::Dash] = getKeycode(XK_minus); - keycodeMap[sf::Keyboard::Space] = getKeycode(XK_space); - keycodeMap[sf::Keyboard::Return] = getKeycode(XK_Return); - keycodeMap[sf::Keyboard::BackSpace] = getKeycode(XK_BackSpace); - keycodeMap[sf::Keyboard::Tab] = getKeycode(XK_Tab); - keycodeMap[sf::Keyboard::PageUp] = getKeycode(XK_Prior); - keycodeMap[sf::Keyboard::PageDown] = getKeycode(XK_Next); - keycodeMap[sf::Keyboard::End] = getKeycode(XK_End); - keycodeMap[sf::Keyboard::Home] = getKeycode(XK_Home); - keycodeMap[sf::Keyboard::Insert] = getKeycode(XK_Insert); - keycodeMap[sf::Keyboard::Delete] = getKeycode(XK_Delete); - keycodeMap[sf::Keyboard::Add] = getKeycode(XK_KP_Add); - keycodeMap[sf::Keyboard::Subtract] = getKeycode(XK_KP_Subtract); - keycodeMap[sf::Keyboard::Multiply] = getKeycode(XK_KP_Multiply); - keycodeMap[sf::Keyboard::Divide] = getKeycode(XK_KP_Divide); - keycodeMap[sf::Keyboard::Left] = getKeycode(XK_Left); - keycodeMap[sf::Keyboard::Right] = getKeycode(XK_Right); - keycodeMap[sf::Keyboard::Up] = getKeycode(XK_Up); - keycodeMap[sf::Keyboard::Down] = getKeycode(XK_Down); - keycodeMap[sf::Keyboard::Numpad0] = getKeycode(XK_KP_0); - keycodeMap[sf::Keyboard::Numpad1] = getKeycode(XK_KP_1); - keycodeMap[sf::Keyboard::Numpad2] = getKeycode(XK_KP_2); - keycodeMap[sf::Keyboard::Numpad3] = getKeycode(XK_KP_3); - keycodeMap[sf::Keyboard::Numpad4] = getKeycode(XK_KP_4); - keycodeMap[sf::Keyboard::Numpad5] = getKeycode(XK_KP_5); - keycodeMap[sf::Keyboard::Numpad6] = getKeycode(XK_KP_6); - keycodeMap[sf::Keyboard::Numpad7] = getKeycode(XK_KP_7); - keycodeMap[sf::Keyboard::Numpad8] = getKeycode(XK_KP_8); - keycodeMap[sf::Keyboard::Numpad9] = getKeycode(XK_KP_9); - keycodeMap[sf::Keyboard::F1] = getKeycode(XK_F1); - keycodeMap[sf::Keyboard::F2] = getKeycode(XK_F2); - keycodeMap[sf::Keyboard::F3] = getKeycode(XK_F3); - keycodeMap[sf::Keyboard::F4] = getKeycode(XK_F4); - keycodeMap[sf::Keyboard::F5] = getKeycode(XK_F5); - keycodeMap[sf::Keyboard::F6] = getKeycode(XK_F6); - keycodeMap[sf::Keyboard::F7] = getKeycode(XK_F7); - keycodeMap[sf::Keyboard::F8] = getKeycode(XK_F8); - keycodeMap[sf::Keyboard::F9] = getKeycode(XK_F9); - keycodeMap[sf::Keyboard::F10] = getKeycode(XK_F10); - keycodeMap[sf::Keyboard::F11] = getKeycode(XK_F11); - keycodeMap[sf::Keyboard::F12] = getKeycode(XK_F12); - keycodeMap[sf::Keyboard::F13] = getKeycode(XK_F13); - keycodeMap[sf::Keyboard::F14] = getKeycode(XK_F14); - keycodeMap[sf::Keyboard::F15] = getKeycode(XK_F15); - keycodeMap[sf::Keyboard::Pause] = getKeycode(XK_Pause); - - mapBuilt = true; -} - } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Unix/InputImpl.hpp b/src/SFML/Window/Unix/InputImpl.hpp index ec4f11e9..9425c3df 100644 --- a/src/SFML/Window/Unix/InputImpl.hpp +++ b/src/SFML/Window/Unix/InputImpl.hpp @@ -158,12 +158,6 @@ public: /// //////////////////////////////////////////////////////////// static Vector2i getTouchPosition(unsigned int finger, const Window& relativeTo); - - //////////////////////////////////////////////////////////// - /// \brief Build the SFML to X11 keymap - /// - //////////////////////////////////////////////////////////// - static void buildMap(); }; } // namespace priv diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 1f6ed09f..40768136 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -47,14 +47,6 @@ #include #include -// So we don't have to require xcb dri2 to be present -#define XCB_DRI2_BUFFER_SWAP_COMPLETE 0 -#define XCB_DRI2_INVALIDATE_BUFFERS 1 - -// So we don't have to require xcb xkb to be present -#define XCB_XKB_NEW_KEYBOARD_NOTIFY 0 -#define XCB_XKB_MAP_NOTIFY 1 - #ifdef SFML_OPENGL_ES #include typedef sf::priv::EglContext ContextType; @@ -73,18 +65,19 @@ namespace sf::Mutex allWindowsMutex; sf::String windowManagerName; - bool mapBuilt = false; - - // We use a simple array instead of a map => constant time lookup - // xcb_keycode_t can only contain 256 distinct values - sf::Keyboard::Key sfKeyMap[256]; - static const unsigned long eventMask = XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW; + // Filter the events received by windows (only allow those matching a specific window) + Bool checkEvent(::Display*, XEvent* event, XPointer userData) + { + // Just check if the event matches the window + return event->xany.window == reinterpret_cast< ::Window >(userData); + } + // Find the name of the current executable std::string findExecutableName() { @@ -245,124 +238,6 @@ namespace return true; } - xcb_query_extension_reply_t getXExtension(const std::string& name) - { - xcb_connection_t* connection = sf::priv::OpenConnection(); - - sf::priv::ScopedXcbPtr error(NULL); - sf::priv::ScopedXcbPtr extension(xcb_query_extension_reply( - connection, - xcb_query_extension( - connection, - name.size(), - name.c_str() - ), - &error - )); - - // Close the connection with the X server - sf::priv::CloseConnection(connection); - - if (error || !extension || !extension->present) - { - xcb_query_extension_reply_t reply; - std::memset(&reply, 0, sizeof(reply)); - return reply; - } - - return *extension.get(); - } - - void dumpXcbExtensions() - { - xcb_connection_t* connection = sf::priv::OpenConnection(); - - sf::priv::ScopedXcbPtr error(NULL); - - // Check if the RandR extension is present - sf::priv::ScopedXcbPtr extensions(xcb_list_extensions_reply( - connection, - xcb_list_extensions( - connection - ), - &error - )); - - if (error || !extensions) - { - // Close the connection with the X server - sf::priv::CloseConnection(connection); - - sf::err() << "Couldn't get list of X extensions" << std::endl; - return; - } - - xcb_str_iterator_t iter = xcb_list_extensions_names_iterator(extensions.get()); - - sf::err() << "X Extensions:" << std::endl; - - while (iter.rem) - { - std::string name(xcb_str_name(iter.data), xcb_str_name_length(iter.data)); - - sf::priv::ScopedXcbPtr error(NULL); - - // Check if the RandR extension is present - sf::priv::ScopedXcbPtr extension(xcb_query_extension_reply( - connection, - xcb_query_extension( - connection, - name.size(), - name.c_str() - ), - &error - )); - - if (error || !extension || !extension->present) - { - sf::err() << "\t" << name << " - Failed to query" << std::endl; - continue; - } - - int firstEvent = extension->first_event; - - sf::err() << "\t" << name << " - First event: " << firstEvent << std::endl; - iter.data += xcb_str_name_length(iter.data) + 1; - --iter.rem; - } - - // Close the connection with the X server - sf::priv::CloseConnection(connection); - } - - void dumpUnhandledEvent(uint8_t type) - { - static std::vector types; - - // Check if we already reported this type - if (std::find(types.begin(), types.end(), type) != types.end()) - return; - - // Insert it if new - types.push_back(type); - - static bool dumpedExtensions = false; - - if (!dumpedExtensions) - { - dumpXcbExtensions(); - dumpedExtensions = true; - } - - sf::err() << "Unhandled event type: " << (static_cast(type) & ~0x80) << std::endl - << "Report this to the SFML maintainers if possible" << std::endl; - } - - xcb_keysym_t getKeysymFromKeycode(xcb_keycode_t keycode) - { - return sf::priv::getKeysymMap()[keycode]; - } - sf::Keyboard::Key keysymToSF(xcb_keysym_t symbol) { switch (symbol) @@ -473,27 +348,6 @@ namespace return sf::Keyboard::Unknown; } - - void buildMap() - { - for (xcb_keycode_t i = 0; ; ++i) - { - sfKeyMap[i] = keysymToSF(getKeysymFromKeycode(i)); - - if (i == 255) - break; - } - - mapBuilt = true; - } - - sf::Keyboard::Key keycodeToSF(xcb_keycode_t keycode) - { - if (!mapBuilt) - buildMap(); - - return sfKeyMap[keycode]; - } } @@ -529,7 +383,6 @@ m_fullscreen (false) ewmhSupported(); m_screen = XCBDefaultScreen(m_connection); - XSetEventQueueOwner(m_display, XCBOwnsEventQueue); // Save the window handle m_window = handle; @@ -583,7 +436,6 @@ m_fullscreen ((style & Style::Fullscreen) != 0) ewmhSupported(); m_screen = XCBDefaultScreen(m_connection); - XSetEventQueueOwner(m_display, XCBOwnsEventQueue); // Compute position and size int left = m_fullscreen ? 0 : (m_screen->width_in_pixels - mode.width) / 2; @@ -737,105 +589,10 @@ WindowHandle WindowImplX11::getSystemHandle() const //////////////////////////////////////////////////////////// void WindowImplX11::processEvents() { - // Key repeat workaround: If key repeat is enabled, XCB will spawn two - // events for each repeat interval: key release and key press. Both have - // the same timestamp and key code. We are holding back the release event - // to check for the matching key press event and if so, discard the release - // event. - - xcb_generic_event_t* event = NULL; - xcb_key_release_event_t* lastKeyReleaseEvent = NULL; - uint8_t eventType = 0; - - if (!m_xcbEvents.empty()) + XEvent event; + while (XCheckIfEvent(m_display, &event, &checkEvent, reinterpret_cast(m_window))) { - event = m_xcbEvents.front(); - m_xcbEvents.pop_front(); - } - else - { - event = xcb_poll_for_event(m_connection); - } - - while (event) - { - eventType = event->response_type & ~0x80; - - // Key was pressed and one has been released prior to that. - if (eventType == XCB_KEY_PRESS && lastKeyReleaseEvent) - { - // If the key press event matches the held back key release event, - // then we have a key repeat and discard the held back release - // event. - if (lastKeyReleaseEvent->time == reinterpret_cast(event)->time && - lastKeyReleaseEvent->detail == reinterpret_cast(event)->detail) - { - free(lastKeyReleaseEvent); - lastKeyReleaseEvent = NULL; - - // If key repeat is disabled, discard the matching key press event as well - if (!m_keyRepeat) - { - free(event); - - if (!m_xcbEvents.empty()) - { - event = m_xcbEvents.front(); - m_xcbEvents.pop_front(); - } - else - { - event = xcb_poll_for_event(m_connection); - } - - continue; - } - } - } - - // If there's still a key release event held back, process it now. - if (lastKeyReleaseEvent) - { - if (processEvent(reinterpret_cast(lastKeyReleaseEvent))) - free(lastKeyReleaseEvent); - - lastKeyReleaseEvent = NULL; - } - - if (eventType == XCB_KEY_RELEASE) - { - // Check if we're in charge of the key release - if (!passEvent(event, reinterpret_cast(event)->event)) - { - // Remember this key release event. - lastKeyReleaseEvent = reinterpret_cast(event); - event = NULL; // For safety reasons. - } - } - else - { - if (processEvent(event)) - free(event); - } - - if (!m_xcbEvents.empty()) - { - event = m_xcbEvents.front(); - m_xcbEvents.pop_front(); - } - else - { - event = xcb_poll_for_event(m_connection); - } - } - - // Process any held back release event. - if (lastKeyReleaseEvent) - { - if (processEvent(reinterpret_cast(lastKeyReleaseEvent))) - free(lastKeyReleaseEvent); - - lastKeyReleaseEvent = NULL; + processEvent(event); } } @@ -1847,28 +1604,57 @@ void WindowImplX11::cleanup() //////////////////////////////////////////////////////////// -bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) +bool WindowImplX11::processEvent(XEvent windowEvent) { + // This function implements a workaround to properly discard + // repeated key events when necessary. The problem is that the + // system's key events policy doesn't match SFML's one: X server will generate + // both repeated KeyPress and KeyRelease events when maintaining a key down, while + // SFML only wants repeated KeyPress events. Thus, we have to: + // - Discard duplicated KeyRelease events when KeyRepeatEnabled is true + // - Discard both duplicated KeyPress and KeyRelease events when KeyRepeatEnabled is false + + // Detect repeated key events + // (code shamelessly taken from SDL) + if (windowEvent.type == KeyRelease) + { + // Check if there's a matching KeyPress event in the queue + XEvent nextEvent; + if (XPending(m_display)) + { + // Grab it but don't remove it from the queue, it still needs to be processed :) + XPeekEvent(m_display, &nextEvent); + if (nextEvent.type == KeyPress) + { + // Check if it is a duplicated event (same timestamp as the KeyRelease event) + if ((nextEvent.xkey.keycode == windowEvent.xkey.keycode) && + (nextEvent.xkey.time - windowEvent.xkey.time < 2)) + { + // If we don't want repeated events, remove the next KeyPress from the queue + if (!m_keyRepeat) + XNextEvent(m_display, &nextEvent); + + // This KeyRelease is a repeated event and we don't want it + return false; + } + } + } + } + // Convert the X11 event to a sf::Event - switch (windowEvent->response_type & ~0x80) + switch (windowEvent.type) { // Destroy event - case XCB_DESTROY_NOTIFY: + case DestroyNotify: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->window)) - return false; - // The window is about to be destroyed: we must cleanup resources cleanup(); break; } // Gain focus event - case XCB_FOCUS_IN: + case FocusIn: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - // Update the input context if (m_inputContext) XSetICFocus(m_inputContext); @@ -1909,11 +1695,8 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Lost focus event - case XCB_FOCUS_OUT: + case FocusOut: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - // Update the input context if (m_inputContext) XUnsetICFocus(m_inputContext); @@ -1925,56 +1708,51 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Resize event - case XCB_CONFIGURE_NOTIFY: + case ConfigureNotify: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->window)) - return false; - - // X notifies about "window configuration events", which also includes moving a window only. Check - // for a different size and only spawn a Resized event when it differs. - xcb_configure_notify_event_t* e = reinterpret_cast(windowEvent); - - if (e->width != m_previousSize.x || e->height != m_previousSize.y) + // ConfigureNotify can be triggered for other reasons, check if the size has actually changed + if ((windowEvent.xconfigure.width != m_previousSize.x) || (windowEvent.xconfigure.height != m_previousSize.y)) { - m_previousSize.x = e->width; - m_previousSize.y = e->height; - Event event; event.type = Event::Resized; - event.size.width = e->width; - event.size.height = e->height; + event.size.width = windowEvent.xconfigure.width; + event.size.height = windowEvent.xconfigure.height; pushEvent(event); + + m_previousSize.x = windowEvent.xconfigure.width; + m_previousSize.y = windowEvent.xconfigure.height; } break; } // Close event - case XCB_CLIENT_MESSAGE: + case ClientMessage: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->window)) - return false; - - xcb_client_message_event_t* e = reinterpret_cast(windowEvent); - static xcb_atom_t wmProtocols = getAtom("WM_PROTOCOLS"); // Handle window manager protocol messages we support - if (e->type == wmProtocols) + if (windowEvent.xclient.message_type == wmProtocols) { static xcb_atom_t wmDeleteWindow = getAtom("WM_DELETE_WINDOW"); static xcb_atom_t netWmPing = ewmhSupported() ? getAtom("_NET_WM_PING", true) : XCB_ATOM_NONE; - if ((e->format == 32) && (e->data.data32[0]) == static_cast(wmDeleteWindow)) + if ((windowEvent.xclient.format == 32) && (windowEvent.xclient.data.l[0]) == static_cast(wmDeleteWindow)) { // Handle the WM_DELETE_WINDOW message Event event; event.type = Event::Closed; pushEvent(event); } - else if (netWmPing && (e->format == 32) && (e->data.data32[0]) == static_cast(netWmPing)) + else if (netWmPing && (windowEvent.xclient.format == 32) && (windowEvent.xclient.data.l[0]) == static_cast(netWmPing)) { + xcb_client_message_event_t event; + // Handle the _NET_WM_PING message, send pong back to WM to show that we are responsive - e->window = XCBDefaultRootWindow(m_connection); + event.response_type = XCB_CLIENT_MESSAGE; + event.format = windowEvent.xclient.format; + event.window = XCBDefaultRootWindow(m_connection); + event.type = windowEvent.xclient.message_type; + std::memcpy(event.data.data8, windowEvent.xclient.data.b, 20); ScopedXcbPtr pongError(xcb_request_check( m_connection, @@ -1983,7 +1761,7 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) 0, XCBDefaultRootWindow(m_connection), XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, - reinterpret_cast(e) + reinterpret_cast(&event) ) )); @@ -1995,33 +1773,27 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Key down event - case XCB_KEY_PRESS: + case KeyPress: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - - xcb_key_press_event_t* e = reinterpret_cast(windowEvent); + // Get the keysym of the key that has been pressed + static XComposeStatus keyboard; + char buffer[32]; + KeySym symbol; + XLookupString(&windowEvent.xkey, buffer, sizeof(buffer), &symbol, &keyboard); // Fill the event parameters // TODO: if modifiers are wrong, use XGetModifierMapping to retrieve the actual modifiers mapping Event event; event.type = Event::KeyPressed; - event.key.code = keycodeToSF(e->detail); - event.key.alt = e->state & XCB_MOD_MASK_1; - event.key.control = e->state & XCB_MOD_MASK_CONTROL; - event.key.shift = e->state & XCB_MOD_MASK_SHIFT; - event.key.system = e->state & XCB_MOD_MASK_4; + event.key.code = keysymToSF(symbol); + event.key.alt = windowEvent.xkey.state & Mod1Mask; + event.key.control = windowEvent.xkey.state & ControlMask; + event.key.shift = windowEvent.xkey.state & ShiftMask; + event.key.system = windowEvent.xkey.state & Mod4Mask; pushEvent(event); - XEvent fakeEvent; - fakeEvent.type = KeyPress; - fakeEvent.xany.display = m_display; - fakeEvent.xany.window = e->event; - fakeEvent.xkey.state = e->state; - fakeEvent.xkey.keycode = e->detail; - // Generate a TextEntered event - if (!XFilterEvent(&fakeEvent, None)) + if (!XFilterEvent(&windowEvent, None)) { #ifdef X_HAVE_UTF8_STRING if (m_inputContext) @@ -2031,7 +1803,7 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) int length = Xutf8LookupString( m_inputContext, - &fakeEvent.xkey, + &windowEvent.xkey, reinterpret_cast(keyBuffer), sizeof(keyBuffer), NULL, @@ -2056,7 +1828,7 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) { static XComposeStatus status; char keyBuffer[16]; - if (XLookupString(&fakeEvent.xkey, keyBuffer, sizeof(keyBuffer), NULL, &status)) + if (XLookupString(&windowEvent.xkey, keyBuffer, sizeof(keyBuffer), NULL, &status)) { Event textEvent; textEvent.type = Event::TextEntered; @@ -2070,54 +1842,49 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Key up event - case XCB_KEY_RELEASE: + case KeyRelease: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - - xcb_key_release_event_t* e = reinterpret_cast(windowEvent); + // Get the keysym of the key that has been pressed + char buffer[32]; + KeySym symbol; + XLookupString(&windowEvent.xkey, buffer, 32, &symbol, NULL); // Fill the event parameters Event event; event.type = Event::KeyReleased; - event.key.code = keycodeToSF(e->detail); - event.key.alt = e->state & XCB_MOD_MASK_1; - event.key.control = e->state & XCB_MOD_MASK_CONTROL; - event.key.shift = e->state & XCB_MOD_MASK_SHIFT; - event.key.system = e->state & XCB_MOD_MASK_4; + event.key.code = keysymToSF(symbol); + event.key.alt = windowEvent.xkey.state & Mod1Mask; + event.key.control = windowEvent.xkey.state & ControlMask; + event.key.shift = windowEvent.xkey.state & ShiftMask; + event.key.system = windowEvent.xkey.state & Mod4Mask; pushEvent(event); break; } // Mouse button pressed - case XCB_BUTTON_PRESS: + case ButtonPress: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - - xcb_button_press_event_t* e = reinterpret_cast(windowEvent); - // XXX: Why button 8 and 9? // Because 4 and 5 are the vertical wheel and 6 and 7 are horizontal wheel ;) - xcb_button_t button = e->detail; - if ((button == XCB_BUTTON_INDEX_1) || - (button == XCB_BUTTON_INDEX_2) || - (button == XCB_BUTTON_INDEX_3) || + unsigned int button = windowEvent.xbutton.button; + if ((button == Button1) || + (button == Button2) || + (button == Button3) || (button == 8) || (button == 9)) { Event event; event.type = Event::MouseButtonPressed; - event.mouseButton.x = e->event_x; - event.mouseButton.y = e->event_y; + event.mouseButton.x = windowEvent.xbutton.x; + event.mouseButton.y = windowEvent.xbutton.y; switch(button) { - case XCB_BUTTON_INDEX_1: event.mouseButton.button = Mouse::Left; break; - case XCB_BUTTON_INDEX_2: event.mouseButton.button = Mouse::Middle; break; - case XCB_BUTTON_INDEX_3: event.mouseButton.button = Mouse::Right; break; - case 8: event.mouseButton.button = Mouse::XButton1; break; - case 9: event.mouseButton.button = Mouse::XButton2; break; + case Button1: event.mouseButton.button = Mouse::Left; break; + case Button2: event.mouseButton.button = Mouse::Middle; break; + case Button3: event.mouseButton.button = Mouse::Right; break; + case 8: event.mouseButton.button = Mouse::XButton1; break; + case 9: event.mouseButton.button = Mouse::XButton2; break; } pushEvent(event); } @@ -2125,49 +1892,44 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Mouse button released - case XCB_BUTTON_RELEASE: + case ButtonRelease: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - - xcb_button_release_event_t* e = reinterpret_cast(windowEvent); - - xcb_button_t button = e->detail; - if ((button == XCB_BUTTON_INDEX_1) || - (button == XCB_BUTTON_INDEX_2) || - (button == XCB_BUTTON_INDEX_3) || + unsigned int button = windowEvent.xbutton.button; + if ((button == Button1) || + (button == Button2) || + (button == Button3) || (button == 8) || (button == 9)) { Event event; event.type = Event::MouseButtonReleased; - event.mouseButton.x = e->event_x; - event.mouseButton.y = e->event_y; + event.mouseButton.x = windowEvent.xbutton.x; + event.mouseButton.y = windowEvent.xbutton.y; switch(button) { - case XCB_BUTTON_INDEX_1: event.mouseButton.button = Mouse::Left; break; - case XCB_BUTTON_INDEX_2: event.mouseButton.button = Mouse::Middle; break; - case XCB_BUTTON_INDEX_3: event.mouseButton.button = Mouse::Right; break; - case 8: event.mouseButton.button = Mouse::XButton1; break; - case 9: event.mouseButton.button = Mouse::XButton2; break; + case Button1: event.mouseButton.button = Mouse::Left; break; + case Button2: event.mouseButton.button = Mouse::Middle; break; + case Button3: event.mouseButton.button = Mouse::Right; break; + case 8: event.mouseButton.button = Mouse::XButton1; break; + case 9: event.mouseButton.button = Mouse::XButton2; break; } pushEvent(event); } - else if ((button == XCB_BUTTON_INDEX_4) || (button == XCB_BUTTON_INDEX_5)) + else if ((button == Button4) || (button == Button5)) { Event event; event.type = Event::MouseWheelMoved; - event.mouseWheel.delta = (button == XCB_BUTTON_INDEX_4) ? 1 : -1; - event.mouseWheel.x = e->event_x; - event.mouseWheel.y = e->event_y; + event.mouseWheel.delta = (button == Button4) ? 1 : -1; + event.mouseWheel.x = windowEvent.xbutton.x; + event.mouseWheel.y = windowEvent.xbutton.y; pushEvent(event); event.type = Event::MouseWheelScrolled; event.mouseWheelScroll.wheel = Mouse::VerticalWheel; - event.mouseWheelScroll.delta = (button == XCB_BUTTON_INDEX_4) ? 1 : -1; - event.mouseWheelScroll.x = e->event_x; - event.mouseWheelScroll.y = e->event_y; + event.mouseWheelScroll.delta = (button == Button4) ? 1 : -1; + event.mouseWheelScroll.x = windowEvent.xbutton.x; + event.mouseWheelScroll.y = windowEvent.xbutton.y; pushEvent(event); } else if ((button == 6) || (button == 7)) @@ -2176,37 +1938,28 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) event.type = Event::MouseWheelScrolled; event.mouseWheelScroll.wheel = Mouse::HorizontalWheel; event.mouseWheelScroll.delta = (button == 6) ? 1 : -1; - event.mouseWheelScroll.x = e->event_x; - event.mouseWheelScroll.y = e->event_y; + event.mouseWheelScroll.x = windowEvent.xbutton.x; + event.mouseWheelScroll.y = windowEvent.xbutton.y; pushEvent(event); } break; } // Mouse moved - case XCB_MOTION_NOTIFY: + case MotionNotify: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - - xcb_motion_notify_event_t* e = reinterpret_cast(windowEvent); Event event; event.type = Event::MouseMoved; - event.mouseMove.x = e->event_x; - event.mouseMove.y = e->event_y; + event.mouseMove.x = windowEvent.xmotion.x; + event.mouseMove.y = windowEvent.xmotion.y; pushEvent(event); break; } // Mouse entered - case XCB_ENTER_NOTIFY: + case EnterNotify: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - - xcb_enter_notify_event_t* enterNotifyEvent = reinterpret_cast(windowEvent); - - if (enterNotifyEvent->mode == NotifyNormal) + if (windowEvent.xcrossing.mode == NotifyNormal) { Event event; event.type = Event::MouseEntered; @@ -2216,14 +1969,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Mouse left - case XCB_LEAVE_NOTIFY: + case LeaveNotify: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - - xcb_leave_notify_event_t* leaveNotifyEvent = reinterpret_cast(windowEvent); - - if (leaveNotifyEvent->mode == NotifyNormal) + if (windowEvent.xcrossing.mode == NotifyNormal) { Event event; event.type = Event::MouseLeft; @@ -2233,152 +1981,15 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Parent window changed - case XCB_REPARENT_NOTIFY: + case ReparentNotify: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->window)) - return false; - // Catch reparent events to properly apply fullscreen on // some "strange" window managers (like Awesome) which // seem to make use of temporary parents during mapping if (m_fullscreen) switchToFullscreen(); - xcb_flush(m_connection); // Discard remaining events - break; - } - - // The stuff that might pop up but we don't care about - // Whitelist more when necessary - // Window visibility changed (hide/unhide) - case XCB_MAP_NOTIFY: - case XCB_UNMAP_NOTIFY: - { - break; - } - - // Handle the rest - default: - { - uint8_t responseType = windowEvent->response_type & ~0x80; - - // Handle any extension events first - - // SHAPE - // Ubuntu's Unity desktop environment makes use of the - // Compiz compositing window manager - // Compiz seems to send SHAPE events to windows even if they - // did not specifically select those events - // We ignore those events here in order to not generate warnings - static xcb_query_extension_reply_t shapeExtension = getXExtension("SHAPE"); - if (shapeExtension.present && (responseType == shapeExtension.first_event)) - break; - - // DRI2 - static xcb_query_extension_reply_t driExtension = getXExtension("DRI2"); - if (driExtension.present) - { - // Because we are using the XCB event queue instead of the Xlib event - // queue, Mesa breaks a bit (VSync among other things) because DRI2 still - // expects certain Xlib events to come its way. We work around this by - // emulating the old Xlib event queue for these specific wire events. - // Sources (retrieved 27 Mar 2015): - // http://wrl.illest.net/post/45342765813/code-tip-glx-and-xcbownseventqueue - // https://bugs.freedesktop.org/show_bug.cgi?id=42131 - // https://bugs.freedesktop.org/show_bug.cgi?id=35945 - // Mesa src/glx/dri2.c - // QtBase src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp - // QtBase Commit bb22b4965070409df4658f16fdf549f0362e8a9c - // Qt Change-Id I3b4ef3f6e3efbae25f49f161e229e9b15e951778 - // QtBase Commit 13c5c81cfa934c9b610720fe79e07465b00ebc8d - // Qt Change-Id Ia93eb8be1cbbc3d8ae7913a934c195af6b5ec538 - // QtBase Commit decb88693c8a7f0c073889b91151f01a850e3adf - // Qt Change-Id Ic466ff26487937b03f072a57e0ee4df335492a5f - if ((responseType == driExtension.first_event + XCB_DRI2_BUFFER_SWAP_COMPLETE) || - (responseType == driExtension.first_event + XCB_DRI2_INVALIDATE_BUFFERS)) - { - // DRI2 BufferSwapComplete and InvalidateBuffers - - // We lock/unlock the display to protect against concurrent access - XLockDisplay(m_display); - - typedef Bool (*wireEventHandler)(Display*, XEvent*, xEvent*); - - // Probe for any handlers that are registered for this event type - wireEventHandler handler = XESetWireToEvent(m_display, responseType, 0); - - if (handler) - { - // Restore the previous handler if one was registered - XESetWireToEvent(m_display, responseType, handler); - - XEvent event; - windowEvent->sequence = LastKnownRequestProcessed(m_display); - - // Pretend to be the Xlib event queue - handler(m_display, &event, reinterpret_cast(windowEvent)); - } - - XUnlockDisplay(m_display); - - return true; - } - } - - // XKEYBOARD - // When the X server sends us XKEYBOARD events, it means that - // the user probably changed the layout of their keyboard - // We update our keymaps in that case - static xcb_query_extension_reply_t xkeyboardExtension = getXExtension("XKEYBOARD"); - if (xkeyboardExtension.present && (responseType == xkeyboardExtension.first_event)) - { - // We do this so we don't have to include the xkb header for the struct declaration - uint8_t xkbType = reinterpret_cast(windowEvent)[1]; - - // We only bother rebuilding our maps if the xkb mapping actually changes - if ((xkbType == XCB_XKB_NEW_KEYBOARD_NOTIFY) || (xkbType == XCB_XKB_MAP_NOTIFY)) - { - // keysym map - buildKeysymMap(); - - // keycode to SFML - buildMap(); - - // SFML to keycode - InputImpl::buildMap(); - - // XInputMethod expects keyboard mapping changes to be propagated to it - // Same idea here as with the DRI2 events above - - // We lock/unlock the display to protect against concurrent access - XLockDisplay(m_display); - - typedef Bool (*wireEventHandler)(Display*, XEvent*, xEvent*); - - // Probe for any handlers that are registered for this event type - wireEventHandler handler = XESetWireToEvent(m_display, responseType, 0); - - if (handler) - { - // Restore the previous handler if one was registered - XESetWireToEvent(m_display, responseType, handler); - - XEvent event; - windowEvent->sequence = LastKnownRequestProcessed(m_display); - - // Pretend to be the Xlib event queue - handler(m_display, &event, reinterpret_cast(windowEvent)); - } - - XUnlockDisplay(m_display); - } - - break; - } - - // Print any surprises to stderr (would be nice if people report when this happens) - dumpUnhandledEvent(responseType); - + XSync(m_display, True); // Discard remaining events break; } } @@ -2386,33 +1997,6 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) return true; } - -//////////////////////////////////////////////////////////// -bool WindowImplX11::passEvent(xcb_generic_event_t* windowEvent, xcb_window_t window) -{ - // Check if this is our event - if (window == m_window) - return false; - - Lock lock(allWindowsMutex); - - // If we are the only window, there is nobody else to pass to - if (allWindows.size() == 1) - return false; - - for (std::vector::iterator i = allWindows.begin(); i != allWindows.end(); ++i) - { - if ((*i)->m_window == window) - { - (*i)->m_xcbEvents.push_back(windowEvent); - return true; - } - } - - // It seems nobody wants the event, we'll just handle it ourselves - return false; -} - } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Unix/WindowImplX11.hpp b/src/SFML/Window/Unix/WindowImplX11.hpp index 2e31fbf5..a717bfb3 100644 --- a/src/SFML/Window/Unix/WindowImplX11.hpp +++ b/src/SFML/Window/Unix/WindowImplX11.hpp @@ -301,18 +301,7 @@ private: /// \return True if the event was processed, false if it was discarded /// //////////////////////////////////////////////////////////// - bool processEvent(xcb_generic_event_t* windowEvent); - - //////////////////////////////////////////////////////////// - /// \brief Pass an incoming event to another window - /// - /// \param windowEvent Event which is being processed - /// \param window Window to pass to - /// - /// \return True if the event was passed to another window, false if it is destined for the current window - /// - //////////////////////////////////////////////////////////// - bool passEvent(xcb_generic_event_t* windowEvent, xcb_window_t window); + bool processEvent(XEvent windowEvent); //////////////////////////////////////////////////////////// // Member data @@ -323,7 +312,6 @@ private: xcb_screen_t* m_screen; ///< Screen identifier XIM m_inputMethod; ///< Input method linked to the X display XIC m_inputContext; ///< Input context used to get unicode input in our window - std::deque m_xcbEvents; ///< Events that were received in another window's loop bool m_isExternal; ///< Tell whether the window has been created externally or by SFML xcb_randr_get_screen_info_reply_t m_oldVideoMode; ///< Video mode in use before we switch to fullscreen Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one