Replaced a few Xlib keyboard handling functions with XCB keyboard handling functions, fixed modified key events returning sf::Keyboard::Unknown on Unix (#847), fixed sf::Keyboard::Quote and sf::Keyboard::Tilde events not functioning properly on Unix, optimized keycode lookup when using sf::Keyboard::isKeyPressed() on Unix.
This commit is contained in:
parent
5aaf9a6115
commit
7287b77c5d
@ -199,7 +199,7 @@ if(NOT SFML_OPENGL_ES)
|
||||
find_package(OpenGL REQUIRED)
|
||||
include_directories(${OPENGL_INCLUDE_DIR})
|
||||
if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
|
||||
find_package(XCB COMPONENTS xlib_xcb icccm image randr util ewmh REQUIRED)
|
||||
find_package(XCB COMPONENTS xlib_xcb icccm image randr util ewmh keysyms REQUIRED)
|
||||
if(NOT LIBXCB_FOUND)
|
||||
message(FATAL_ERROR "Xcb library not found")
|
||||
endif()
|
||||
|
@ -30,10 +30,158 @@
|
||||
#include <SFML/Window/Unix/Display.hpp>
|
||||
#include <SFML/Window/Unix/ScopedXcbPtr.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <xcb/xcb_keysyms.h>
|
||||
#include <X11/Xlib-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_key_symbols_t* keySymbols, xcb_keysym_t keysym)
|
||||
{
|
||||
// keycodes is actually a vector of keycodes
|
||||
// Since we only care about the unmodified keycode,
|
||||
// we simply return the first one
|
||||
sf::priv::ScopedXcbPtr<xcb_keycode_t> keycodes(xcb_key_symbols_get_keycode(keySymbols, keysym));
|
||||
|
||||
if (keycodes)
|
||||
return *keycodes.get();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void buildMap()
|
||||
{
|
||||
// Open a connection with the X server
|
||||
xcb_connection_t* connection = sf::priv::OpenConnection();
|
||||
|
||||
xcb_key_symbols_t* keySymbols = xcb_key_symbols_alloc(connection);
|
||||
|
||||
if (!keySymbols)
|
||||
{
|
||||
sf::err() << "Failed to allocate key symbols" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
keycodeMap[sf::Keyboard::A] = getKeycode(keySymbols, XK_A);
|
||||
keycodeMap[sf::Keyboard::B] = getKeycode(keySymbols, XK_B);
|
||||
keycodeMap[sf::Keyboard::C] = getKeycode(keySymbols, XK_C);
|
||||
keycodeMap[sf::Keyboard::D] = getKeycode(keySymbols, XK_D);
|
||||
keycodeMap[sf::Keyboard::E] = getKeycode(keySymbols, XK_E);
|
||||
keycodeMap[sf::Keyboard::F] = getKeycode(keySymbols, XK_F);
|
||||
keycodeMap[sf::Keyboard::G] = getKeycode(keySymbols, XK_G);
|
||||
keycodeMap[sf::Keyboard::H] = getKeycode(keySymbols, XK_H);
|
||||
keycodeMap[sf::Keyboard::I] = getKeycode(keySymbols, XK_I);
|
||||
keycodeMap[sf::Keyboard::J] = getKeycode(keySymbols, XK_J);
|
||||
keycodeMap[sf::Keyboard::K] = getKeycode(keySymbols, XK_K);
|
||||
keycodeMap[sf::Keyboard::L] = getKeycode(keySymbols, XK_L);
|
||||
keycodeMap[sf::Keyboard::M] = getKeycode(keySymbols, XK_M);
|
||||
keycodeMap[sf::Keyboard::N] = getKeycode(keySymbols, XK_N);
|
||||
keycodeMap[sf::Keyboard::O] = getKeycode(keySymbols, XK_O);
|
||||
keycodeMap[sf::Keyboard::P] = getKeycode(keySymbols, XK_P);
|
||||
keycodeMap[sf::Keyboard::Q] = getKeycode(keySymbols, XK_Q);
|
||||
keycodeMap[sf::Keyboard::R] = getKeycode(keySymbols, XK_R);
|
||||
keycodeMap[sf::Keyboard::S] = getKeycode(keySymbols, XK_S);
|
||||
keycodeMap[sf::Keyboard::T] = getKeycode(keySymbols, XK_T);
|
||||
keycodeMap[sf::Keyboard::U] = getKeycode(keySymbols, XK_U);
|
||||
keycodeMap[sf::Keyboard::V] = getKeycode(keySymbols, XK_V);
|
||||
keycodeMap[sf::Keyboard::W] = getKeycode(keySymbols, XK_W);
|
||||
keycodeMap[sf::Keyboard::X] = getKeycode(keySymbols, XK_X);
|
||||
keycodeMap[sf::Keyboard::Y] = getKeycode(keySymbols, XK_Y);
|
||||
keycodeMap[sf::Keyboard::Z] = getKeycode(keySymbols, XK_Z);
|
||||
keycodeMap[sf::Keyboard::Num0] = getKeycode(keySymbols, XK_0);
|
||||
keycodeMap[sf::Keyboard::Num1] = getKeycode(keySymbols, XK_1);
|
||||
keycodeMap[sf::Keyboard::Num2] = getKeycode(keySymbols, XK_2);
|
||||
keycodeMap[sf::Keyboard::Num3] = getKeycode(keySymbols, XK_3);
|
||||
keycodeMap[sf::Keyboard::Num4] = getKeycode(keySymbols, XK_4);
|
||||
keycodeMap[sf::Keyboard::Num5] = getKeycode(keySymbols, XK_5);
|
||||
keycodeMap[sf::Keyboard::Num6] = getKeycode(keySymbols, XK_6);
|
||||
keycodeMap[sf::Keyboard::Num7] = getKeycode(keySymbols, XK_7);
|
||||
keycodeMap[sf::Keyboard::Num8] = getKeycode(keySymbols, XK_8);
|
||||
keycodeMap[sf::Keyboard::Num9] = getKeycode(keySymbols, XK_9);
|
||||
keycodeMap[sf::Keyboard::Escape] = getKeycode(keySymbols, XK_Escape);
|
||||
keycodeMap[sf::Keyboard::LControl] = getKeycode(keySymbols, XK_Control_L);
|
||||
keycodeMap[sf::Keyboard::LShift] = getKeycode(keySymbols, XK_Shift_L);
|
||||
keycodeMap[sf::Keyboard::LAlt] = getKeycode(keySymbols, XK_Alt_L);
|
||||
keycodeMap[sf::Keyboard::LSystem] = getKeycode(keySymbols, XK_Super_L);
|
||||
keycodeMap[sf::Keyboard::RControl] = getKeycode(keySymbols, XK_Control_R);
|
||||
keycodeMap[sf::Keyboard::RShift] = getKeycode(keySymbols, XK_Shift_R);
|
||||
keycodeMap[sf::Keyboard::RAlt] = getKeycode(keySymbols, XK_Alt_R);
|
||||
keycodeMap[sf::Keyboard::RSystem] = getKeycode(keySymbols, XK_Super_R);
|
||||
keycodeMap[sf::Keyboard::Menu] = getKeycode(keySymbols, XK_Menu);
|
||||
keycodeMap[sf::Keyboard::LBracket] = getKeycode(keySymbols, XK_bracketleft);
|
||||
keycodeMap[sf::Keyboard::RBracket] = getKeycode(keySymbols, XK_bracketright);
|
||||
keycodeMap[sf::Keyboard::SemiColon] = getKeycode(keySymbols, XK_semicolon);
|
||||
keycodeMap[sf::Keyboard::Comma] = getKeycode(keySymbols, XK_comma);
|
||||
keycodeMap[sf::Keyboard::Period] = getKeycode(keySymbols, XK_period);
|
||||
keycodeMap[sf::Keyboard::Quote] = getKeycode(keySymbols, XK_apostrophe);
|
||||
keycodeMap[sf::Keyboard::Slash] = getKeycode(keySymbols, XK_slash);
|
||||
keycodeMap[sf::Keyboard::BackSlash] = getKeycode(keySymbols, XK_backslash);
|
||||
keycodeMap[sf::Keyboard::Tilde] = getKeycode(keySymbols, XK_grave);
|
||||
keycodeMap[sf::Keyboard::Equal] = getKeycode(keySymbols, XK_equal);
|
||||
keycodeMap[sf::Keyboard::Dash] = getKeycode(keySymbols, XK_minus);
|
||||
keycodeMap[sf::Keyboard::Space] = getKeycode(keySymbols, XK_space);
|
||||
keycodeMap[sf::Keyboard::Return] = getKeycode(keySymbols, XK_Return);
|
||||
keycodeMap[sf::Keyboard::BackSpace] = getKeycode(keySymbols, XK_BackSpace);
|
||||
keycodeMap[sf::Keyboard::Tab] = getKeycode(keySymbols, XK_Tab);
|
||||
keycodeMap[sf::Keyboard::PageUp] = getKeycode(keySymbols, XK_Prior);
|
||||
keycodeMap[sf::Keyboard::PageDown] = getKeycode(keySymbols, XK_Next);
|
||||
keycodeMap[sf::Keyboard::End] = getKeycode(keySymbols, XK_End);
|
||||
keycodeMap[sf::Keyboard::Home] = getKeycode(keySymbols, XK_Home);
|
||||
keycodeMap[sf::Keyboard::Insert] = getKeycode(keySymbols, XK_Insert);
|
||||
keycodeMap[sf::Keyboard::Delete] = getKeycode(keySymbols, XK_Delete);
|
||||
keycodeMap[sf::Keyboard::Add] = getKeycode(keySymbols, XK_KP_Add);
|
||||
keycodeMap[sf::Keyboard::Subtract] = getKeycode(keySymbols, XK_KP_Subtract);
|
||||
keycodeMap[sf::Keyboard::Multiply] = getKeycode(keySymbols, XK_KP_Multiply);
|
||||
keycodeMap[sf::Keyboard::Divide] = getKeycode(keySymbols, XK_KP_Divide);
|
||||
keycodeMap[sf::Keyboard::Left] = getKeycode(keySymbols, XK_Left);
|
||||
keycodeMap[sf::Keyboard::Right] = getKeycode(keySymbols, XK_Right);
|
||||
keycodeMap[sf::Keyboard::Up] = getKeycode(keySymbols, XK_Up);
|
||||
keycodeMap[sf::Keyboard::Down] = getKeycode(keySymbols, XK_Down);
|
||||
keycodeMap[sf::Keyboard::Numpad0] = getKeycode(keySymbols, XK_KP_0);
|
||||
keycodeMap[sf::Keyboard::Numpad1] = getKeycode(keySymbols, XK_KP_1);
|
||||
keycodeMap[sf::Keyboard::Numpad2] = getKeycode(keySymbols, XK_KP_2);
|
||||
keycodeMap[sf::Keyboard::Numpad3] = getKeycode(keySymbols, XK_KP_3);
|
||||
keycodeMap[sf::Keyboard::Numpad4] = getKeycode(keySymbols, XK_KP_4);
|
||||
keycodeMap[sf::Keyboard::Numpad5] = getKeycode(keySymbols, XK_KP_5);
|
||||
keycodeMap[sf::Keyboard::Numpad6] = getKeycode(keySymbols, XK_KP_6);
|
||||
keycodeMap[sf::Keyboard::Numpad7] = getKeycode(keySymbols, XK_KP_7);
|
||||
keycodeMap[sf::Keyboard::Numpad8] = getKeycode(keySymbols, XK_KP_8);
|
||||
keycodeMap[sf::Keyboard::Numpad9] = getKeycode(keySymbols, XK_KP_9);
|
||||
keycodeMap[sf::Keyboard::F1] = getKeycode(keySymbols, XK_F1);
|
||||
keycodeMap[sf::Keyboard::F2] = getKeycode(keySymbols, XK_F2);
|
||||
keycodeMap[sf::Keyboard::F3] = getKeycode(keySymbols, XK_F3);
|
||||
keycodeMap[sf::Keyboard::F4] = getKeycode(keySymbols, XK_F4);
|
||||
keycodeMap[sf::Keyboard::F5] = getKeycode(keySymbols, XK_F5);
|
||||
keycodeMap[sf::Keyboard::F6] = getKeycode(keySymbols, XK_F6);
|
||||
keycodeMap[sf::Keyboard::F7] = getKeycode(keySymbols, XK_F7);
|
||||
keycodeMap[sf::Keyboard::F8] = getKeycode(keySymbols, XK_F8);
|
||||
keycodeMap[sf::Keyboard::F9] = getKeycode(keySymbols, XK_F9);
|
||||
keycodeMap[sf::Keyboard::F10] = getKeycode(keySymbols, XK_F10);
|
||||
keycodeMap[sf::Keyboard::F11] = getKeycode(keySymbols, XK_F11);
|
||||
keycodeMap[sf::Keyboard::F12] = getKeycode(keySymbols, XK_F12);
|
||||
keycodeMap[sf::Keyboard::F13] = getKeycode(keySymbols, XK_F13);
|
||||
keycodeMap[sf::Keyboard::F14] = getKeycode(keySymbols, XK_F14);
|
||||
keycodeMap[sf::Keyboard::F15] = getKeycode(keySymbols, XK_F15);
|
||||
keycodeMap[sf::Keyboard::Pause] = getKeycode(keySymbols, XK_Pause);
|
||||
|
||||
xcb_key_symbols_free(keySymbols);
|
||||
|
||||
// Close the connection with the X server
|
||||
sf::priv::CloseConnection(connection);
|
||||
|
||||
mapBuilt = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
@ -42,153 +190,42 @@ 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();
|
||||
xcb_connection_t* connection = XGetXCBConnection(display);
|
||||
// Sanity checks
|
||||
if (key < 0 || key >= sf::Keyboard::KeyCount)
|
||||
return false;
|
||||
|
||||
// Convert to keycode
|
||||
KeyCode keycode = XKeysymToKeycode(display, keysym);
|
||||
if (keycode != 0)
|
||||
xcb_keycode_t keycode = keycodeMap[key];
|
||||
|
||||
ScopedXcbPtr<xcb_generic_error_t> error(NULL);
|
||||
|
||||
// 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)
|
||||
{
|
||||
ScopedXcbPtr<xcb_generic_error_t> error(NULL);
|
||||
|
||||
// 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
|
||||
CloseDisplay(display);
|
||||
|
||||
if (error)
|
||||
{
|
||||
err() << "Failed to query keymap" << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check our keycode
|
||||
return (keymap->keys[keycode / 8] & (1 << (keycode % 8))) != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -308,6 +308,7 @@ WindowImplX11::WindowImplX11(WindowHandle handle) :
|
||||
m_window (0),
|
||||
m_inputMethod (NULL),
|
||||
m_inputContext (NULL),
|
||||
m_keySymbols (NULL),
|
||||
m_isExternal (true),
|
||||
m_atomWmProtocols(0),
|
||||
m_atomClose (0),
|
||||
@ -379,6 +380,7 @@ WindowImplX11::WindowImplX11(VideoMode mode, const String& title, unsigned long
|
||||
m_window (0),
|
||||
m_inputMethod (NULL),
|
||||
m_inputContext (NULL),
|
||||
m_keySymbols (NULL),
|
||||
m_isExternal (false),
|
||||
m_atomWmProtocols(0),
|
||||
m_atomClose (0),
|
||||
@ -541,6 +543,10 @@ WindowImplX11::~WindowImplX11()
|
||||
xcb_flush(m_connection);
|
||||
}
|
||||
|
||||
// Free key symbols
|
||||
if (m_keySymbols)
|
||||
xcb_key_symbols_free(m_keySymbols);
|
||||
|
||||
// Close the input method
|
||||
if (m_inputMethod)
|
||||
XCloseIM(m_inputMethod);
|
||||
@ -1619,6 +1625,12 @@ void WindowImplX11::initialize()
|
||||
if (!m_inputContext)
|
||||
err() << "Failed to create input context for window -- TextEntered event won't be able to return unicode" << std::endl;
|
||||
|
||||
// Allocate our key symbols
|
||||
m_keySymbols = xcb_key_symbols_alloc(m_connection);
|
||||
|
||||
if (!m_keySymbols)
|
||||
err() << "Failed to allocate key symbols" << std::endl;
|
||||
|
||||
// Show the window
|
||||
setVisible(true);
|
||||
|
||||
@ -1857,20 +1869,8 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
||||
xcb_key_press_event_t* e = reinterpret_cast<xcb_key_press_event_t*>(windowEvent);
|
||||
|
||||
// Get the keysym of the key that has been pressed
|
||||
static XComposeStatus keyboard;
|
||||
char buffer[32];
|
||||
KeySym symbol;
|
||||
|
||||
// There is no xcb equivalent of XLookupString, so the xcb event
|
||||
// has to be converted to an XEvent
|
||||
XEvent fake_event;
|
||||
fake_event.type = KeyPress;
|
||||
fake_event.xany.display = m_display;
|
||||
fake_event.xany.window = e->event;
|
||||
fake_event.xkey.state = e->state;
|
||||
fake_event.xkey.keycode = e->detail;
|
||||
|
||||
XLookupString(&fake_event.xkey, buffer, sizeof(buffer), &symbol, &keyboard);
|
||||
// We don't pass e->state as the last parameter because we want the unmodified keysym
|
||||
xcb_keysym_t symbol = xcb_key_press_lookup_keysym(m_keySymbols, e, 0);
|
||||
|
||||
// Fill the event parameters
|
||||
// TODO: if modifiers are wrong, use XGetModifierMapping to retrieve the actual modifiers mapping
|
||||
@ -1883,8 +1883,15 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
||||
event.key.system = e->state & XCB_MOD_MASK_4;
|
||||
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(&fake_event, None))
|
||||
if (!XFilterEvent(&fakeEvent, None))
|
||||
{
|
||||
#ifdef X_HAVE_UTF8_STRING
|
||||
if (m_inputContext)
|
||||
@ -1894,7 +1901,7 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
||||
|
||||
int length = Xutf8LookupString(
|
||||
m_inputContext,
|
||||
&fake_event.xkey,
|
||||
&fakeEvent.xkey,
|
||||
reinterpret_cast<char*>(keyBuffer),
|
||||
sizeof(keyBuffer),
|
||||
NULL,
|
||||
@ -1919,7 +1926,7 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
||||
{
|
||||
static XComposeStatus status;
|
||||
char keyBuffer[16];
|
||||
if (XLookupString(&fake_event.xkey, keyBuffer, sizeof(keyBuffer), NULL, &status))
|
||||
if (XLookupString(&fakeEvent.xkey, keyBuffer, sizeof(keyBuffer), NULL, &status))
|
||||
{
|
||||
Event textEvent;
|
||||
textEvent.type = Event::TextEntered;
|
||||
@ -1941,16 +1948,8 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
||||
xcb_key_release_event_t* e = reinterpret_cast<xcb_key_release_event_t*>(windowEvent);
|
||||
|
||||
// Get the keysym of the key that has been pressed
|
||||
char buffer[32];
|
||||
KeySym symbol;
|
||||
|
||||
// There is no xcb equivalent of XLookupString, so the xcb event
|
||||
// has to be converted to an XEvent
|
||||
XKeyEvent fake_event;
|
||||
fake_event.display = m_display;
|
||||
fake_event.state = e->state;
|
||||
fake_event.keycode = e->detail;
|
||||
XLookupString(&fake_event, buffer, 32, &symbol, NULL);
|
||||
// We don't pass e->state as the last parameter because we want the unmodified keysym
|
||||
xcb_keysym_t symbol = xcb_key_release_lookup_keysym(m_keySymbols, e, 0);
|
||||
|
||||
// Fill the event parameters
|
||||
Event event;
|
||||
@ -2253,9 +2252,9 @@ Keyboard::Key WindowImplX11::keysymToSF(xcb_keysym_t symbol)
|
||||
case XK_bracketright: return Keyboard::RBracket;
|
||||
case XK_comma: return Keyboard::Comma;
|
||||
case XK_period: return Keyboard::Period;
|
||||
case XK_dead_acute: return Keyboard::Quote;
|
||||
case XK_apostrophe: return Keyboard::Quote;
|
||||
case XK_backslash: return Keyboard::BackSlash;
|
||||
case XK_dead_grave: return Keyboard::Tilde;
|
||||
case XK_grave: return Keyboard::Tilde;
|
||||
case XK_space: return Keyboard::Space;
|
||||
case XK_Return: return Keyboard::Return;
|
||||
case XK_KP_Enter: return Keyboard::Return;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <SFML/System/String.hpp>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <xcb/xcb_ewmh.h>
|
||||
#include <xcb/xcb_keysyms.h>
|
||||
#include <xcb/randr.h>
|
||||
#include <deque>
|
||||
|
||||
@ -278,6 +279,7 @@ 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
|
||||
xcb_key_symbols_t* m_keySymbols; ///< Symbols used to look up keysyms
|
||||
std::deque<xcb_generic_event_t*> 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
|
||||
Atom m_atomWmProtocols; ///< Atom used to identify WM protocol messages
|
||||
|
Loading…
Reference in New Issue
Block a user