[PATCH 3/3] winex11.drv: Don't grab or warp the cursor if a button is pressed outside of focused window

Rémi Bernon rbernon at codeweavers.com
Mon Jun 10 06:43:26 CDT 2019


This could be a situation where the user has clicked on a window
title bar (eventually the current window). Grabbing the cursor then
will warp it and move the window with it.

Also, as described in the previous commit, FocusOut events with
NotifyGrab mode is not sent by all WMs, and there is also a small delay
between FocusIn with NotifyNormal mode event that is sent as soon as the
window is focused, and FocusOut with NotifyGrab mode event that is sent
when window is moved by the WM, where the cursor could still be moved by
the application.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/winex11.drv/mouse.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index f737a306a56..478adcf26a9 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -368,6 +368,31 @@ static void disable_xinput2(void)
 #endif
 }
 
+static BOOL is_safe_to_grab_or_warp_pointer(void)
+{
+    struct x11drv_thread_data *data = x11drv_thread_data();
+    Window xfocus, xroot, xparent, xchild, *xchildren = NULL;
+    int revert, root_x, root_y, win_x, win_y;
+    unsigned int nchildren, xstate;
+    BOOL ret = TRUE;
+
+    /* If we aren't clipping the mouse already and if a mouse button is
+     * pressed outside of the focused window, then it isn't safe to warp
+     * or grab the mouse as it could be moving a window.
+     */
+    XGetInputFocus( data->display, &xfocus, &revert );
+    if (!clipping_cursor &&
+        XQueryTree( data->display, xfocus, &xroot, &xparent, &xchildren, &nchildren ) &&
+        XQueryPointer( data->display, xparent, &xroot, &xchild, &root_x, &root_y, &win_x, &win_y, &xstate ) &&
+        xchild != xfocus &&
+        (xstate & (Button1Mask | Button2Mask | Button3Mask)))
+        ret = FALSE;
+
+    if (xchildren)
+        XFree(xchildren);
+
+    return ret;
+}
 
 /***********************************************************************
  *		grab_clipping_window
@@ -403,6 +428,12 @@ static BOOL grab_clipping_window( const RECT *clip )
         return TRUE;
     }
 
+    if (!is_safe_to_grab_or_warp_pointer())
+    {
+        WARN( "Button is pressed outside of focused window, refusing to clip to %s\n", wine_dbgstr_rect(clip) );
+        return FALSE;
+    }
+
     TRACE( "clipping to %s win %lx\n", wine_dbgstr_rect(clip), clip_window );
 
     if (!data->clip_hwnd) XUnmapWindow( data->display, clip_window );
@@ -1430,6 +1461,12 @@ BOOL CDECL X11DRV_SetCursorPos( INT x, INT y )
     struct x11drv_thread_data *data = x11drv_init_thread_data();
     POINT pos = virtual_screen_to_root( x, y );
 
+    if (!is_safe_to_grab_or_warp_pointer())
+    {
+        WARN( "Button is pressed outside of focused window, refusing to warp to %u, %u\n", pos.x, pos.y );
+        return FALSE;
+    }
+
     XWarpPointer( data->display, root_window, root_window, 0, 0, 0, 0, pos.x, pos.y );
     data->warp_serial = NextRequest( data->display );
     XNoOp( data->display );
-- 
2.20.1




More information about the wine-devel mailing list