user32: Make all the recently added ShowWindow tests pass in Wine

Dmitry Timoshkov dmitry at codeweavers.com
Wed May 17 00:39:42 CDT 2006


Hello,

this patch makes all the recently added ShowWindow tests pass in Wine,
and is aimed to fix the bug #4960.

Although this patch creates a regression for popup windows created with
WS_MAXIMIZED style set and calling ShowWindow( SW_SHOWMAXIMIZE ) right
after that (Windows still calls SetWindowPos in that case, but Wine
doesn't anymore - the tests show that SetWindowPos should not be called
for child windows if their state already matches the ShowWindow command)
but top level windows already behave slightly differently in Wine since
they are WM driven, and adding window state change (min/max/restore) through
a WM will make them behave even more differently.

Changelog:
    Make all the recently added ShowWindow tests pass in 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	2006-05-17 11:16:59.000000000 +0900
+++ wine/dlls/user/tests/msg.c	2006-05-17 13:33:50.000000000 +0900
@@ -643,6 +643,9 @@ static const struct message WmShowChildI
     { WM_MOVE, sent|defwinproc },
     { WM_SIZE, sent|defwinproc },
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
+    /* FIXME: Wine creates an icon/title window while Windows doesn't */
+    { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE },
+    { WM_GETTEXT, sent|optional },
     { 0 }
 };
 /* repeated ShowWindow(SW_MINIMIZE) for child with invisible parent */
@@ -677,6 +680,9 @@ static const struct message WmShowChildI
     { WM_MOVE, sent|defwinproc },
     { WM_SIZE, sent|defwinproc },
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
+    /* FIXME: Wine creates an icon/title window while Windows doesn't */
+    { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE },
+    { WM_GETTEXT, sent|optional },
     { 0 }
 };
 /* repeated ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
@@ -693,6 +699,9 @@ static const struct message WmShowChildI
     { WM_MOVE, sent|defwinproc },
     { WM_SIZE, sent|defwinproc },
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
+    /* FIXME: Wine creates an icon/title window while Windows doesn't */
+    { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE },
+    { WM_GETTEXT, sent|optional },
     { 0 }
 };
 /* repeated ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
@@ -3281,6 +3290,7 @@ static void test_showwindow(void)
     hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE,
                            100, 100, 200, 200, 0, 0, 0, NULL);
     ok (hwnd != 0, "Failed to create popup window\n");
+    ok(IsZoomed(hwnd), "window should be maximized\n");
     ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
     trace("done\n");
 
@@ -3291,18 +3301,22 @@ static void test_showwindow(void)
         rc.left, rc.top, rc.right, rc.bottom);
     /* Reset window's size & position */
     SetWindowPos(hwnd, 0, 10, 10, 200, 200, SWP_NOZORDER | SWP_NOACTIVATE);
+    ok(IsZoomed(hwnd), "window should be maximized\n");
     flush_sequence();
 
-    trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible popup window\n");
+    trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
     ShowWindow(hwnd, SW_SHOWMAXIMIZED);
-    ok_sequence(WmShowMaxPopupResizedSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE);
+    ok(IsZoomed(hwnd), "window should be maximized\n");
+    ok_sequence(WmShowMaxPopupResizedSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", TRUE);
     trace("done\n");
 
     GetWindowRect(hwnd, &rc);
+todo_wine {
     ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) &&
         rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN),
         "Invalid maximized size after ShowWindow (%ld,%ld)-(%ld,%ld)\n",
         rc.left, rc.top, rc.right, rc.bottom);
+}
     DestroyWindow(hwnd);
     flush_sequence();
 
@@ -3314,12 +3328,14 @@ static void test_showwindow(void)
     hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE,
                            100, 100, 200, 200, 0, 0, 0, NULL);
     ok (hwnd != 0, "Failed to create popup window\n");
+    ok(IsZoomed(hwnd), "window should be maximized\n");
     ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
     trace("done\n");
 
-    trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible popup window\n");
+    trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
     ShowWindow(hwnd, SW_SHOWMAXIMIZED);
-    ok_sequence(WmShowMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE);
+    ok(IsZoomed(hwnd), "window should be maximized\n");
+    ok_sequence(WmShowMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", TRUE);
     trace("done\n");
     DestroyWindow(hwnd);
     flush_sequence();
@@ -3331,6 +3347,7 @@ static void test_showwindow(void)
     hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE | WS_VISIBLE,
                            100, 100, 200, 200, 0, 0, 0, NULL);
     ok (hwnd != 0, "Failed to create popup window\n");
+    ok(IsZoomed(hwnd), "window should be maximized\n");
     ok_sequence(WmCreateMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
     trace("done\n");
     DestroyWindow(hwnd);
@@ -3344,11 +3361,13 @@ static void test_showwindow(void)
     hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_VISIBLE,
                            100, 100, 200, 200, 0, 0, 0, NULL);
     ok (hwnd != 0, "Failed to create popup window\n");
+    ok(!IsZoomed(hwnd), "window should NOT be maximized\n");
     ok_sequence(WmCreatePopupSeq, "CreateWindow(WS_VISIBLE):popup", TRUE);
     trace("done\n");
 
     trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n");
     ShowWindow(hwnd, SW_SHOWMAXIMIZED);
+    ok(IsZoomed(hwnd), "window should be maximized\n");
     ok_sequence(WmShowVisMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", TRUE);
     trace("done\n");
     DestroyWindow(hwnd);
@@ -3740,14 +3759,14 @@ static void invisible_parent_tests(void)
     ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
 
     ShowWindow( hchild, SW_MINIMIZE );
-    ok_sequence(WmShowChildInvisibleParentSeq_1, "ShowWindow(SW_MINIMIZE) child with invisible parent", TRUE);
+    ok_sequence(WmShowChildInvisibleParentSeq_1, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE);
     ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
     ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
 
     /* repeat */
     flush_events();
     ShowWindow( hchild, SW_MINIMIZE );
-    ok_sequence(WmShowChildInvisibleParentSeq_1r, "ShowWindow(SW_MINIMIZE) child with invisible parent", TRUE);
+    ok_sequence(WmShowChildInvisibleParentSeq_1r, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE);
 
     DestroyWindow(hchild);
     hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
@@ -3755,14 +3774,14 @@ static void invisible_parent_tests(void)
     flush_sequence();
 
     ShowWindow( hchild, SW_MAXIMIZE );
-    ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_MAXIMIZE) child with invisible parent", TRUE);
+    ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE);
     ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
     ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
 
     /* repeat */
     flush_events();
     ShowWindow( hchild, SW_MAXIMIZE );
-    ok_sequence(WmShowChildInvisibleParentSeq_2r, "ShowWindow(SW_MAXIMIZE) child with invisible parent", TRUE);
+    ok_sequence(WmShowChildInvisibleParentSeq_2r, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE);
 
     DestroyWindow(hchild);
     hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
@@ -3770,14 +3789,14 @@ static void invisible_parent_tests(void)
     flush_sequence();
 
     ShowWindow( hchild, SW_SHOWMINIMIZED );
-    ok_sequence(WmShowChildInvisibleParentSeq_3, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", TRUE);
+    ok_sequence(WmShowChildInvisibleParentSeq_3, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE);
     ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
     ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
 
     /* repeat */
     flush_events();
     ShowWindow( hchild, SW_SHOWMINIMIZED );
-    ok_sequence(WmShowChildInvisibleParentSeq_3r, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", TRUE);
+    ok_sequence(WmShowChildInvisibleParentSeq_3r, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE);
 
     DestroyWindow(hchild);
     hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
@@ -3786,7 +3805,7 @@ static void invisible_parent_tests(void)
 
     /* same as ShowWindow( hchild, SW_MAXIMIZE ); */
     ShowWindow( hchild, SW_SHOWMAXIMIZED );
-    ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", TRUE);
+    ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE);
     ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
     ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
 
@@ -3796,14 +3815,14 @@ static void invisible_parent_tests(void)
     flush_sequence();
 
     ShowWindow( hchild, SW_SHOWMINNOACTIVE );
-    ok_sequence(WmShowChildInvisibleParentSeq_4, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", TRUE);
+    ok_sequence(WmShowChildInvisibleParentSeq_4, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE);
     ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
     ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
 
     /* repeat */
     flush_events();
     ShowWindow( hchild, SW_SHOWMINNOACTIVE );
-    ok_sequence(WmShowChildInvisibleParentSeq_4r, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", TRUE);
+    ok_sequence(WmShowChildInvisibleParentSeq_4r, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE);
 
     DestroyWindow(hchild);
     hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
diff -up cvs/hq/wine/dlls/x11drv/winpos.c wine/dlls/x11drv/winpos.c
--- cvs/hq/wine/dlls/x11drv/winpos.c	2006-05-17 11:17:04.000000000 +0900
+++ wine/dlls/x11drv/winpos.c	2006-05-17 13:17:48.000000000 +0900
@@ -852,13 +852,23 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT
 
     if (IsIconic( hwnd ))
     {
-        if (cmd == SW_MINIMIZE) return SWP_NOSIZE | SWP_NOMOVE;
+        switch (cmd)
+        {
+        case SW_SHOWMINNOACTIVE:
+        case SW_SHOWMINIMIZED:
+        case SW_FORCEMINIMIZE:
+        case SW_MINIMIZE:
+            return SWP_NOSIZE | SWP_NOMOVE;
+        }
         if (!SendMessageW( hwnd, WM_QUERYOPEN, 0, 0 )) return SWP_NOSIZE | SWP_NOMOVE;
         swpFlags |= SWP_NOCOPYBITS;
     }
 
     switch( cmd )
     {
+    case SW_SHOWMINNOACTIVE:
+    case SW_SHOWMINIMIZED:
+    case SW_FORCEMINIMIZE:
     case SW_MINIMIZE:
         if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
         if( wndPtr->dwStyle & WS_MAXIMIZE) wndPtr->flags |= WIN_RESTORE_MAX;
@@ -877,6 +887,8 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT
         break;
 
     case SW_MAXIMIZE:
+        if (IsZoomed( hwnd )) return SWP_NOSIZE | SWP_NOMOVE;
+
         WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL );
 
         old_style = WIN_SetStyle( hwnd, WS_MAXIMIZE, WS_MINIMIZE );
@@ -933,7 +945,7 @@ BOOL X11DRV_ShowWindow( HWND hwnd, INT c
     HWND parent;
     LONG style = GetWindowLongW( hwnd, GWL_STYLE );
     BOOL wasVisible = (style & WS_VISIBLE) != 0;
-    BOOL showFlag = TRUE;
+    BOOL showFlag = TRUE, state_change = FALSE;
     RECT newPos = {0, 0, 0, 0};
     UINT swp = 0;
 
@@ -949,23 +961,24 @@ BOOL X11DRV_ShowWindow( HWND hwnd, INT c
                 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
 	    break;
 
+	case SW_MINIMIZE:
 	case SW_SHOWMINNOACTIVE:
             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
             /* fall through */
 	case SW_SHOWMINIMIZED:
         case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */
-            swp |= SWP_SHOWWINDOW;
+            swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
             /* fall through */
-	case SW_MINIMIZE:
-            swp |= SWP_FRAMECHANGED;
-            if( !(style & WS_MINIMIZE) )
-		 swp |= WINPOS_MinMaximize( hwnd, SW_MINIMIZE, &newPos );
-            else swp |= SWP_NOSIZE | SWP_NOMOVE;
+            swp |= WINPOS_MinMaximize( hwnd, cmd, &newPos );
+            if( style & WS_MINIMIZE ) return wasVisible;
+            state_change = TRUE;
 	    break;
 
 	case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
             swp |= WINPOS_MinMaximize( hwnd, SW_MAXIMIZE, &newPos );
+            if( style & WS_MAXIMIZE ) return wasVisible;
+            state_change = TRUE;
             break;
 
 	case SW_SHOWNA:
@@ -979,6 +992,7 @@ BOOL X11DRV_ShowWindow( HWND hwnd, INT c
 
 	case SW_RESTORE:
 	    swp |= SWP_FRAMECHANGED;
+            state_change = TRUE;
             /* fall through */
 	case SW_SHOWNOACTIVATE:
             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
@@ -993,14 +1007,14 @@ BOOL X11DRV_ShowWindow( HWND hwnd, INT c
 	    break;
     }
 
-    if ((showFlag != wasVisible || cmd == SW_SHOWNA) && cmd != SW_SHOWMAXIMIZED)
+    if ((showFlag != wasVisible || cmd == SW_SHOWNA) && !state_change)
     {
         SendMessageW( hwnd, WM_SHOWWINDOW, showFlag, 0 );
         if (!IsWindow( hwnd )) return wasVisible;
     }
 
     parent = GetAncestor( hwnd, GA_PARENT );
-    if (parent && !IsWindowVisible( parent ))
+    if (parent && !IsWindowVisible( parent ) && !state_change)
     {
         /* if parent is not visible simply toggle WS_VISIBLE and return */
         if (showFlag) WIN_SetStyle( hwnd, WS_VISIBLE, 0 );
@@ -1009,9 +1023,14 @@ BOOL X11DRV_ShowWindow( HWND hwnd, INT c
     else
     {
         /* ShowWindow won't activate a not being maximized child window */
-        if ((style & WS_CHILD) && cmd != SW_MAXIMIZE)
+        if ((style & WS_CHILD) && !state_change)
             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
 
+        /* it appears that Windows always adds an undocumented 0x8000 flag
+         * if the state of a window changes. FIXME: real SWP_xxxx name?
+         */
+        if (state_change) swp |= 0x8000;
+
         SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
                       newPos.right, newPos.bottom, LOWORD(swp) );
     }





More information about the wine-patches mailing list