diff options
Diffstat (limited to 'src/SFML/Window/Unix/InputImpl.cpp')
-rw-r--r-- | src/SFML/Window/Unix/InputImpl.cpp | 442 |
1 files changed, 273 insertions, 169 deletions
diff --git a/src/SFML/Window/Unix/InputImpl.cpp b/src/SFML/Window/Unix/InputImpl.cpp index 8ff7697..4d815f8 100644 --- a/src/SFML/Window/Unix/InputImpl.cpp +++ b/src/SFML/Window/Unix/InputImpl.cpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org) // // This software is provided 'as-is', without any express or implied warranty. // In no event will the authors be held liable for any damages arising from the use of this software. @@ -25,11 +25,148 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// +#include <SFML/Window/Window.hpp> // important to be included first (conflict with None) #include <SFML/Window/Unix/InputImpl.hpp> -#include <SFML/Window/Window.hpp> #include <SFML/Window/Unix/Display.hpp> -#include <X11/Xlib.h> +#include <SFML/Window/Unix/ScopedXcbPtr.hpp> +#include <SFML/System/Err.hpp> +#include <xcb/xcb.h> #include <X11/keysym.h> +#include <cstdlib> + +//////////////////////////////////////////////////////////// +// 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; + } + + void 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_0); + keycodeMap[sf::Keyboard::Num1] = getKeycode(XK_1); + keycodeMap[sf::Keyboard::Num2] = getKeycode(XK_2); + keycodeMap[sf::Keyboard::Num3] = getKeycode(XK_3); + keycodeMap[sf::Keyboard::Num4] = getKeycode(XK_4); + keycodeMap[sf::Keyboard::Num5] = getKeycode(XK_5); + keycodeMap[sf::Keyboard::Num6] = getKeycode(XK_6); + keycodeMap[sf::Keyboard::Num7] = getKeycode(XK_7); + keycodeMap[sf::Keyboard::Num8] = getKeycode(XK_8); + keycodeMap[sf::Keyboard::Num9] = getKeycode(XK_9); + 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 sf @@ -39,143 +176,47 @@ namespace priv //////////////////////////////////////////////////////////// bool InputImpl::isKeyPressed(Keyboard::Key key) { - // 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; - } + if (!mapBuilt) + buildMap(); - // Open a connection with the X server - Display* display = OpenDisplay(); + // Sanity checks + if (key < 0 || key >= sf::Keyboard::KeyCount) + return false; // Convert to keycode - KeyCode keycode = XKeysymToKeycode(display, keysym); - if (keycode != 0) - { - // Get the whole keyboard state - char keys[32]; - XQueryKeymap(display, keys); + xcb_keycode_t keycode = keycodeMap[key]; - // Close the connection with the X server - CloseDisplay(display); + ScopedXcbPtr<xcb_generic_error_t> error(NULL); - // Check our keycode - return (keys[keycode / 8] & (1 << (keycode % 8))) != 0; - } - else + // Open a connection with the X server + xcb_connection_t* connection = OpenConnection(); + + // Get the whole keyboard state + ScopedXcbPtr<xcb_query_keymap_reply_t> keymap( + xcb_query_keymap_reply( + connection, + xcb_query_keymap(connection), + &error + ) + ); + + // Close the connection with the X server + CloseConnection(connection); + + if (error) { - // Close the connection with the X server - CloseDisplay(display); + err() << "Failed to query keymap" << std::endl; return false; } + + // Check our keycode + return (keymap->keys[keycode / 8] & (1 << (keycode % 8))) != 0; } //////////////////////////////////////////////////////////// -void InputImpl::setVirtualKeyboardVisible(bool visible) +void InputImpl::setVirtualKeyboardVisible(bool /*visible*/) { // Not applicable } @@ -185,30 +226,43 @@ void InputImpl::setVirtualKeyboardVisible(bool visible) bool InputImpl::isMouseButtonPressed(Mouse::Button button) { // Open a connection with the X server - Display* display = OpenDisplay(); + xcb_connection_t* connection = OpenConnection(); + + ScopedXcbPtr<xcb_generic_error_t> error(NULL); + + // Get pointer mask + ScopedXcbPtr<xcb_query_pointer_reply_t> pointer( + xcb_query_pointer_reply( + connection, + xcb_query_pointer( + connection, + XCBDefaultRootWindow(connection) + ), + &error + ) + ); - // we don't care about these but they are required - ::Window root, child; - int wx, wy; - int gx, gy; + // Close the connection with the X server + CloseConnection(connection); - unsigned int buttons = 0; - XQueryPointer(display, DefaultRootWindow(display), &root, &child, &gx, &gy, &wx, &wy, &buttons); + if (error) + { + err() << "Failed to query pointer" << std::endl; - // Close the connection with the X server - CloseDisplay(display); + return false; + } + + uint16_t buttons = pointer->mask; switch (button) { - case Mouse::Left: return buttons & Button1Mask; - case Mouse::Right: return buttons & Button3Mask; - case Mouse::Middle: return buttons & Button2Mask; + case Mouse::Left: return buttons & XCB_BUTTON_MASK_1; + case Mouse::Right: return buttons & XCB_BUTTON_MASK_3; + case Mouse::Middle: return buttons & XCB_BUTTON_MASK_2; case Mouse::XButton1: return false; // not supported by X case Mouse::XButton2: return false; // not supported by X default: return false; } - - return false; } @@ -216,21 +270,32 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button) Vector2i InputImpl::getMousePosition() { // Open a connection with the X server - Display* display = OpenDisplay(); + xcb_connection_t* connection = OpenConnection(); - // we don't care about these but they are required - ::Window root, child; - int x, y; - unsigned int buttons; + ScopedXcbPtr<xcb_generic_error_t> error(NULL); - int gx = 0; - int gy = 0; - XQueryPointer(display, DefaultRootWindow(display), &root, &child, &gx, &gy, &x, &y, &buttons); + ScopedXcbPtr<xcb_query_pointer_reply_t> pointer( + xcb_query_pointer_reply( + connection, + xcb_query_pointer( + connection, + XCBDefaultRootWindow(connection) + ), + &error + ) + ); // Close the connection with the X server - CloseDisplay(display); + CloseConnection(connection); - return Vector2i(gx, gy); + if (error) + { + err() << "Failed to query pointer" << std::endl; + + return Vector2i(0, 0); + } + + return Vector2i(pointer->root_x, pointer->root_y); } @@ -241,21 +306,32 @@ Vector2i InputImpl::getMousePosition(const Window& relativeTo) if (handle) { // Open a connection with the X server - Display* display = OpenDisplay(); + xcb_connection_t* connection = OpenConnection(); - // we don't care about these but they are required - ::Window root, child; - int gx, gy; - unsigned int buttons; + ScopedXcbPtr<xcb_generic_error_t> error(NULL); - int x = 0; - int y = 0; - XQueryPointer(display, handle, &root, &child, &gx, &gy, &x, &y, &buttons); + ScopedXcbPtr<xcb_query_pointer_reply_t> pointer( + xcb_query_pointer_reply( + connection, + xcb_query_pointer( + connection, + handle + ), + &error + ) + ); // Close the connection with the X server - CloseDisplay(display); + CloseConnection(connection); + + if (error) + { + err() << "Failed to query pointer" << std::endl; + + return Vector2i(0, 0); + } - return Vector2i(x, y); + return Vector2i(pointer->win_x, pointer->win_y); } else { @@ -268,13 +344,27 @@ Vector2i InputImpl::getMousePosition(const Window& relativeTo) void InputImpl::setMousePosition(const Vector2i& position) { // Open a connection with the X server - Display* display = OpenDisplay(); + xcb_connection_t* connection = OpenConnection(); + + ScopedXcbPtr<xcb_generic_error_t> error(xcb_request_check( + connection, + xcb_warp_pointer( + connection, + None, // Source window + XCBDefaultRootWindow(connection), // Destination window + 0, 0, // Source position + 0, 0, // Source size + position.x, position.y // Destination position + ) + )); + + if (error) + err() << "Failed to set mouse position" << std::endl; - XWarpPointer(display, None, DefaultRootWindow(display), 0, 0, 0, 0, position.x, position.y); - XFlush(display); + xcb_flush(connection); // Close the connection with the X server - CloseDisplay(display); + CloseConnection(connection); } @@ -282,17 +372,31 @@ void InputImpl::setMousePosition(const Vector2i& position) void InputImpl::setMousePosition(const Vector2i& position, const Window& relativeTo) { // Open a connection with the X server - Display* display = OpenDisplay(); + xcb_connection_t* connection = OpenConnection(); WindowHandle handle = relativeTo.getSystemHandle(); if (handle) { - XWarpPointer(display, None, handle, 0, 0, 0, 0, position.x, position.y); - XFlush(display); + ScopedXcbPtr<xcb_generic_error_t> error(xcb_request_check( + connection, + xcb_warp_pointer( + connection, + None, // Source window + handle, // Destination window + 0, 0, // Source position + 0, 0, // Source size + position.x, position.y // Destination position + ) + )); + + if (error) + err() << "Failed to set mouse position" << std::endl; + + xcb_flush(connection); } // Close the connection with the X server - CloseDisplay(display); + CloseConnection(connection); } |