From 61526628d1ea7c2ac1b610d843ca3b8c8e1b0ff5 Mon Sep 17 00:00:00 2001 From: Victor Levasseur Date: Tue, 21 Jun 2016 17:55:00 +0200 Subject: [PATCH] Fix the cursor not always grabbed again correctly after a focus gain --- src/SFML/Window/Unix/WindowImplX11.cpp | 103 +++++++++++++++---------- 1 file changed, 61 insertions(+), 42 deletions(-) diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 655c3b36..f9aa78fc 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -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) { @@ -978,32 +981,39 @@ void WindowImplX11::setMouseCursorGrabbed(bool grabbed) if (grabbed) { - sf::priv::ScopedXcbPtr error(NULL); + // Try multiple times to grab the cursor + for (unsigned int trial = 0; trial < maxTrialsCount; ++trial) + { + sf::priv::ScopedXcbPtr error(NULL); - sf::priv::ScopedXcbPtr grabPointerReply(xcb_grab_pointer_reply( - m_connection, - xcb_grab_pointer( + sf::priv::ScopedXcbPtr 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 { @@ -1739,30 +1749,39 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) // Grab cursor if (m_cursorGrabbed) { - sf::priv::ScopedXcbPtr error(NULL); - - sf::priv::ScopedXcbPtr 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)) + // Try multiple times to grab the cursor + for (unsigned int trial = 0; trial < maxTrialsCount; ++trial) { - err() << "Failed to grab mouse cursor" << std::endl; + sf::priv::ScopedXcbPtr error(NULL); - m_cursorGrabbed = false; + sf::priv::ScopedXcbPtr 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;