Alexandre Julliard : winex11: Warp the pointer when clipping, but ignore the resulting events.

Alexandre Julliard julliard at winehq.org
Mon May 16 11:36:49 CDT 2011


Module: wine
Branch: master
Commit: 0e2b4f99a9f5d97f8da0189037b7516cf1585d45
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=0e2b4f99a9f5d97f8da0189037b7516cf1585d45

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon May 16 14:33:32 2011 +0200

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 f2e2841..419ad0f 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 b79525a..188e36f 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 a14fa39..8e335af 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 */




More information about the wine-cvs mailing list