Преглед изворни кода

x11: Ignore slave button presses on non-focused windows

When a window has the pointer grabbed, the X server will grab all master device events, and XInput2 will continue to deliver slave events to the window immediately under the pointer, regardless of grab status. Only send slave pointer events to the focused window, and fall back to the core X events to catch button presses missed when the pointer is over another window.

(cherry picked from commit 0fc9db9b82c318b44562778cd4709e9638a57087)
Frank Praznik пре 1 дан
родитељ
комит
e057712565
3 измењених фајлова са 14 додато и 5 уклоњено
  1. 4 4
      src/video/x11/SDL_x11events.c
  2. 1 0
      src/video/x11/SDL_x11video.h
  3. 9 1
      src/video/x11/SDL_x11xinput2.c

+ 4 - 4
src/video/x11/SDL_x11events.c

@@ -1862,8 +1862,8 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
 
     case ButtonPress:
     {
-        if (data->xinput2_mouse_enabled) {
-            // This input is being handled by XInput2
+        if (data->xinput2_mouse_enabled && xevent->xbutton.serial == videodata->xinput_last_button_serial) {
+            // This input event was handled by XInput2.
             break;
         }
 
@@ -1873,8 +1873,8 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
 
     case ButtonRelease:
     {
-        if (data->xinput2_mouse_enabled) {
-            // This input is being handled by XInput2
+        if (data->xinput2_mouse_enabled && xevent->xbutton.serial == videodata->xinput_last_button_serial) {
+            // This input event was handled by XInput2.
             break;
         }
 

+ 1 - 0
src/video/x11/SDL_x11video.h

@@ -138,6 +138,7 @@ struct SDL_VideoData
     Uint32 global_mouse_buttons;
 
     SDL_XInput2DeviceInfo *mouse_device_info;
+    unsigned long xinput_last_button_serial;
     int xinput_master_pointer_device;
     bool xinput_hierarchy_changed;
 

+ 9 - 1
src/video/x11/SDL_x11xinput2.c

@@ -607,8 +607,16 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
             SDL_WindowData *windowdata = X11_FindWindow(videodata, xev->event);
             int x_ticks = 0, y_ticks = 0;
 
-            // Slave pointer devices don't have button remapping applied automatically, so do it manually.
+            // Store the button serial to filter out redundant core button events.
+            videodata->xinput_last_button_serial = xev->serial;
+
             if (xev->deviceid != videodata->xinput_master_pointer_device) {
+                // Ignore slave button events on non-focused windows, or focus can be incorrectly set while a grab is active.
+                if (SDL_GetMouseFocus() != windowdata->window) {
+                    break;
+                }
+
+                // Slave pointer devices don't have button remapping applied automatically, so do it manually.
                 if (button <= xinput2_pointer_button_map_size) {
                     button = xinput2_pointer_button_map[button - 1];
                 }