[PATCH 3/3] winex11.drv: clip mouse position correctly.

Lauri Kenttä lauri.kentta at gmail.com
Mon Jan 18 17:34:16 CST 2010


When the cursor position is clipped with ClipCursor, the cursor should
move inside the clip rect and in no event leave it before the clip rect
is set to NULL.

This patch fixes cursor position clipping in X11DRV_ClipCursor,
X11DRV_GetCursorPos, X11DRV_SetCursorPos and X11DRV_send_mouse_input and
makes the X cursor warp back inside the clip rect if moved out.
---
 dlls/winex11.drv/mouse.c |   52 ++++++++++++++++++++++++++++++++++++---------
 1 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index b85c71f..17512c8 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -274,6 +274,20 @@ static void queue_raw_mouse_message( UINT message, HWND hwnd, DWORD x, DWORD y,
 
 
 /***********************************************************************
+ *           set_cursor_pos_if_changed
+ */
+static void set_cursor_pos_if_changed( POINT pt )
+{
+    wine_tsx11_lock();
+    if (pt.x != cursor_pos.x || pt.y != cursor_pos.y)
+    {
+        X11DRV_SetCursorPos( pt.x, pt.y );
+    }
+    wine_tsx11_unlock();
+}
+
+
+/***********************************************************************
  *		X11DRV_send_mouse_input
  */
 void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y,
@@ -287,6 +301,9 @@ void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y,
         {
             pt.x = (x * screen_width) >> 16;
             pt.y = (y * screen_height) >> 16;
+            wine_tsx11_lock();
+            clip_point_to_rect( &cursor_clip, &pt );
+            wine_tsx11_unlock();
         }
         else
         {
@@ -296,6 +313,7 @@ void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y,
             if (cursor_pos.x == x && cursor_pos.y == y &&
                 (flags & ~(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE)))
                 flags &= ~MOUSEEVENTF_MOVE;
+            clip_point_to_rect( &cursor_clip, &pt );
             wine_tsx11_unlock();
         }
     }
@@ -320,6 +338,7 @@ void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y,
         wine_tsx11_lock();
         pt.x = cursor_pos.x + (long)x * xMult;
         pt.y = cursor_pos.y + (long)y * yMult;
+        clip_point_to_rect( &cursor_clip, &pt );
         wine_tsx11_unlock();
     }
     else
@@ -340,10 +359,7 @@ void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y,
         }
         else
         {
-            wine_tsx11_lock();
-            clip_point_to_rect( &cursor_clip, &pt);
-            cursor_pos = pt;
-            wine_tsx11_unlock();
+            set_cursor_pos_if_changed( pt );
         }
     }
     if (flags & MOUSEEVENTF_LEFTDOWN)
@@ -988,20 +1004,20 @@ BOOL CDECL X11DRV_SetCursorPos( INT x, INT y )
 {
     Display *display = thread_init_display();
     POINT pt;
-
-    TRACE( "warping to (%d,%d)\n", x, y );
+    pt.x = x; pt.y = y;
 
     wine_tsx11_lock();
-    if (cursor_pos.x == x && cursor_pos.y == y)
+    clip_point_to_rect( &cursor_clip, &pt );
+    TRACE( "warping to (%d,%d), clipped (%d,%d)\n", x, y, pt.x, pt.y );
+
+    if (cursor_pos.x == pt.x && cursor_pos.y == pt.y)
     {
         wine_tsx11_unlock();
         /* We still need to generate WM_MOUSEMOVE */
-        queue_raw_mouse_message( WM_MOUSEMOVE, NULL, x, y, 0, GetCurrentTime(), 0, 0, FALSE );
+        queue_raw_mouse_message( WM_MOUSEMOVE, NULL, pt.x, pt.y, 0, GetCurrentTime(), 0, 0, FALSE );
         return TRUE;
     }
 
-    pt.x = x; pt.y = y;
-    clip_point_to_rect( &cursor_clip, &pt);
     /* FIXME: SetCursorPos shouldn't call hooks, but this one does! */
     XWarpPointer( display, root_window, root_window, 0, 0, 0, 0,
                   pt.x - virtual_screen_rect.left, pt.y - virtual_screen_rect.top );
@@ -1020,6 +1036,7 @@ BOOL CDECL X11DRV_GetCursorPos(LPPOINT pos)
     Window root, child;
     int rootX, rootY, winX, winY;
     unsigned int xstate;
+    POINT pt;
 
     wine_tsx11_lock();
     if ((GetTickCount() - last_time_modified > 100) &&
@@ -1029,9 +1046,14 @@ BOOL CDECL X11DRV_GetCursorPos(LPPOINT pos)
         update_button_state( xstate );
         winX += virtual_screen_rect.left;
         winY += virtual_screen_rect.top;
-        TRACE("pointer at (%d,%d)\n", winX, winY );
         cursor_pos.x = winX;
         cursor_pos.y = winY;
+
+        /* clip the new position and warp mouse inside the clip rect */
+        pt = cursor_pos;
+        clip_point_to_rect( &cursor_clip, &pt );
+        TRACE( "pointer at (%d,%d), clipped (%d,%d)\n", winX, winY, pt.x, pt.y );
+        set_cursor_pos_if_changed( pt );
     }
     *pos = cursor_pos;
     wine_tsx11_unlock();
@@ -1046,9 +1068,17 @@ BOOL CDECL X11DRV_GetCursorPos(LPPOINT pos)
  */
 BOOL CDECL X11DRV_ClipCursor( LPCRECT clip )
 {
+    POINT pt;
     if (!IntersectRect( &cursor_clip, &virtual_screen_rect, clip ))
         cursor_clip = virtual_screen_rect;
 
+    /* clip the current position to the new rect */
+    wine_tsx11_lock();
+    pt = cursor_pos;
+    clip_point_to_rect( &cursor_clip, &pt );
+    wine_tsx11_unlock();
+    set_cursor_pos_if_changed( pt );
+
     return TRUE;
 }
 
-- 
1.6.6




More information about the wine-patches mailing list