Make DrawMenuBar and SetMenu tests pass under Wine. Take 4
Dmitry Timoshkov
dmitry at baikal.ru
Wed Sep 28 08:05:04 CDT 2005
Hello,
this is basically the same patch as a previous one, but with tests
for parent/child repainting sequences suggested by Alexandre.
The tests show that Wine incorrectly suppresses the WM_ERASEBKGND message
sending while Windows does that (although clipping box is empty) for
RDW_FRAME case. A quick fix with removing a test for NULLREGION in
dlls/user/painting.c,send_erase() breaks some other test cases, so that
needs more work.
Changelog:
Dmitry Timoshkov <dmitry at codeweavers.com>
Make DrawMenuBar and SetMenu tests pass under Wine.
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-09-14 13:48:11.000000000 +0900
+++ wine/dlls/user/tests/msg.c 2005-09-28 21:48:43.000000000 +0900
@@ -189,6 +189,53 @@ static const struct message WmSWP_MoveSe
{ 0 }
};
+/* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
+ SWP_NOZORDER|SWP_FRAMECHANGED)
+ * for a visible overlapped window with WS_CLIPCHILDREN style set.
+ */
+static const struct message WmSWP_FrameChanged_clip[] = {
+ { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED },
+ { WM_NCCALCSIZE, sent|wparam|parent, 1 },
+ { WM_NCPAINT, sent|parent }, /* wparam != 1 */
+ { WM_ERASEBKGND, sent|parent|optional }, /* FIXME: remove optional once Wine is fixed */
+ { WM_NCPAINT, sent }, /* wparam != 1 */
+ { WM_ERASEBKGND, sent },
+ { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+ { WM_PAINT, sent },
+ { 0 }
+};
+/* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|
+ SWP_NOZORDER|SWP_FRAMECHANGED)
+ * for a visible overlapped window.
+ */
+static const struct message WmSWP_FrameChangedDeferErase[] = {
+ { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED },
+ { WM_NCCALCSIZE, sent|wparam|parent, 1 },
+ { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+ { WM_PAINT, sent|parent },
+ { WM_NCPAINT, sent|beginpaint|parent }, /* wparam != 1 */
+ { WM_PAINT, sent },
+ { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */
+ { WM_ERASEBKGND, sent|beginpaint },
+ { 0 }
+};
+
+/* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
+ SWP_NOZORDER|SWP_FRAMECHANGED)
+ * for a visible overlapped window without WS_CLIPCHILDREN style set.
+ */
+static const struct message WmSWP_FrameChanged_noclip[] = {
+ { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED },
+ { WM_NCCALCSIZE, sent|wparam|parent, 1 },
+ { WM_NCPAINT, sent|parent }, /* wparam != 1 */
+ { WM_ERASEBKGND, sent|parent|optional }, /* FIXME: remove optional once Wine is fixed */
+ { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+ { WM_PAINT, sent },
+ { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */
+ { WM_ERASEBKGND, sent|beginpaint },
+ { 0 }
+};
+
/* ShowWindow(SW_SHOW) for a not visible overlapped window */
static const struct message WmShowOverlappedSeq[] = {
{ WM_SHOWWINDOW, sent|wparam, 1 },
@@ -923,7 +970,7 @@ static const struct message WmSetMenuVis
{ WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
{ WM_NCCALCSIZE, sent|wparam, 1 },
{ EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
- { WM_NCPAINT, sent|wparam, 1 },
+ { WM_NCPAINT, sent }, /* wparam != 1 */
{ WM_GETTEXT, sent|defwinproc|optional },
{ WM_ERASEBKGND, sent|optional },
{ WM_ACTIVATE, sent|optional },
@@ -932,7 +979,7 @@ static const struct message WmSetMenuVis
{ WM_SIZE, sent|defwinproc },
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
{ WM_NCCALCSIZE, sent|wparam|optional, 1 },
- { WM_NCPAINT, sent|wparam|optional, 1 },
+ { WM_NCPAINT, sent|optional }, /* wparam != 1 */
{ WM_ERASEBKGND, sent|optional },
{ 0 }
};
@@ -940,7 +987,7 @@ static const struct message WmSetMenuVis
static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
{ WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
{ WM_NCCALCSIZE, sent|wparam, 1 },
- { WM_NCPAINT, sent|wparam, 1 },
+ { WM_NCPAINT, sent }, /* wparam != 1 */
{ WM_GETTEXT, sent|defwinproc|optional },
{ WM_ERASEBKGND, sent|optional },
{ WM_ACTIVATE, sent|optional },
@@ -953,7 +1000,7 @@ static const struct message WmDrawMenuBa
{
{ WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
{ WM_NCCALCSIZE, sent|wparam, 1 },
- { WM_NCPAINT, sent|wparam, 1 },
+ { WM_NCPAINT, sent }, /* wparam != 1 */
{ WM_GETTEXT, sent|defwinproc|optional },
{ WM_ERASEBKGND, sent|optional },
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
@@ -3219,14 +3266,20 @@ static void test_messages(void)
ok (SetMenu(hwnd, 0), "SetMenu\n");
ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE);
ShowWindow(hwnd, SW_SHOW);
+ UpdateWindow( hwnd );
+ while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
flush_sequence();
ok (SetMenu(hwnd, 0), "SetMenu\n");
- ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", TRUE);
+ ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", FALSE);
ok (SetMenu(hwnd, hmenu), "SetMenu\n");
- ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", TRUE);
+ ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", FALSE);
+ UpdateWindow( hwnd );
+ while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+ flush_sequence();
ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
- ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", TRUE);
+ while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+ ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE);
DestroyWindow(hwnd);
flush_sequence();
@@ -4001,12 +4054,54 @@ static void test_paint_messages(void)
while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
+ assert( GetWindowLong(hparent, GWL_STYLE) & WS_CLIPCHILDREN );
+ UpdateWindow( hparent );
+ while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+ flush_sequence();
+ trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
+ RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
+ SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+ while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+ ok_sequence(WmSWP_FrameChanged_clip, "SetWindowPos:FrameChanged_clip", FALSE );
+
+ UpdateWindow( hparent );
+ while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+ flush_sequence();
+ trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
+ RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
+ SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE |
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+ while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+ ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
+
SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
+ assert( !(GetWindowLong(hparent, GWL_STYLE) & WS_CLIPCHILDREN) );
+ UpdateWindow( hparent );
+ while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+ flush_sequence();
+ trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n");
+ RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
+ SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+ while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+ ok_sequence(WmSWP_FrameChanged_noclip, "SetWindowPos:FrameChanged_noclip", FALSE );
+
+ UpdateWindow( hparent );
+ while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+ flush_sequence();
+ trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n");
+ RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
+ SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE |
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+ while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+ ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
+
log_all_parent_messages--;
DestroyWindow( hparent );
ok(!IsWindow(hchild), "child must be destroyed with its parent\n");
@@ -4675,6 +4770,36 @@ static LRESULT WINAPI ParentMsgCheckProc
message == WM_ENABLE || message == WM_ENTERIDLE ||
message == WM_IME_SETCONTEXT)
{
+ switch (message)
+ {
+ case WM_ERASEBKGND:
+ {
+ RECT rc;
+ INT ret = GetClipBox((HDC)wParam, &rc);
+
+ trace("WM_ERASEBKGND: GetClipBox()=%d, (%ld,%ld-%ld,%ld)\n",
+ ret, rc.left, rc.top, rc.right, rc.bottom);
+ break;
+ }
+
+ case WM_WINDOWPOSCHANGING:
+ case WM_WINDOWPOSCHANGED:
+ {
+ WINDOWPOS *winpos = (WINDOWPOS *)lParam;
+
+ trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
+ trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
+ winpos->hwnd, winpos->hwndInsertAfter,
+ winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
+
+ /* Log only documented flags, win2k uses 0x1000 and 0x2000
+ * in the high word for internal purposes
+ */
+ wParam = winpos->flags & 0xffff;
+ break;
+ }
+ }
+
msg.message = message;
msg.flags = sent|parent|wparam|lparam;
if (defwndproc_counter) msg.flags |= defwinproc;
diff -up cvs/hq/wine/dlls/x11drv/winpos.c wine/dlls/x11drv/winpos.c
--- cvs/hq/wine/dlls/x11drv/winpos.c 2005-09-20 12:52:44.000000000 +0900
+++ wine/dlls/x11drv/winpos.c 2005-09-28 21:33:34.000000000 +0900
@@ -727,6 +727,14 @@ BOOL X11DRV_SetWindowPos( WINDOWPOS *win
&newWindowRect, &newClientRect, orig_flags, valid_rects ))
return FALSE;
+ if ( !(orig_flags & SWP_SHOWWINDOW) &&
+ GetWindowLongW(winpos->hwnd, GWL_STYLE) & WS_VISIBLE )
+ {
+ UINT rdw_flags = RDW_FRAME | RDW_ERASE;
+ if ( !(orig_flags & SWP_DEFERERASE) ) rdw_flags |= RDW_ERASENOW;
+ RedrawWindow( winpos->hwnd, NULL, NULL, rdw_flags );
+ }
+
if( winpos->flags & SWP_HIDEWINDOW )
HideCaret(winpos->hwnd);
else if (winpos->flags & SWP_SHOWWINDOW)
More information about the wine-patches
mailing list