Do not release capture before sending WM_NCDESTROY message

Dmitry Timoshkov dmitry at baikal.ru
Mon Mar 14 08:04:44 CST 2005


Hello,

test.winehq.org msg.c tests show that Windows actually doesn't release
capture before sending WM_NCDESTROY message.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Do not release capture before sending WM_NCDESTROY message,
    update the tests to reflect that.

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-03-14 21:31:56.000000000 +0800
+++ wine/dlls/user/tests/msg.c	2005-03-14 21:28:54.000000000 +0800
@@ -152,6 +152,7 @@ static const struct message WmSWP_Resize
     { WM_NCPAINT, sent|optional },
     { WM_GETTEXT, sent|defwinproc|optional },
     { WM_ERASEBKGND, sent|optional },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
     { 0 }
 };
 
@@ -170,6 +171,7 @@ static const struct message WmSWP_Resize
     { WM_NCPAINT, sent|optional },
     { WM_GETTEXT, sent|defwinproc|optional },
     { WM_ERASEBKGND, sent|optional },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
     { 0 }
 };
 
@@ -183,6 +185,7 @@ static const struct message WmSWP_MoveSe
     { WM_ERASEBKGND, sent|optional },
     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCLIENTSIZE },
     { WM_MOVE, sent|defwinproc|wparam, 0 },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
     { 0 }
 };
 
@@ -1029,6 +1032,7 @@ static const struct message WmSHOWNAChil
 static const struct message WmSHOWNAChildInvisParVis[] = {
     { WM_SHOWWINDOW, sent|wparam, 1 },
     { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER},
+    { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
     { WM_ERASEBKGND, sent|optional },
     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
     { 0 }
@@ -1041,6 +1045,7 @@ static const struct message WmSHOWNATopV
 static const struct message WmSHOWNATopInvisible[] = {
     { WM_SHOWWINDOW, sent|wparam, 1 },
     { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
+    { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
     { WM_NCPAINT, sent|wparam, 1 },
     { WM_GETICON, sent|optional },
     { WM_GETICON, sent|optional },
@@ -2835,7 +2840,11 @@ static void test_showwindow(void)
     ok_sequence(WmSHOWNAChildInvisParVis, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE);
     trace("done\n");
 
+    SetCapture(hchild);
+    ok(GetCapture() == hchild, "wrong capture window %p\n", GetCapture());
     DestroyWindow(hchild);
+    ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
+
     DestroyWindow(hwnd);
     flush_sequence();
 }
@@ -4374,9 +4383,32 @@ static LRESULT WINAPI MsgCheckProcA(HWND
 
     switch (message)
     {
+	case WM_CAPTURECHANGED:
+	    if (test_DestroyWindow_flag)
+	    {
+		DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
+		if (style & WS_CHILD)
+		    lParam = GetWindowLongA(hwnd, GWL_ID);
+		else if (style & WS_POPUP)
+		    lParam = WND_POPUP_ID;
+		else
+		    lParam = WND_PARENT_ID;
+	    }
+	    break;
+
 	case WM_NCDESTROY:
+	{
+	    HWND capture;
+
 	    ok(!GetWindow(hwnd, GW_CHILD), "children should be unlinked at this point\n");
-	    ok(GetCapture() != hwnd, "capture should be released at this point\n");
+	    capture = GetCapture();
+	    if (capture)
+	    {
+		ok(capture == hwnd, "capture should NOT be released at this point (capture %p)\n", capture);
+		trace("current capture %p, releasing...\n", capture);
+		ReleaseCapture();
+	    }
+	}
 	/* fall through */
 	case WM_DESTROY:
             if (pGetAncestor)
@@ -5445,10 +5477,12 @@ static void test_scrollwindowex(void)
 }
 
 static const struct message destroy_window_with_children[] = {
+    { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, /* popup */
     { HCBT_DESTROYWND, hook|lparam, 0, WND_PARENT_ID }, /* parent */
     { HCBT_DESTROYWND, hook|lparam, 0, WND_POPUP_ID }, /* popup */
     { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* popup */
     { WM_DESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
+    { WM_CAPTURECHANGED, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
     { WM_NCDESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
     { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* parent */
     { WM_DESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */
@@ -5559,9 +5593,9 @@ todo_wine {
     trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
 	   parent, child1, child2, child3, child4);
 
-    SetCapture(child3);
+    SetCapture(child4);
     test = GetCapture();
-    ok(test == child3, "wrong capture window %p\n", test);
+    ok(test == child4, "wrong capture window %p\n", test);
 
     test_DestroyWindow_flag = TRUE;
     ok(DestroyWindow(parent), "DestroyWindow() error %ld\n", GetLastError());
diff -up cvs/hq/wine/dlls/user/tests/win.c wine/dlls/user/tests/win.c
--- cvs/hq/wine/dlls/user/tests/win.c	2005-03-14 21:31:56.000000000 +0800
+++ wine/dlls/user/tests/win.c	2005-03-14 21:41:41.000000000 +0800
@@ -2043,7 +2043,12 @@ static void test_capture_1(void)
 
     SendMessageA(button, WM_LBUTTONDOWN, 0, 0);
 
+    capture = SetCapture(button);
+    ok(capture == 0, "SetCapture() = %p\n", capture);
+    check_wnd_state(button, 0, button, button);
+
     DestroyWindow(button);
+    check_wnd_state(0, 0, 0, 0);
 }
 
 static void test_capture_2(void)
diff -up cvs/hq/wine/windows/win.c wine/windows/win.c
--- cvs/hq/wine/windows/win.c	2005-03-11 20:08:25.000000000 +0800
+++ wine/windows/win.c	2005-03-14 21:50:39.000000000 +0800
@@ -614,23 +614,6 @@ 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
@@ -667,8 +650,6 @@ 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 );
 






More information about the wine-patches mailing list