Alexandre Julliard : winex11: Grab the mouse in the thread that owns the foreground window if possible.

Alexandre Julliard julliard at winehq.org
Thu Apr 28 12:18:56 CDT 2011


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Apr 28 13:07:05 2011 +0200

winex11: Grab the mouse in the thread that owns the foreground window if possible.

---

 dlls/winex11.drv/mouse.c |   99 +++++++++++++++++++++++++++++-----------------
 1 files changed, 62 insertions(+), 37 deletions(-)

diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 7f45a2a..96d93e5 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -369,44 +369,18 @@ static HWND create_clipping_msg_window(void)
 }
 
 /***********************************************************************
- *             clip_cursor_notify
- *
- * Notification function called upon receiving a WM_X11DRV_CLIP_CURSOR.
- */
-LRESULT clip_cursor_notify( HWND hwnd, HWND new_clip_hwnd )
-{
-    struct x11drv_thread_data *data = x11drv_thread_data();
-
-    if (hwnd == GetDesktopWindow())  /* change the clip window stored in the desktop process */
-    {
-        static HWND clip_hwnd;
-
-        HWND prev = clip_hwnd;
-        clip_hwnd = new_clip_hwnd;
-        if (prev || new_clip_hwnd) TRACE( "clip hwnd changed from %p to %p\n", prev, new_clip_hwnd );
-        if (prev) SendNotifyMessageW( prev, WM_X11DRV_CLIP_CURSOR, 0, 0 );
-    }
-    else if (hwnd == data->clip_hwnd)  /* this is a notification that clipping has been reset */
-    {
-        data->clip_hwnd = 0;
-        disable_xinput2();
-        DestroyWindow( hwnd );
-    }
-    return 0;
-}
-
-/***********************************************************************
  *		grab_clipping_window
  *
  * Start a pointer grab on the clip window.
  */
 static BOOL grab_clipping_window( const RECT *clip )
 {
-    struct x11drv_thread_data *data = x11drv_init_thread_data();
-    Window clip_window = init_clip_window();
+    struct x11drv_thread_data *data = x11drv_thread_data();
+    Window clip_window;
     HWND msg_hwnd = 0;
 
-    if (!clip_window) return TRUE;
+    if (!data) return FALSE;
+    if (!(clip_window = init_clip_window())) return TRUE;
 
     /* create a clip message window unless we are already clipping */
     if (!data->clip_hwnd)
@@ -475,6 +449,42 @@ void ungrab_clipping_window(void)
 }
 
 /***********************************************************************
+ *             clip_cursor_notify
+ *
+ * Notification function called upon receiving a WM_X11DRV_CLIP_CURSOR.
+ */
+LRESULT clip_cursor_notify( HWND hwnd, HWND new_clip_hwnd )
+{
+    struct x11drv_thread_data *data = x11drv_thread_data();
+
+    if (hwnd == GetDesktopWindow())  /* change the clip window stored in the desktop process */
+    {
+        static HWND clip_hwnd;
+
+        HWND prev = clip_hwnd;
+        clip_hwnd = new_clip_hwnd;
+        if (prev || new_clip_hwnd) TRACE( "clip hwnd changed from %p to %p\n", prev, new_clip_hwnd );
+        if (prev) SendNotifyMessageW( prev, WM_X11DRV_CLIP_CURSOR, 0, 0 );
+    }
+    else if (hwnd == data->clip_hwnd)  /* this is a notification that clipping has been reset */
+    {
+        data->clip_hwnd = 0;
+        disable_xinput2();
+        DestroyWindow( hwnd );
+    }
+    else if (hwnd == GetForegroundWindow())  /* request to clip */
+    {
+        RECT clip;
+
+        GetClipCursor( &clip );
+        if (clip.left > virtual_screen_rect.left || clip.right < virtual_screen_rect.right ||
+            clip.top > virtual_screen_rect.top   || clip.bottom < virtual_screen_rect.bottom)
+            return grab_clipping_window( &clip );
+    }
+    return 0;
+}
+
+/***********************************************************************
  *		send_mouse_input
  *
  * Update the various window states on a mouse event.
@@ -1191,16 +1201,31 @@ BOOL CDECL X11DRV_GetCursorPos(LPPOINT pos)
  */
 BOOL CDECL X11DRV_ClipCursor( LPCRECT clip )
 {
+    if (!clip)
+    {
+        ungrab_clipping_window();
+        return TRUE;
+    }
+
+    if (X11DRV_get_win_data( GetDesktopWindow() )) return TRUE;  /* don't clip in the desktop process */
+
     /* we are clipping if the clip rectangle is smaller than the screen */
-    if (clip && (clip->left > virtual_screen_rect.left ||
-                 clip->right < virtual_screen_rect.right ||
-                 clip->top > virtual_screen_rect.top ||
-                 clip->bottom < virtual_screen_rect.bottom))
+    if (grab_pointer && (clip->left > virtual_screen_rect.left ||
+                         clip->right < virtual_screen_rect.right ||
+                         clip->top > virtual_screen_rect.top ||
+                         clip->bottom < virtual_screen_rect.bottom))
     {
-        if (GetWindowThreadProcessId( GetDesktopWindow(), NULL ) == GetCurrentThreadId())
-            return TRUE;  /* don't clip in the desktop process */
+        DWORD tid, pid;
+        HWND foreground = GetForegroundWindow();
 
-        if (grab_pointer && grab_clipping_window( clip )) return TRUE;
+        /* forward request to the foreground window if it's in a different thread */
+        tid = GetWindowThreadProcessId( foreground, &pid );
+        if (tid && tid != GetCurrentThreadId() && pid == GetCurrentProcessId())
+        {
+            TRACE( "forwarding clip request to %p\n", foreground );
+            if (SendMessageW( foreground, WM_X11DRV_CLIP_CURSOR, 0, 0 )) return TRUE;
+        }
+        else if (grab_clipping_window( clip )) return TRUE;
     }
 
     ungrab_clipping_window();




More information about the wine-cvs mailing list