From 0e2b4f99a9f5d97f8da0189037b7516cf1585d45 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 16 May 2011 14:33:32 +0200 Subject: [PATCH] winex11: Warp the pointer when clipping, but ignore the resulting events. --- dlls/winex11.drv/event.c | 21 +++++++++++---------- dlls/winex11.drv/mouse.c | 32 ++++++++++++++++++++++++-------- dlls/winex11.drv/x11drv.h | 1 + 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index f2e2841bd4e..419ad0f9b07 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -318,25 +318,26 @@ static enum event_merge_action merge_events( XEvent *prev, XEvent *next ) break; #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H case GenericEvent: - if (prev->xcookie.extension != xinput2_opcode) break; - if (prev->xcookie.evtype != XI_RawMotion) break; - switch (next->type) { - case MotionNotify: + struct x11drv_thread_data *thread_data = x11drv_thread_data(); + if (prev->xcookie.extension != xinput2_opcode) break; + if (prev->xcookie.evtype != XI_RawMotion) break; + if (thread_data->warp_serial) break; + switch (next->type) { - struct x11drv_thread_data *thread_data = x11drv_thread_data(); + case MotionNotify: if (next->xany.window == thread_data->clip_window && next->xmotion.time - thread_data->last_motion_notify < 1000) { TRACE( "ignoring MotionNotify for clip window\n" ); return MERGE_IGNORE; } + break; + case GenericEvent: + if (next->xcookie.extension != xinput2_opcode) break; + if (next->xcookie.evtype != XI_RawMotion) break; + return merge_raw_motion_events( prev->xcookie.data, next->xcookie.data ); } - break; - case GenericEvent: - if (next->xcookie.extension != xinput2_opcode) break; - if (next->xcookie.evtype != XI_RawMotion) break; - return merge_raw_motion_events( prev->xcookie.data, next->xcookie.data ); } break; #endif diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index b79525a85ff..188e36fe695 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -1213,15 +1213,13 @@ BOOL CDECL X11DRV_SetCursorPos( INT x, INT y ) { struct x11drv_thread_data *data = x11drv_init_thread_data(); - if (data->xi2_state == xi_enabled) return TRUE; - - TRACE( "warping to (%d,%d)\n", x, y ); - wine_tsx11_lock(); + data->warp_serial = NextRequest( data->display ); XWarpPointer( data->display, root_window, root_window, 0, 0, 0, 0, x - virtual_screen_rect.left, y - virtual_screen_rect.top ); XFlush( data->display ); /* avoids bad mouse lag in games that do their own mouse warping */ wine_tsx11_unlock(); + TRACE( "warped to %d,%d serial %lu\n", x, y, data->warp_serial ); return TRUE; } @@ -1240,9 +1238,10 @@ BOOL CDECL X11DRV_GetCursorPos(LPPOINT pos) ret = XQueryPointer( display, root_window, &root, &child, &rootX, &rootY, &winX, &winY, &xstate ); if (ret) { + POINT old = *pos; pos->x = winX + virtual_screen_rect.left; pos->y = winY + virtual_screen_rect.top; - TRACE("pointer at (%d,%d)\n", pos->x, pos->y ); + TRACE( "pointer at (%d,%d) server pos %d,%d\n", pos->x, pos->y, old.x, old.y ); } wine_tsx11_unlock(); return ret; @@ -1353,7 +1352,8 @@ void X11DRV_MotionNotify( HWND hwnd, XEvent *xev ) XMotionEvent *event = &xev->xmotion; INPUT input; - TRACE( "hwnd %p/%lx pos %d,%d is_hint %d\n", hwnd, event->window, event->x, event->y, event->is_hint ); + TRACE( "hwnd %p/%lx pos %d,%d is_hint %d serial %lu\n", + hwnd, event->window, event->x, event->y, event->is_hint, event->serial ); input.u.mi.dx = event->x; input.u.mi.dy = event->y; @@ -1366,6 +1366,7 @@ void X11DRV_MotionNotify( HWND hwnd, XEvent *xev ) { struct x11drv_thread_data *thread_data = x11drv_thread_data(); if (event->time - thread_data->last_motion_notify < 1000) return; + if (thread_data->warp_serial && (long)(event->serial - thread_data->warp_serial) < 0) return; thread_data->last_motion_notify = event->time; } @@ -1402,12 +1403,15 @@ void X11DRV_EnterNotify( HWND hwnd, XEvent *xev ) /*********************************************************************** * X11DRV_RawMotion */ -static void X11DRV_RawMotion( XIRawEvent *event ) +static void X11DRV_RawMotion( XGenericEventCookie *xev ) { + XIRawEvent *event = xev->data; const double *values = event->valuators.values; INPUT input; + struct x11drv_thread_data *thread_data = x11drv_thread_data(); if (!event->valuators.mask_len) return; + if (thread_data->xi2_state != xi_enabled) return; input.u.mi.dx = 0; input.u.mi.dy = 0; @@ -1419,6 +1423,18 @@ static void X11DRV_RawMotion( XIRawEvent *event ) if (XIMaskIsSet( event->valuators.mask, 0 )) input.u.mi.dx = *values++; if (XIMaskIsSet( event->valuators.mask, 1 )) input.u.mi.dy = *values++; + if (thread_data->warp_serial) + { + long diff = xev->serial - thread_data->warp_serial; + + if (diff >= 0) thread_data->warp_serial = 0; /* we caught up now */ + if (diff <= 0) /* <= 0 because we also want to ignore the first event after the warp request */ + { + TRACE( "pos %d,%d old serial %lu, ignoring\n", input.u.mi.dx, input.u.mi.dy, xev->serial ); + return; + } + } + TRACE( "pos %d,%d\n", input.u.mi.dx, input.u.mi.dy ); input.type = INPUT_MOUSE; @@ -1478,7 +1494,7 @@ void X11DRV_GenericEvent( HWND hwnd, XEvent *xev ) switch (event->evtype) { case XI_RawMotion: - X11DRV_RawMotion( event->data ); + X11DRV_RawMotion( event ); break; default: diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index a14fa391555..8e335afda3a 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -551,6 +551,7 @@ struct x11drv_thread_data Time last_motion_notify; /* time of last mouse motion */ XFontSet font_set; /* international text drawing font set */ Window selection_wnd; /* window used for selection interactions */ + unsigned long warp_serial; /* serial number of last pointer warp request */ Window clip_window; /* window used for cursor clipping */ HWND clip_hwnd; /* message window stored in desktop while clipping is active */ DWORD clip_reset; /* time when clipping was last reset */