Fix the cursor not always grabbed again correctly after a focus gain

This commit is contained in:
Victor Levasseur 2016-06-21 17:55:00 +02:00 committed by Lukas Dürrenberger
parent 6f3273b7a6
commit 61526628d1

View File

@ -34,6 +34,7 @@
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#include <SFML/System/Mutex.hpp> #include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp> #include <SFML/System/Lock.hpp>
#include <SFML/System/Sleep.hpp>
#include <xcb/xcb_image.h> #include <xcb/xcb_image.h>
#include <xcb/randr.h> #include <xcb/randr.h>
#include <X11/Xlibint.h> #include <X11/Xlibint.h>
@ -72,6 +73,8 @@ namespace
XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW |
XCB_EVENT_MASK_VISIBILITY_CHANGE; XCB_EVENT_MASK_VISIBILITY_CHANGE;
static const unsigned int maxTrialsCount = 5;
// Filter the events received by windows (only allow those matching a specific window) // Filter the events received by windows (only allow those matching a specific window)
Bool checkEvent(::Display*, XEvent* event, XPointer userData) Bool checkEvent(::Display*, XEvent* event, XPointer userData)
{ {
@ -978,32 +981,39 @@ void WindowImplX11::setMouseCursorGrabbed(bool grabbed)
if (grabbed) if (grabbed)
{ {
sf::priv::ScopedXcbPtr<xcb_generic_error_t> error(NULL); // Try multiple times to grab the cursor
for (unsigned int trial = 0; trial < maxTrialsCount; ++trial)
{
sf::priv::ScopedXcbPtr<xcb_generic_error_t> error(NULL);
sf::priv::ScopedXcbPtr<xcb_grab_pointer_reply_t> grabPointerReply(xcb_grab_pointer_reply( sf::priv::ScopedXcbPtr<xcb_grab_pointer_reply_t> grabPointerReply(xcb_grab_pointer_reply(
m_connection,
xcb_grab_pointer(
m_connection, m_connection,
true, xcb_grab_pointer(
m_window, m_connection,
XCB_NONE, true,
XCB_GRAB_MODE_ASYNC, m_window,
XCB_GRAB_MODE_ASYNC, XCB_NONE,
m_window, XCB_GRAB_MODE_ASYNC,
XCB_NONE, XCB_GRAB_MODE_ASYNC,
XCB_CURRENT_TIME m_window,
), XCB_NONE,
&error XCB_CURRENT_TIME
)); ),
&error
));
if (!error && grabPointerReply && (grabPointerReply->status == XCB_GRAB_STATUS_SUCCESS)) if (!error && grabPointerReply && (grabPointerReply->status == XCB_GRAB_STATUS_SUCCESS))
{ {
m_cursorGrabbed = true; m_cursorGrabbed = true;
break;
}
// The cursor grab failed, trying again after a small sleep
sf::sleep(sf::milliseconds(50));
} }
else
{ if (!m_cursorGrabbed)
err() << "Failed to grab mouse cursor" << std::endl; err() << "Failed to grab mouse cursor" << std::endl;
}
} }
else else
{ {
@ -1739,30 +1749,39 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
// Grab cursor // Grab cursor
if (m_cursorGrabbed) if (m_cursorGrabbed)
{ {
sf::priv::ScopedXcbPtr<xcb_generic_error_t> error(NULL); // Try multiple times to grab the cursor
for (unsigned int trial = 0; trial < maxTrialsCount; ++trial)
sf::priv::ScopedXcbPtr<xcb_grab_pointer_reply_t> grabPointerReply(xcb_grab_pointer_reply(
m_connection,
xcb_grab_pointer(
m_connection,
true,
m_window,
XCB_NONE,
XCB_GRAB_MODE_ASYNC,
XCB_GRAB_MODE_ASYNC,
m_window,
XCB_NONE,
XCB_CURRENT_TIME
),
&error
));
if (error || !grabPointerReply || (grabPointerReply->status != XCB_GRAB_STATUS_SUCCESS))
{ {
err() << "Failed to grab mouse cursor" << std::endl; sf::priv::ScopedXcbPtr<xcb_generic_error_t> error(NULL);
m_cursorGrabbed = false; sf::priv::ScopedXcbPtr<xcb_grab_pointer_reply_t> grabPointerReply(xcb_grab_pointer_reply(
m_connection,
xcb_grab_pointer(
m_connection,
true,
m_window,
XCB_NONE,
XCB_GRAB_MODE_ASYNC,
XCB_GRAB_MODE_ASYNC,
m_window,
XCB_NONE,
XCB_CURRENT_TIME
),
&error
));
if (!error && grabPointerReply && (grabPointerReply->status == XCB_GRAB_STATUS_SUCCESS))
{
m_cursorGrabbed = true;
break;
}
// The cursor grab failed, trying again after a small sleep
sf::sleep(sf::milliseconds(50));
} }
if (!m_cursorGrabbed)
err() << "Failed to grab mouse cursor" << std::endl;
} }
Event event; Event event;