SDL: x11: Check for button presses before clearing an XInput2 pointer grab

From 1f0bc4b808a5da933ce4fedee89e2d42eb862498 Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Sun, 30 Jun 2024 12:16:50 -0400
Subject: [PATCH] x11: Check for button presses before clearing an XInput2
 pointer grab

XInput2 will grab the pointer on button presses, which causes the grab attempt to fail and ultimately timeout since the pointer is already grabbed, however, ungrabbing the pointer when no buttons are pressed and the pointer is outside the window can generate enter/leave notify events, which result in further calls of the grab function. The end result is an infinite loop of grab/ungrab attempts generating enter/leave events. This causes a hang in testautomation when creating a window with the grabbed flag if the pointer is not positioned within window bounds.

Check the button state and only ungrab if a mouse button is in the pressed state.
---
 src/video/x11/SDL_x11window.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c
index d696ced794ac3..60e5a32817839 100644
--- a/src/video/x11/SDL_x11window.c
+++ b/src/video/x11/SDL_x11window.c
@@ -1856,10 +1856,11 @@ int X11_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool
         }
 
         /* If XInput2 is enabled, it will grab the pointer on button presses,
-         * which results in XGrabPointer returning AlreadyGrabbed. Clear any
-         * existing grabs before attempting the confinement grab.
+         * which results in XGrabPointer returning AlreadyGrabbed. If buttons
+         * are currently pressed, clear any existing grabs before attempting
+         * the confinement grab.
          */
-        if (data->xinput2_mouse_enabled) {
+        if (data->xinput2_mouse_enabled && SDL_GetMouseState(NULL, NULL)) {
             X11_XUngrabPointer(display, CurrentTime);
         }