Some window managers temporarily grab the pointer during window transition. We need to wait a while for window manager to release its grab, otherwise XGrabPointer may fail with AlreadyGrabbed, causing cursor clipping to fail.
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/winex11.drv/mouse.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index f737a306a5..7501959369 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -378,9 +378,13 @@ static BOOL grab_clipping_window( const RECT *clip ) { static const WCHAR messageW[] = {'M','e','s','s','a','g','e',0}; struct x11drv_thread_data *data = x11drv_thread_data(); + static DWORD timeout = 5000; + static DWORD step = 100; + DWORD time = 0; Window clip_window; HWND msg_hwnd = 0; POINT pos; + INT ret;
if (GetWindowThreadProcessId( GetDesktopWindow(), NULL ) == GetCurrentThreadId()) return TRUE; /* don't clip in the desktop process */ @@ -416,13 +420,24 @@ static BOOL grab_clipping_window( const RECT *clip ) clip->right < clip_rect.right || clip->bottom < clip_rect.bottom) data->warp_serial = NextRequest( data->display );
- if (!XGrabPointer( data->display, clip_window, False, - PointerMotionMask | ButtonPressMask | ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, clip_window, None, CurrentTime )) + /* Some windows managers temporarily grab the pointer during window transition. Retry grabbing. */ + do + { + ret = XGrabPointer( data->display, clip_window, False, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, clip_window, None, CurrentTime ); + if (ret == AlreadyGrabbed || ret == GrabFrozen) + { + time += step; + Sleep(step); + } + } while ((ret == AlreadyGrabbed || ret == GrabFrozen) && time < timeout); + + if (ret == GrabSuccess) clipping_cursor = TRUE;
if (!clipping_cursor) { + ERR("Failed to grab pointer\n"); disable_xinput2(); DestroyWindow( msg_hwnd ); return FALSE;