Skip to content
This repository has been archived by the owner on Dec 17, 2019. It is now read-only.

Commit

Permalink
Fix the cursor not always grabbed again correctly after a focus gain
Browse files Browse the repository at this point in the history
  • Loading branch information
victorlevasseur authored and eXpl0it3r committed Jul 17, 2016
1 parent 6f3273b commit 6152662
Showing 1 changed file with 60 additions and 41 deletions.
101 changes: 60 additions & 41 deletions src/SFML/Window/Unix/WindowImplX11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <SFML/System/Err.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Sleep.hpp>
#include <xcb/xcb_image.h>
#include <xcb/randr.h>
#include <X11/Xlibint.h>
Expand Down Expand Up @@ -72,6 +73,8 @@ namespace
XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW |
XCB_EVENT_MASK_VISIBILITY_CHANGE;

static const unsigned int maxTrialsCount = 5;

// Filter the events received by windows (only allow those matching a specific window)
Bool checkEvent(::Display*, XEvent* event, XPointer userData)
{
Expand Down Expand Up @@ -978,32 +981,39 @@ void WindowImplX11::setMouseCursorGrabbed(bool 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(
m_connection,
xcb_grab_pointer(
sf::priv::ScopedXcbPtr<xcb_grab_pointer_reply_t> grabPointerReply(xcb_grab_pointer_reply(
m_connection,
true,
m_window,
XCB_NONE,
XCB_GRAB_MODE_ASYNC,
XCB_GRAB_MODE_ASYNC,
m_window,
XCB_NONE,
XCB_CURRENT_TIME
),
&error
));
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;
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));
}
else
{

if (!m_cursorGrabbed)
err() << "Failed to grab mouse cursor" << std::endl;
}
}
else
{
Expand Down Expand Up @@ -1739,30 +1749,39 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
// Grab cursor
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_generic_error_t> error(NULL);

sf::priv::ScopedXcbPtr<xcb_grab_pointer_reply_t> grabPointerReply(xcb_grab_pointer_reply(
m_connection,
xcb_grab_pointer(
sf::priv::ScopedXcbPtr<xcb_grab_pointer_reply_t> grabPointerReply(xcb_grab_pointer_reply(
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;
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;
}

m_cursorGrabbed = false;
// 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;
Expand Down

0 comments on commit 6152662

Please sign in to comment.