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