Fixed numerous bugs/undefined behavior in the XCB implementation, added a lot more XCB error handling and reporting, make use of xcb-ewmh to handle EWMH for us, refactored some code out of the Window constructor into their own methods, fixed fullscreen state transition not working on window managers that create temporary parent windows when the window is being mapped, removed automatic fullscreen pointer grabbing since that is the subject of #614 and might not be desired in some situations.

This commit is contained in:
binary1248 2015-03-25 11:29:51 +01:00 committed by Lukas Dürrenberger
parent 623f63a48a
commit c229877313
4 changed files with 830 additions and 546 deletions

View File

@ -197,7 +197,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 REQUIRED)
find_package(XCB COMPONENTS xlib_xcb icccm image randr util ewmh REQUIRED)
if(NOT LIBXCB_FOUND)
message(FATAL_ERROR "Xcb library not found")
endif()

View File

@ -29,6 +29,7 @@
#include <SFML/Window/Unix/InputImpl.hpp>
#include <SFML/Window/Unix/Display.hpp>
#include <SFML/Window/Unix/ScopedXcbPtr.hpp>
#include <SFML/System/Err.hpp>
#include <X11/Xlib-xcb.h>
#include <X11/keysym.h>
#include <cstdlib>
@ -157,12 +158,27 @@ bool InputImpl::isKeyPressed(Keyboard::Key key)
KeyCode keycode = XKeysymToKeycode(display, keysym);
if (keycode != 0)
{
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), NULL));
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;
}
@ -189,13 +205,32 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button)
// Open a connection with the X server
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)), NULL));
uint16_t buttons = pointer->mask;
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
CloseConnection(connection);
if (error)
{
err() << "Failed to query pointer" << std::endl;
return false;
}
uint16_t buttons = pointer->mask;
switch (button)
{
case Mouse::Left: return buttons & XCB_BUTTON_MASK_1;
@ -214,11 +249,29 @@ Vector2i InputImpl::getMousePosition()
// Open a connection with the X server
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
CloseConnection(connection);
if (error)
{
err() << "Failed to query pointer" << std::endl;
return Vector2i(0, 0);
}
return Vector2i(pointer->root_x, pointer->root_y);
}
@ -232,11 +285,29 @@ Vector2i InputImpl::getMousePosition(const Window& relativeTo)
// Open a connection with the X server
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
CloseConnection(connection);
if (error)
{
err() << "Failed to query pointer" << std::endl;
return Vector2i(0, 0);
}
return Vector2i(pointer->win_x, pointer->win_y);
}
else
@ -252,7 +323,21 @@ void InputImpl::setMousePosition(const Vector2i& position)
// Open a connection with the X server
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);
// Close the connection with the X server
@ -269,7 +354,21 @@ void InputImpl::setMousePosition(const Vector2i& position, const Window& relativ
WindowHandle handle = relativeTo.getSystemHandle();
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);
}

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,7 @@
#include <SFML/Window/WindowImpl.hpp>
#include <SFML/System/String.hpp>
#include <X11/Xlib-xcb.h>
#include <xcb/xcb_ewmh.h>
#include <set>
@ -179,6 +180,12 @@ protected:
private:
////////////////////////////////////////////////////////////
/// \brief Request the WM to make the current window active
///
////////////////////////////////////////////////////////////
void grabFocus();
////////////////////////////////////////////////////////////
/// \brief Set fullscreen video mode
///
@ -200,12 +207,16 @@ private:
void switchToFullscreen();
////////////////////////////////////////////////////////////
/// \brief Grab or ungrab mouse pointer.
///
/// \param grabbed True to grab, false to ungrab.
/// \brief Set the WM protocols we support
///
////////////////////////////////////////////////////////////
void setPointerGrabbed(bool grabbed);
void setProtocols();
////////////////////////////////////////////////////////////
/// \brief Set Motif WM hints
///
////////////////////////////////////////////////////////////
void setMotifHints(unsigned long style);
////////////////////////////////////////////////////////////
/// \brief Do some common initializations after the window has been created
@ -248,22 +259,22 @@ private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
::Window m_window; ///< X11 structure defining our window
::Display* m_display; ///< Pointer to the display
xcb_connection_t* m_connection; ///< Pointer to the xcb connection
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
bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
Atom m_atomWmProtocols; ///< Atom used to identify WM protocol messages
Atom m_atomClose; ///< Atom used to identify the close event
Atom m_atomPing; ///< Atom used to identify the ping event
int 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?
::Window m_window; ///< X11 structure defining our window
::Display* m_display; ///< Pointer to the display
xcb_connection_t* m_connection; ///< Pointer to the xcb connection
xcb_ewmh_connection_t m_ewmhConnection; ///< xcb EWMH connection
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
bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
Atom m_atomWmProtocols; ///< Atom used to identify WM protocol messages
Atom m_atomClose; ///< Atom used to identify the close event
int 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