x11.drv: [2/2] Use internal cached cursor position for GetCursorPos.

Vitaliy Margolen wine-patch at kievinfo.com
Mon Oct 2 07:17:47 CDT 2006


ChangeLog:
winex11.drv: Use internal cached cursor position for GetCursorPos.
Query X directly only when cursor is outside process' windows.

We need to use cached cursor position in GetCursorPos() because it should
return previous position inside hook handler. And get updated right after
hook chain is finished and we sent appropriate mouse messages.

However we have a problem with synchronizing this cached cursor position
between processes. To solve that we can either share that information between
processes or query X the same we did before, if cursor is outside process'
windows.

 dlls/winex11.drv/event.c  |    4 +--
 dlls/winex11.drv/mouse.c  |   71 ++++++++++++++++++++++++++++++---------------
 dlls/winex11.drv/window.c |    2 +
 dlls/winex11.drv/x11drv.h |    1 +
 4 files changed, 52 insertions(+), 26 deletions(-)

-------------- next part --------------
b81f98baf1ba0321f413a0a0c3a5cf90b07fab8c
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index 210d816..bbd1a0c 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -87,7 +87,7 @@ static struct event_handler handlers[MAX
     { ButtonRelease,    X11DRV_ButtonRelease },
     { MotionNotify,     X11DRV_MotionNotify },
     { EnterNotify,      X11DRV_EnterNotify },
-    /* LeaveNotify */
+    { LeaveNotify,      X11DRV_LeaveNotify },
     { FocusIn,          EVENT_FocusIn },
     { FocusOut,         EVENT_FocusOut },
     { KeymapNotify,     X11DRV_KeymapNotify },
@@ -116,7 +116,7 @@ static struct event_handler handlers[MAX
     { MappingNotify,    X11DRV_MappingNotify },
 };
 
-static int nb_event_handlers = 18;  /* change this if you add handlers above */
+static int nb_event_handlers = 19;  /* change this if you add handlers above */
 
 
 /* return the name of an X event */
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 14ffcc7..470b9f1 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -70,6 +70,7 @@ static const UINT button_up_flags[NB_BUT
 };
 
 POINT cursor_pos;
+static int mouse_inside_wine;
 
 static CRITICAL_SECTION cursor_CritSection;
 static CRITICAL_SECTION_DEBUG critsect_debug =
@@ -697,17 +698,29 @@ BOOL X11DRV_SetCursorPos( INT x, INT y )
 {
     Display *display = thread_display();
 
-    TRACE( "warping to (%d,%d)\n", x, y );
+    /* Cursor position hasn't changed at all or not yet. */
+    EnterCriticalSection(&cursor_CritSection);
+    if (cursor_pos.x == x && cursor_pos.y == y)
+    {
+        LeaveCriticalSection(&cursor_CritSection);
 
-    wine_tsx11_lock();
-    XWarpPointer( display, root_window, root_window, 0, 0, 0, 0, x, y );
-    XFlush( display ); /* avoids bad mouse lag in games that do their own mouse warping */
-    wine_tsx11_unlock();
+        /* We still need to generate WM_MOUSEMOVE */
+        queue_raw_mouse_message( WM_MOUSEMOVE, NULL, x, y, 0, GetCurrentTime(), 0, 0 );
+        return TRUE;
+    }
+    LeaveCriticalSection(&cursor_CritSection);
+
+    TRACE( "warping to (%d,%d)\n", x, y );
 
     EnterCriticalSection( &cursor_CritSection );
     cursor_pos.x = x;
     cursor_pos.y = y;
     LeaveCriticalSection( &cursor_CritSection );
+
+    wine_tsx11_lock();
+    XWarpPointer( display, root_window, root_window, 0, 0, 0, 0, x, y );
+    XFlush( display ); /* avoids bad mouse lag in games that do their own mouse warping */
+    wine_tsx11_unlock();
     return TRUE;
 }
 
@@ -716,25 +729,28 @@ BOOL X11DRV_SetCursorPos( INT x, INT y )
  */
 BOOL X11DRV_GetCursorPos(LPPOINT pos)
 {
-    Display *display = thread_display();
-    Window root, child;
-    int rootX, rootY, winX, winY;
-    unsigned int xstate;
-    BOOL res;
-
-    wine_tsx11_lock();
-    res = XQueryPointer( display, root_window, &root, &child,
-                         &rootX, &rootY, &winX, &winY, &xstate );
-    wine_tsx11_unlock();
-    if (res)
+    if (!mouse_inside_wine)
     {
-        update_key_state( xstate );
-        update_button_state( xstate );
-        TRACE("pointer at (%d,%d)\n", winX, winY );
-        EnterCriticalSection( &cursor_CritSection );
-        cursor_pos.x = winX;
-        cursor_pos.y = winY;
-        LeaveCriticalSection( &cursor_CritSection );
+        Display *display = thread_display();
+        Window root, child;
+        int rootX, rootY, winX, winY;
+        unsigned int xstate;
+        Bool res;
+
+        wine_tsx11_lock();
+        res = XQueryPointer( display, root_window, &root, &child,
+                             &rootX, &rootY, &winX, &winY, &xstate );
+        wine_tsx11_unlock();
+        if (res)
+        {
+            update_key_state( xstate );
+            update_button_state( xstate );
+            TRACE("pointer at (%d,%d)\n", winX, winY );
+            EnterCriticalSection( &cursor_CritSection );
+            cursor_pos.x = winX;
+            cursor_pos.y = winY;
+            LeaveCriticalSection( &cursor_CritSection );
+        }
     }
     EnterCriticalSection( &cursor_CritSection );
     *pos = cursor_pos;
@@ -838,6 +854,7 @@ void X11DRV_EnterNotify( HWND hwnd, XEve
 
     TRACE("hwnd %p, event->detail %d\n", hwnd, event->detail);
 
+    mouse_inside_wine = TRUE;
     if (!hwnd) return;
     if (event->detail == NotifyVirtual || event->detail == NotifyNonlinearVirtual) return;
 
@@ -847,3 +864,11 @@ void X11DRV_EnterNotify( HWND hwnd, XEve
     X11DRV_send_mouse_input( hwnd, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
                              pt.x, pt.y, 0, EVENT_x11_time_to_win32_time(event->time), 0, 0 );
 }
+
+/***********************************************************************
+ *           X11DRV_LeaveNotify
+ */
+void X11DRV_LeaveNotify( HWND hwnd, XEvent *xev )
+{
+    mouse_inside_wine = FALSE;
+}
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index fe07ddf..17ecc1e 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -758,7 +758,7 @@ static Window create_whole_window( Displ
     attr.event_mask    = (ExposureMask | PointerMotionMask |
                           ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
                           KeyPressMask | KeyReleaseMask | StructureNotifyMask |
-                          FocusChangeMask | KeymapStateMask);
+                          FocusChangeMask | KeymapStateMask | LeaveWindowMask);
     mask |= CWBitGravity | CWBackingStore | CWEventMask;
 
     wine_tsx11_lock();
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index b5bec51..2e1423e 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -611,6 +611,7 @@ extern void X11DRV_ButtonPress( HWND hwn
 extern void X11DRV_ButtonRelease( HWND hwnd, XEvent *event );
 extern void X11DRV_MotionNotify( HWND hwnd, XEvent *event );
 extern void X11DRV_EnterNotify( HWND hwnd, XEvent *event );
+extern void X11DRV_LeaveNotify( HWND hwnd, XEvent *event );
 extern void X11DRV_KeyEvent( HWND hwnd, XEvent *event );
 extern void X11DRV_KeymapNotify( HWND hwnd, XEvent *event );
 extern void X11DRV_Expose( HWND hwnd, XEvent *event );



More information about the wine-patches mailing list