[5/5] winex11.drv: Use a dedicated window for mouse capture.

Vincent Povirk madewokherd at gmail.com
Wed Apr 16 14:13:02 CDT 2014


-------------- next part --------------
From 5762b43eca7ade336dd9ca02f88211999e72542d Mon Sep 17 00:00:00 2001
From: Vincent Povirk <vincent at codeweavers.com>
Date: Thu, 6 Mar 2014 15:30:46 -0600
Subject: [PATCH 05/11] winex11.drv: Use a dedicated window for mouse capture.

---
 dlls/winex11.drv/mouse.c  | 63 ++++++++++++++++++++++++++++++++++++++++++-----
 dlls/winex11.drv/window.c | 35 +++-----------------------
 dlls/winex11.drv/x11drv.h |  1 +
 3 files changed, 61 insertions(+), 38 deletions(-)

diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index f1e58fe..0ae0758 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -535,18 +535,25 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU
     if (!hwnd)
     {
         struct x11drv_thread_data *thread_data = x11drv_thread_data();
-        HWND clip_hwnd = thread_data->clip_hwnd;
+        HWND cursor_hwnd;
 
-        if (!clip_hwnd) return;
-        if (thread_data->clip_window != window) return;
-        if (InterlockedExchangePointer( (void **)&cursor_window, clip_hwnd ) != clip_hwnd ||
+        if (thread_data->clip_window == window)
+        {
+            if (!thread_data->clip_hwnd) return;
+            cursor_hwnd = thread_data->clip_hwnd;
+            input->u.mi.dx += clip_rect.left;
+            input->u.mi.dy += clip_rect.top;
+        }
+        else if (thread_data->grab_window == window)
+            cursor_hwnd = GetCapture();
+        else
+            return;
+        if (InterlockedExchangePointer( (void **)&cursor_window, cursor_hwnd ) != cursor_hwnd ||
             input->u.mi.time - last_cursor_change > 100)
         {
             sync_window_cursor( window );
             last_cursor_change = input->u.mi.time;
         }
-        input->u.mi.dx += clip_rect.left;
-        input->u.mi.dy += clip_rect.top;
         __wine_send_input( hwnd, input );
         return;
     }
@@ -1421,6 +1428,50 @@ BOOL CDECL X11DRV_ClipCursor( LPCRECT clip )
     return TRUE;
 }
 
+
+/***********************************************************************
+ *		SetCapture  (X11DRV.@)
+ */
+void CDECL X11DRV_SetCapture( HWND hwnd, UINT flags )
+{
+    struct x11drv_thread_data *thread_data = x11drv_thread_data();
+
+    if (!thread_data) return;
+    if (!(flags & (GUI_INMOVESIZE | GUI_INMENUMODE))) return;
+
+    if (hwnd)
+    {
+        if (!thread_data->capture_window)
+        {
+            XSetWindowAttributes attr;
+
+            attr.override_redirect = TRUE;
+            attr.event_mask = StructureNotifyMask | FocusChangeMask;
+            thread_data->capture_window = XCreateWindow( thread_data->display,
+                root_window, 0, 0, 1, 1, 0, 0, InputOnly, default_visual.visual,
+                CWOverrideRedirect | CWEventMask, &attr );
+
+            if (!thread_data->capture_window) return;
+        }
+
+        XFlush( gdi_display );
+        XMapWindow( thread_data->display, thread_data->capture_window );
+        XGrabPointer( thread_data->display, thread_data->capture_window, False,
+                      PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
+                      GrabModeAsync, GrabModeAsync, None, None, CurrentTime );
+        sync_window_cursor( thread_data->capture_window );
+        InterlockedExchangePointer( (void **)&cursor_window, hwnd );
+        thread_data->grab_window = thread_data->capture_window;
+    }
+    else if (thread_data->capture_window)  /* release capture */
+    {
+        XFlush( gdi_display );
+        XUnmapWindow( thread_data->display, thread_data->capture_window );
+        XFlush( thread_data->display );
+        thread_data->grab_window = None;
+    }
+}
+
 /***********************************************************************
  *           move_resize_window
  */
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index a9caa0d..c150cae 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -2060,37 +2060,6 @@ BOOL CDECL X11DRV_ScrollDC( HDC hdc, INT dx, INT dy, HRGN update )
 }
 
 
-/***********************************************************************
- *		SetCapture  (X11DRV.@)
- */
-void CDECL X11DRV_SetCapture( HWND hwnd, UINT flags )
-{
-    struct x11drv_thread_data *thread_data = x11drv_thread_data();
-
-    if (!thread_data) return;
-    if (!(flags & (GUI_INMOVESIZE | GUI_INMENUMODE))) return;
-
-    if (hwnd)
-    {
-        Window grab_win = X11DRV_get_whole_window( GetAncestor( hwnd, GA_ROOT ) );
-
-        if (!grab_win) return;
-        XFlush( gdi_display );
-        XGrabPointer( thread_data->display, grab_win, False,
-                      PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
-                      GrabModeAsync, GrabModeAsync, None, None, CurrentTime );
-        thread_data->grab_window = grab_win;
-    }
-    else  /* release capture */
-    {
-        XFlush( gdi_display );
-        XUngrabPointer( thread_data->display, CurrentTime );
-        XFlush( thread_data->display );
-        thread_data->grab_window = None;
-    }
-}
-
-
 /*****************************************************************
  *		SetParent   (X11DRV.@)
  */
@@ -2603,7 +2572,9 @@ LRESULT CDECL X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
         X11DRV_resize_desktop( LOWORD(lp), HIWORD(lp) );
         return 0;
     case WM_X11DRV_SET_CURSOR:
-        if ((data = get_win_data( hwnd )))
+        if (x11drv_thread_data()->grab_window)
+            set_window_cursor( x11drv_thread_data()->grab_window, (HCURSOR)lp );
+        else if ((data = get_win_data( hwnd )))
         {
             if (data->whole_window) set_window_cursor( data->whole_window, (HCURSOR)lp );
             release_win_data( data );
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 7a3374d..b0b6ba9 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -311,6 +311,7 @@ struct x11drv_thread_data
     Display *display;
     XEvent  *current_event;        /* event currently being processed */
     Window   grab_window;          /* window that currently grabs the mouse */
+    Window   capture_window;       /* window used for capture */
     HWND     last_focus;           /* last window that had focus */
     XIM      xim;                  /* input method */
     HWND     last_xic_hwnd;        /* last xic window */
-- 
1.8.3.2



More information about the wine-patches mailing list