Release capture before sending WM_NCDESTROY message

Dmitry Timoshkov dmitry at baikal.ru
Thu Feb 24 07:28:23 CST 2005


Hello,

this patch proves that the fix in the Crossover tree which makes sure that
a capture should be released before WM_NCDESTROY was sent is almost correct.

Changelog:
    Mike McCormack <mike at codeweavers.com>
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Release capture before sending WM_NCDESTROY message, do not send
    WM_CAPTURECHANGED in that case. Add a test case for that behaviour.

diff -up cvs/hq/wine/dlls/user/tests/msg.c wine/dlls/user/tests/msg.c
--- cvs/hq/wine/dlls/user/tests/msg.c	2005-02-24 16:30:20.000000000 +0800
+++ wine/dlls/user/tests/msg.c	2005-02-24 20:54:58.000000000 +0800
@@ -4342,6 +4342,7 @@ static LRESULT WINAPI MsgCheckProcA(HWND
     {
 	case WM_NCDESTROY:
 	    ok(!GetWindow(hwnd, GW_CHILD), "children should be unlinked at this point\n");
+	    ok(GetCapture() != hwnd, "capture should be released at this point\n");
 	/* fall through */
 	case WM_DESTROY:
             if (pGetAncestor)
@@ -5504,6 +5505,10 @@ static void test_DestroyWindow(void)
     trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
 	   parent, child1, child2, child3, child4);
 
+    SetCapture(child3);
+    test = GetCapture();
+    ok(test == child3, "wrong capture window %p\n", test);
+
     test_DestroyWindow_flag = TRUE;
     ok(DestroyWindow(parent), "DestroyWindow() error %ld\n", GetLastError());
     test_DestroyWindow_flag = FALSE;
@@ -5514,6 +5519,9 @@ static void test_DestroyWindow(void)
     ok(!IsWindow(child2), "child2 still exists");
     ok(!IsWindow(child3), "child3 still exists");
     ok(!IsWindow(child4), "child4 still exists");
+
+    test = GetCapture();
+    ok(!test, "wrong capture window %p\n", test);
 }
 
 
diff -up cvs/hq/wine/windows/win.c wine/windows/win.c
--- cvs/hq/wine/windows/win.c	2005-02-20 20:03:11.000000000 +0800
+++ wine/windows/win.c	2005-02-24 20:58:43.000000000 +0800
@@ -614,6 +614,23 @@ BOOL WIN_GetRectangles( HWND hwnd, RECT 
 
 
 /***********************************************************************
+ *           WIN_ReleaseCapture
+ *
+ * Internal version of ReleaseCapture which doesn't send WM_CAPTURECHANGED
+ * message. Used at the window destruction time.
+ */
+static void WIN_ReleaseCapture( void )
+{
+    SERVER_START_REQ( set_capture_window )
+    {
+        req->handle = 0;
+        req->flags  = 0;
+        wine_server_call_err( req );
+    }
+    SERVER_END_REQ;
+}
+
+/***********************************************************************
  *           WIN_DestroyWindow
  *
  * Destroy storage associated to a window. "Internals" p.358
@@ -650,6 +667,8 @@ LRESULT WIN_DestroyWindow( HWND hwnd )
     RedrawWindow( hwnd, NULL, 0,
                   RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
 
+    if (hwnd == GetCapture()) WIN_ReleaseCapture();
+
     /* Unlink now so we won't bother with the children later on */
     WIN_UnlinkWindow( hwnd );
 
@@ -661,7 +680,6 @@ LRESULT WIN_DestroyWindow( HWND hwnd )
     /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
 
     WINPOS_CheckInternalPos( hwnd );
-    if( hwnd == GetCapture()) ReleaseCapture();
 
     /* free resources associated with the window */
 






More information about the wine-patches mailing list