Merge branch 'bugfix/altf4_new'

This commit is contained in:
Lukas Dürrenberger 2015-03-29 22:35:26 +02:00
commit b9cc6f5c0d
5 changed files with 1792 additions and 619 deletions

View File

@ -75,6 +75,8 @@ elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD)
${SRCROOT}/Unix/Display.hpp ${SRCROOT}/Unix/Display.hpp
${SRCROOT}/Unix/InputImpl.cpp ${SRCROOT}/Unix/InputImpl.cpp
${SRCROOT}/Unix/InputImpl.hpp ${SRCROOT}/Unix/InputImpl.hpp
${SRCROOT}/Unix/ScopedXcbPtr.hpp
${SRCROOT}/Unix/ScopedXcbPtr.inl
${SRCROOT}/Unix/SensorImpl.cpp ${SRCROOT}/Unix/SensorImpl.cpp
${SRCROOT}/Unix/SensorImpl.hpp ${SRCROOT}/Unix/SensorImpl.hpp
${SRCROOT}/Unix/VideoModeImpl.cpp ${SRCROOT}/Unix/VideoModeImpl.cpp
@ -197,7 +199,7 @@ if(NOT SFML_OPENGL_ES)
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR}) include_directories(${OPENGL_INCLUDE_DIR})
if(SFML_OS_LINUX OR SFML_OS_FREEBSD) if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
find_package(XCB COMPONENTS xlib_xcb icccm image randr util REQUIRED) find_package(XCB COMPONENTS xlib_xcb icccm image randr util ewmh keysyms REQUIRED)
if(NOT LIBXCB_FOUND) if(NOT LIBXCB_FOUND)
message(FATAL_ERROR "Xcb library not found") message(FATAL_ERROR "Xcb library not found")
endif() endif()

View File

@ -29,10 +29,159 @@
#include <SFML/Window/Unix/InputImpl.hpp> #include <SFML/Window/Unix/InputImpl.hpp>
#include <SFML/Window/Unix/Display.hpp> #include <SFML/Window/Unix/Display.hpp>
#include <SFML/Window/Unix/ScopedXcbPtr.hpp> #include <SFML/Window/Unix/ScopedXcbPtr.hpp>
#include <SFML/System/Err.hpp>
#include <xcb/xcb_keysyms.h>
#include <X11/Xlib-xcb.h> #include <X11/Xlib-xcb.h>
#include <X11/keysym.h> #include <X11/keysym.h>
#include <cstdlib> #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 namespace sf
{ {
@ -41,138 +190,42 @@ namespace priv
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool InputImpl::isKeyPressed(Keyboard::Key key) bool InputImpl::isKeyPressed(Keyboard::Key key)
{ {
// Get the corresponding X11 keysym if (!mapBuilt)
KeySym keysym = 0; buildMap();
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;
}
// Open a connection with the X server // Sanity checks
Display* display = OpenDisplay(); if (key < 0 || key >= sf::Keyboard::KeyCount)
xcb_connection_t* connection = XGetXCBConnection(display); return false;
// Convert to keycode // Convert to keycode
KeyCode keycode = XKeysymToKeycode(display, keysym); xcb_keycode_t keycode = keycodeMap[key];
if (keycode != 0)
{
// Get the whole keyboard state
ScopedXcbPtr<xcb_query_keymap_reply_t> keymap(xcb_query_keymap_reply(connection, xcb_query_keymap(connection), NULL));
// Close the connection with the X server ScopedXcbPtr<xcb_generic_error_t> error(NULL);
CloseDisplay(display);
// Check our keycode // Open a connection with the X server
return (keymap->keys[keycode / 8] & (1 << (keycode % 8))) != 0; xcb_connection_t* connection = OpenConnection();
}
else // 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 err() << "Failed to query keymap" << std::endl;
CloseDisplay(display);
return false; return false;
} }
// Check our keycode
return (keymap->keys[keycode / 8] & (1 << (keycode % 8))) != 0;
} }
@ -189,13 +242,32 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button)
// Open a connection with the X server // Open a connection with the X server
xcb_connection_t* connection = OpenConnection(); xcb_connection_t* connection = OpenConnection();
ScopedXcbPtr<xcb_generic_error_t> error(NULL);
// Get pointer mask // Get pointer mask
ScopedXcbPtr<xcb_query_pointer_reply_t> pointer(xcb_query_pointer_reply(connection, xcb_query_pointer(connection, XCBDefaultRootWindow(connection)), NULL)); ScopedXcbPtr<xcb_query_pointer_reply_t> pointer(
uint16_t buttons = pointer->mask; xcb_query_pointer_reply(
connection,
xcb_query_pointer(
connection,
XCBDefaultRootWindow(connection)
),
&error
)
);
// Close the connection with the X server // Close the connection with the X server
CloseConnection(connection); CloseConnection(connection);
if (error)
{
err() << "Failed to query pointer" << std::endl;
return false;
}
uint16_t buttons = pointer->mask;
switch (button) switch (button)
{ {
case Mouse::Left: return buttons & XCB_BUTTON_MASK_1; case Mouse::Left: return buttons & XCB_BUTTON_MASK_1;
@ -214,11 +286,29 @@ Vector2i InputImpl::getMousePosition()
// Open a connection with the X server // Open a connection with the X server
xcb_connection_t* connection = OpenConnection(); xcb_connection_t* connection = OpenConnection();
ScopedXcbPtr<xcb_query_pointer_reply_t> pointer(xcb_query_pointer_reply(connection, xcb_query_pointer(connection, XCBDefaultRootWindow(connection)), NULL)); ScopedXcbPtr<xcb_generic_error_t> error(NULL);
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 // Close the connection with the X server
CloseConnection(connection); CloseConnection(connection);
if (error)
{
err() << "Failed to query pointer" << std::endl;
return Vector2i(0, 0);
}
return Vector2i(pointer->root_x, pointer->root_y); return Vector2i(pointer->root_x, pointer->root_y);
} }
@ -232,11 +322,29 @@ Vector2i InputImpl::getMousePosition(const Window& relativeTo)
// Open a connection with the X server // Open a connection with the X server
xcb_connection_t* connection = OpenConnection(); xcb_connection_t* connection = OpenConnection();
ScopedXcbPtr<xcb_query_pointer_reply_t> pointer(xcb_query_pointer_reply(connection, xcb_query_pointer(connection, handle), NULL)); ScopedXcbPtr<xcb_generic_error_t> error(NULL);
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 // Close the connection with the X server
CloseConnection(connection); CloseConnection(connection);
if (error)
{
err() << "Failed to query pointer" << std::endl;
return Vector2i(0, 0);
}
return Vector2i(pointer->win_x, pointer->win_y); return Vector2i(pointer->win_x, pointer->win_y);
} }
else else
@ -252,7 +360,21 @@ void InputImpl::setMousePosition(const Vector2i& position)
// Open a connection with the X server // Open a connection with the X server
xcb_connection_t* connection = OpenConnection(); xcb_connection_t* connection = OpenConnection();
xcb_warp_pointer(connection, None, XCBDefaultRootWindow(connection), 0, 0, 0, 0, position.x, position.y); 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;
xcb_flush(connection); xcb_flush(connection);
// Close the connection with the X server // Close the connection with the X server
@ -269,7 +391,21 @@ void InputImpl::setMousePosition(const Vector2i& position, const Window& relativ
WindowHandle handle = relativeTo.getSystemHandle(); WindowHandle handle = relativeTo.getSystemHandle();
if (handle) if (handle)
{ {
xcb_warp_pointer(connection, None, handle, 0, 0, 0, 0, position.x, position.y); 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); xcb_flush(connection);
} }

View File

@ -48,64 +48,86 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
// Retrieve the default screen // Retrieve the default screen
xcb_screen_t* screen = XCBDefaultScreen(connection); xcb_screen_t* screen = XCBDefaultScreen(connection);
// Check if the XRandR extension is present ScopedXcbPtr<xcb_generic_error_t> error(NULL);
static const std::string RANDR = "RANDR";
ScopedXcbPtr<xcb_query_extension_reply_t> randr_ext(xcb_query_extension_reply( const xcb_query_extension_reply_t* randrExt = xcb_get_extension_data(connection, &xcb_randr_id);
if (!randrExt || !randrExt->present)
{
// Randr extension is not supported: we cannot get the video modes
err() << "Failed to use the RandR extension while trying to get the supported video modes" << std::endl;
// Close the connection with the X server
CloseConnection(connection);
return modes;
}
// Load RandR and check its version
ScopedXcbPtr<xcb_randr_query_version_reply_t> randrVersion(xcb_randr_query_version_reply(
connection, connection,
xcb_query_extension( xcb_randr_query_version(
connection, connection,
RANDR.size(), 1,
RANDR.c_str() 1
), ),
NULL &error
)); ));
if (randr_ext->present) if (error)
{ {
// Get the current configuration err() << "Failed to load the RandR extension while trying to get the supported video modes" << std::endl;
ScopedXcbPtr<xcb_generic_error_t> error(NULL);
ScopedXcbPtr<xcb_randr_get_screen_info_reply_t> config(xcb_randr_get_screen_info_reply( // Close the connection with the X server
CloseConnection(connection);
return modes;
}
// Get the current configuration
ScopedXcbPtr<xcb_randr_get_screen_info_reply_t> config(xcb_randr_get_screen_info_reply(
connection,
xcb_randr_get_screen_info(
connection, connection,
xcb_randr_get_screen_info( screen->root
connection, ),
screen->root &error
), ));
&error
));
if (!error) if (error)
{
// Failed to get the screen configuration
err() << "Failed to retrieve the screen configuration while trying to get the supported video modes" << std::endl;
// Close the connection with the X server
CloseConnection(connection);
return modes;
}
// Get the available screen sizes
xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config.get());
if (sizes && (config->nSizes > 0))
{
// Get the list of supported depths
xcb_depth_iterator_t iter = xcb_screen_allowed_depths_iterator(screen);
// Combine depths and sizes to fill the array of supported modes
for (; iter.rem; xcb_depth_next(&iter))
{ {
// Get the available screen sizes for (int j = 0; j < config->nSizes; ++j)
xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config.get());
if (sizes && (config->nSizes > 0))
{ {
// Get the list of supported depths // Convert to VideoMode
xcb_depth_iterator_t iter = xcb_screen_allowed_depths_iterator(screen); VideoMode mode(sizes[j].width, sizes[j].height, iter.data->depth);
// Combine depths and sizes to fill the array of supported modes
for (; iter.rem; xcb_depth_next(&iter))
{
for (int j = 0; j < config->nSizes; ++j)
{
// Convert to VideoMode
VideoMode mode(sizes[j].width, sizes[j].height, iter.data->depth);
// Add it only if it is not already in the array if (config->rotation == XCB_RANDR_ROTATION_ROTATE_90 ||
if (std::find(modes.begin(), modes.end(), mode) == modes.end()) config->rotation == XCB_RANDR_ROTATION_ROTATE_270)
modes.push_back(mode); std::swap(mode.width, mode.height);
}
} // Add it only if it is not already in the array
if (std::find(modes.begin(), modes.end(), mode) == modes.end())
modes.push_back(mode);
} }
} }
else
{
// Failed to get the screen configuration
err() << "Failed to retrieve the screen configuration while trying to get the supported video modes" << std::endl;
}
}
else
{
// XRandr extension is not supported: we cannot get the video modes
err() << "Failed to use the XRandR extension while trying to get the supported video modes" << std::endl;
} }
// Close the connection with the X server // Close the connection with the X server
@ -126,52 +148,81 @@ VideoMode VideoModeImpl::getDesktopMode()
// Retrieve the default screen // Retrieve the default screen
xcb_screen_t* screen = XCBDefaultScreen(connection); xcb_screen_t* screen = XCBDefaultScreen(connection);
// Check if the XRandR extension is present ScopedXcbPtr<xcb_generic_error_t> error(NULL);
static const std::string RANDR = "RANDR";
ScopedXcbPtr<xcb_query_extension_reply_t> randr_ext(xcb_query_extension_reply( // Check if the RandR extension is present
const xcb_query_extension_reply_t* randrExt = xcb_get_extension_data(connection, &xcb_randr_id);
if (!randrExt || !randrExt->present)
{
// Randr extension is not supported: we cannot get the video modes
err() << "Failed to use the RandR extension while trying to get the desktop video mode" << std::endl;
// Close the connection with the X server
CloseConnection(connection);
return desktopMode;
}
// Load RandR and check its version
ScopedXcbPtr<xcb_randr_query_version_reply_t> randrVersion(xcb_randr_query_version_reply(
connection, connection,
xcb_query_extension( xcb_randr_query_version(
connection, connection,
RANDR.size(), 1,
RANDR.c_str() 1
), ),
NULL &error
)); ));
if (randr_ext->present) if (error)
{ {
// Get the current configuration err() << "Failed to load the RandR extension while trying to get the desktop video mode" << std::endl;
ScopedXcbPtr<xcb_generic_error_t> error(NULL);
ScopedXcbPtr<xcb_randr_get_screen_info_reply_t> config(xcb_randr_get_screen_info_reply( // Close the connection with the X server
CloseConnection(connection);
return desktopMode;
}
// Get the current configuration
ScopedXcbPtr<xcb_randr_get_screen_info_reply_t> config(xcb_randr_get_screen_info_reply(
connection,
xcb_randr_get_screen_info(
connection, connection,
xcb_randr_get_screen_info( screen->root
connection, ),
screen->root &error
), ));
&error
));
if (!error) if (error)
{ {
// Get the current video mode // Failed to get the screen configuration
xcb_randr_mode_t currentMode = config->sizeID; err() << "Failed to retrieve the screen configuration while trying to get the desktop video mode" << std::endl;
// Get the available screen sizes // Close the connection with the X server
int nbSizes = xcb_randr_get_screen_info_sizes_length(config.get()); CloseConnection(connection);
xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config.get());
if (sizes && (nbSizes > 0)) return desktopMode;
desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, screen->root_depth); }
}
else // Get the current video mode
{ xcb_randr_mode_t currentMode = config->sizeID;
// Failed to get the screen configuration
err() << "Failed to retrieve the screen configuration while trying to get the desktop video modes" << std::endl; // Get the available screen sizes
} int nbSizes = xcb_randr_get_screen_info_sizes_length(config.get());
xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config.get());
if (sizes && (nbSizes > 0))
{
desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, screen->root_depth);
if (config->rotation == XCB_RANDR_ROTATION_ROTATE_90 ||
config->rotation == XCB_RANDR_ROTATION_ROTATE_270)
std::swap(desktopMode.width, desktopMode.height);
} }
else else
{ {
// XRandr extension is not supported: we cannot get the video modes err() << "Failed to retrieve any screen sizes while trying to get the desktop video mode" << std::endl;
err() << "Failed to use the XRandR extension while trying to get the desktop video modes" << std::endl;
} }
// Close the connection with the X server // Close the connection with the X server

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,10 @@
#include <SFML/Window/WindowImpl.hpp> #include <SFML/Window/WindowImpl.hpp>
#include <SFML/System/String.hpp> #include <SFML/System/String.hpp>
#include <X11/Xlib-xcb.h> #include <X11/Xlib-xcb.h>
#include <set> #include <xcb/xcb_ewmh.h>
#include <xcb/xcb_keysyms.h>
#include <xcb/randr.h>
#include <deque>
namespace sf namespace sf
@ -180,12 +183,42 @@ protected:
private: private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Switch to fullscreen mode /// \brief Request the WM to make the current window active
///
////////////////////////////////////////////////////////////
void grabFocus();
////////////////////////////////////////////////////////////
/// \brief Set fullscreen video mode
/// ///
/// \param Mode video mode to switch to /// \param Mode video mode to switch to
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void switchToFullscreen(const VideoMode& mode); void setVideoMode(const VideoMode& mode);
////////////////////////////////////////////////////////////
/// \brief Reset to desktop video mode
///
////////////////////////////////////////////////////////////
void resetVideoMode();
////////////////////////////////////////////////////////////
/// \brief Switch to fullscreen mode
///
////////////////////////////////////////////////////////////
void switchToFullscreen();
////////////////////////////////////////////////////////////
/// \brief Set the WM protocols we support
///
////////////////////////////////////////////////////////////
void setProtocols();
////////////////////////////////////////////////////////////
/// \brief Set Motif WM hints
///
////////////////////////////////////////////////////////////
void setMotifHints(unsigned long style);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Do some common initializations after the window has been created /// \brief Do some common initializations after the window has been created
@ -213,7 +246,18 @@ private:
/// \return True if the event was processed, false if it was discarded /// \return True if the event was processed, false if it was discarded
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool processEvent(xcb_generic_event_t *windowEvent); 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);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Convert a X11 keysym to SFML key code /// \brief Convert a X11 keysym to SFML key code
@ -228,19 +272,24 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
::Window m_window; ///< X11 structure defining our window xcb_window_t m_window; ///< xcb identifier defining our window
::Display* m_display; ///< Pointer to the display ::Display* m_display; ///< Pointer to the display
xcb_connection_t* m_connection; ///< Pointer to the xcb connection xcb_connection_t* m_connection; ///< Pointer to the xcb connection
xcb_screen_t* m_screen; ///< Screen identifier xcb_ewmh_connection_t m_ewmhConnection; ///< xcb EWMH connection
XIM m_inputMethod; ///< Input method linked to the X display xcb_screen_t* m_screen; ///< Screen identifier
XIC m_inputContext; ///< Input context used to get unicode input in our window XIM m_inputMethod; ///< Input method linked to the X display
bool m_isExternal; ///< Tell whether the window has been created externally or by SFML XIC m_inputContext; ///< Input context used to get unicode input in our window
Atom m_atomClose; ///< Atom used to identify the close event xcb_key_symbols_t* m_keySymbols; ///< Symbols used to look up keysyms
int m_oldVideoMode; ///< Video mode in use before we switch to fullscreen std::deque<xcb_generic_event_t*> m_xcbEvents; ///< Events that were received in another window's loop
Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
bool m_keyRepeat; ///< Is the KeyRepeat feature enabled? Atom m_atomWmProtocols; ///< Atom used to identify WM protocol messages
Vector2i m_previousSize; ///< Previous size of the window, to find if a ConfigureNotify event is a resize event (could be a move event only) Atom m_atomClose; ///< Atom used to identify the close event
bool m_useSizeHints; ///< Is the size of the window fixed with size hints? 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
bool m_keyRepeat; ///< Is the KeyRepeat feature enabled?
Vector2i m_previousSize; ///< Previous size of the window, to find if a ConfigureNotify event is a resize event (could be a move event only)
bool m_useSizeHints; ///< Is the size of the window fixed with size hints?
bool m_fullscreen; ///< Is window in fullscreen?
}; };
} // namespace priv } // namespace priv