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:
parent
623f63a48a
commit
c229877313
@ -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()
|
||||
|
@ -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
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user