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@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 );