x11: specify event mask for buttons when grabbing pointer (thanks, Stas!). This fixes a strange corner case (notes appended below), and should be safe to do anyhow. Fixes Bugzilla #3674. "I did more tests. It appears the bug only happens if there is another window on the screen that has "always on top" property. For me it is xawtv - it is always opened in a screen corner. Closing xawtv or removing "always on top" property from it makes the problem to go away. Plus, it doesn't appear like the buttons are not delivered at all. It appears that instead the button presses are delivered on some mouse positions, but not delivered when you move the mouse to other part of the window... So this is really weird and is likely somewhere deep in the Xorg. Maybe somehow it happens that the cursor is actually above the xawtv window, but, because my app uses grab, it is not visible there, and in that case the events are not delivered to my app? But with my patch the button events are always delivered flawlessly, it seems. Hmm, and that indeed seems to explain my problem: if the mask is set properly and my app uses grab, then, even if the mouse is above some other window, the events would still be delivered to the grabbing app, which is what actually wanted because my app uses relative mouse mode, so it doesn't know the pointer can cross some other window (my app draws the pointer itself). So my current theory is that my patch only enforces the mouse grab, which otherwise can be tricked by some other window preventing the button events delivery (but motion events are still delivered via xinput2, which makes it all look very obscure)."
diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c
index 54dffd3..d532d2b 100644
--- a/src/video/x11/SDL_x11window.c
+++ b/src/video/x11/SDL_x11window.c
@@ -1499,12 +1499,13 @@ X11_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
if (oldstyle_fullscreen || grabbed) {
/* Try to grab the mouse */
if (!data->videodata->broken_pointer_grab) {
+ const unsigned int mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask;
int attempts;
int result;
/* Try for up to 5000ms (5s) to grab. If it still fails, stop trying. */
for (attempts = 0; attempts < 100; attempts++) {
- result = X11_XGrabPointer(display, data->xwindow, True, 0, GrabModeAsync,
+ result = X11_XGrabPointer(display, data->xwindow, True, mask, GrabModeAsync,
GrabModeAsync, data->xwindow, None, CurrentTime);
if (result == GrabSuccess) {
break;