CreateWindow should not activate invisible minimized or maximized windows.

Vitaliy Margolen wine-patch at kievinfo.com
Tue Nov 29 15:54:16 CST 2005


ChangeLog:
CreateWindow should not activate invisible minimized or maximized windows.
Add several tests to show the correct behavior.

 dlls/user/tests/msg.c |  215 +++++++++++++++++++++++++++++++++++++++++++++++++
 dlls/x11drv/window.c  |    8 +-
 2 files changed, 220 insertions(+), 3 deletions(-)
-------------- next part --------------
e467b948572fae1f0c560bf6f8ca1ba8c594714b
diff --git a/dlls/user/tests/msg.c b/dlls/user/tests/msg.c
index 8d704d6..d04aeeb 100644
--- a/dlls/user/tests/msg.c
+++ b/dlls/user/tests/msg.c
@@ -352,6 +352,137 @@ static const struct message WmDestroyOve
     { WM_NCDESTROY, sent },
     { 0 }
 };
+/* CreateWindow(WS_MAXIMAZE|WS_VISIBLE) for popup window */
+static const struct message WmCreateMaxPopupSeq[] = {
+    { HCBT_CREATEWND, hook },
+    { WM_NCCREATE, sent },
+    { WM_NCCALCSIZE, sent|wparam, 0 },
+    { WM_CREATE, sent },
+    { WM_SIZE, sent },
+    { WM_MOVE, sent },
+    { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
+    { WM_GETMINMAXINFO, sent },
+    { WM_WINDOWPOSCHANGING, sent /*|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|0x8000*/ },
+    { WM_NCCALCSIZE, sent|wparam, TRUE },
+    { WM_WINDOWPOSCHANGED, sent /*|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOZORDER|0x8000*/ },
+    { WM_MOVE, sent|defwinproc },
+    { WM_SIZE, sent|defwinproc },
+    { WM_SHOWWINDOW, sent|wparam, 1 },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
+    { HCBT_ACTIVATE, hook },
+    { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
+    { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
+    { WM_ACTIVATEAPP, sent|wparam, 1 },
+    { WM_NCACTIVATE, sent|wparam, 1 },
+    { WM_ACTIVATE, sent|wparam, 1 },
+    { HCBT_SETFOCUS, hook },
+    { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+    { WM_SYNCPAINT, sent|wparam|optional, 4 },
+    { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 },
+    { WM_ERASEBKGND, sent|defwinproc|optional },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER|SWP_NOSIZE },
+    { 0 }
+};
+/* CreateWindow(WS_MAXIMAZE) for popup window, not initially visible */
+static const struct message WmCreateInvisibleMaxPopupSeq[] = {
+    { HCBT_CREATEWND, hook },
+    { WM_NCCREATE, sent },
+    { WM_NCCALCSIZE, sent|wparam, 0 },
+    { WM_CREATE, sent },
+    { WM_SIZE, sent },
+    { WM_MOVE, sent },
+    { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
+    { WM_GETMINMAXINFO, sent },
+    { WM_WINDOWPOSCHANGING, sent /*|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|0x8000*/ },
+    { WM_NCCALCSIZE, sent|wparam, TRUE },
+    { WM_WINDOWPOSCHANGED, sent /*|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOZORDER|0x8000*/ },
+    { WM_MOVE, sent|defwinproc },
+    { WM_SIZE, sent|defwinproc },
+    { 0 }
+};
+/* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */
+static const struct message WmShowMaxPopupResizedSeq[] = {
+    { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
+    { WM_GETMINMAXINFO, sent },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED },
+    { WM_NCCALCSIZE, sent|wparam, TRUE },
+    { HCBT_ACTIVATE, hook },
+    { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
+    { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
+    { WM_ACTIVATEAPP, sent|wparam, 1 },
+    { WM_NCACTIVATE, sent|wparam, 1 },
+    { WM_ACTIVATE, sent|wparam, 1 },
+    { HCBT_SETFOCUS, hook },
+    { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+    { WM_NCPAINT, sent|wparam|optional, 1 },
+    { WM_ERASEBKGND, sent|optional },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOZORDER },
+    /* WinNT4.0 sends WM_MOVE */
+    { WM_MOVE, sent|defwinproc|optional },
+    { WM_SIZE, sent|defwinproc },
+    { 0 }
+};
+/* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */
+static const struct message WmShowMaxPopupSeq[] = {
+    { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
+    { WM_GETMINMAXINFO, sent },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED },
+    { WM_NCCALCSIZE, sent|wparam, TRUE },
+    { HCBT_ACTIVATE, hook },
+    { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
+    { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
+    { WM_ACTIVATEAPP, sent|wparam, 1 },
+    { WM_NCACTIVATE, sent|wparam, 1 },
+    { WM_ACTIVATE, sent|wparam, 1 },
+    { HCBT_SETFOCUS, hook },
+    { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+    { WM_SYNCPAINT, sent|wparam|optional, 4 },
+    { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 },
+    { WM_ERASEBKGND, sent|defwinproc|optional },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
+    { 0 }
+};
+/* CreateWindow(WS_VISIBLE) for popup window */
+static const struct message WmCreatePopupSeq[] = {
+    { HCBT_CREATEWND, hook },
+    { WM_NCCREATE, sent },
+    { WM_NCCALCSIZE, sent|wparam, 0 },
+    { WM_CREATE, sent },
+    { WM_SIZE, sent },
+    { WM_MOVE, sent },
+    { WM_SHOWWINDOW, sent|wparam, 1 },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
+    { HCBT_ACTIVATE, hook },
+    { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
+    { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
+    { WM_NCPAINT, sent|wparam|optional, 1 },
+    { WM_ERASEBKGND, sent|optional },
+    { WM_ACTIVATEAPP, sent|wparam, 1 },
+    { WM_NCACTIVATE, sent|wparam, 1 },
+    { WM_ACTIVATE, sent|wparam, 1 },
+    { HCBT_SETFOCUS, hook },
+    { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+    { WM_SYNCPAINT, sent|wparam|optional, 4 },
+    { WM_NCPAINT, sent|wparam|optional, 1 },
+    { WM_ERASEBKGND, sent|optional },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER|SWP_NOSIZE },
+    { 0 }
+};
+/* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */
+static const struct message WmShowVisMaxPopupSeq[] = {
+    { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
+    { WM_GETMINMAXINFO, sent },
+    { WM_GETTEXT, sent|optional },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
+    { WM_NCCALCSIZE, sent|wparam, TRUE },
+    { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
+    { WM_NCPAINT, sent|wparam|optional, 1 },
+    { WM_ERASEBKGND, sent|optional },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOZORDER|0x8000 },
+    { WM_MOVE, sent|defwinproc },
+    { WM_SIZE, sent|defwinproc },
+    { 0 }
+};
 /* CreateWindow (for a child popup window, not initially visible) */
 static const struct message WmCreateChildPopupSeq[] = {
     { HCBT_CREATEWND, hook },
@@ -2865,6 +2996,7 @@ static void test_scroll_messages(HWND hw
 static void test_showwindow(void)
 {
     HWND hwnd, hchild;
+    RECT rc;
 
     hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
                            100, 100, 200, 200, 0, 0, 0, NULL);
@@ -2924,6 +3056,89 @@ static void test_showwindow(void)
 
     DestroyWindow(hwnd);
     flush_sequence();
+
+    /* Popup windows */
+    /* Test 1:
+     * 1. Create invisible maximized popup window.
+     * 2. Move and resize it.
+     * 3. Show it maximized.
+     */
+    trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
+    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_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
+    trace("done\n");
+
+    GetWindowRect(hwnd, &rc);
+    ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) &&
+        rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN),
+        "Invalid maximized size before ShowWindow (%ld,%ld)-(%ld,%ld)\n",
+        rc.left, rc.top, rc.right, rc.bottom);
+    /* Reset window's size & position */
+    SetWindowPos(hwnd, 0, 10, 10, 200, 200, SWP_NOZORDER | SWP_NOACTIVATE);
+    flush_sequence();
+
+    trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible popup window\n");
+    ShowWindow(hwnd, SW_SHOWMAXIMIZED);
+    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();
+
+    /* Test 2:
+     * 1. Create invisible maximized popup window.
+     * 2. Show it maximized.
+     */
+    trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
+    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_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
+    trace("done\n");
+
+    trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible popup window\n");
+    ShowWindow(hwnd, SW_SHOWMAXIMIZED);
+    ok_sequence(WmShowMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", TRUE);
+    trace("done\n");
+    DestroyWindow(hwnd);
+    flush_sequence();
+
+    /* Test 3:
+     * 1. Create visible maximized popup window.
+     */
+    trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n");
+    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_sequence(WmCreateMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", TRUE);
+    trace("done\n");
+    DestroyWindow(hwnd);
+    flush_sequence();
+
+    /* Test 4:
+     * 1. Create visible popup window.
+     * 2. Maximize it.
+     */
+    trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n");
+    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_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_sequence(WmShowVisMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", TRUE);
+    trace("done\n");
+    DestroyWindow(hwnd);
+    flush_sequence();
 }
 
 static void test_sys_menu(HWND hwnd)
diff --git a/dlls/x11drv/window.c b/dlls/x11drv/window.c
index 735afe5..c4530c5 100644
--- a/dlls/x11drv/window.c
+++ b/dlls/x11drv/window.c
@@ -1020,9 +1020,11 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CRE
         UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
         WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
         WINPOS_MinMaximize( hwnd, swFlag, &newPos );
-        swFlag = ((style & WS_CHILD) || GetActiveWindow())
-            ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
-            : SWP_NOZORDER | SWP_FRAMECHANGED;
+
+        swFlag  = SWP_FRAMECHANGED; /* Frame always gets changed */
+        swFlag |= style & WS_VISIBLE ? SWP_NOZORDER : SWP_NOACTIVATE;
+        swFlag |= ((style & WS_CHILD) || GetActiveWindow()) ? SWP_NOACTIVATE : 0;
+
         SetWindowPos( hwnd, 0, newPos.left, newPos.top,
                       newPos.right, newPos.bottom, swFlag );
     }


More information about the wine-patches mailing list