user32: Extend the support for SWP_STATECHANGED for all windows

Dmitry Timoshkov dmitry at codeweavers.com
Tue Dec 19 05:35:42 CST 2006


Hello,

this is a stripped down version of the following patch:

http://www.winehq.org/pipermail/wine-patches/2006-May/026812.html

It makes 3 existing message tests pass, and adds 1 more test.

Changelog:
    Juris Smotrovs <juris.smotrovs at sets.lv>
    user32: Extend the support for SWP_STATECHANGED for all windows.

---
 dlls/user32/tests/msg.c   |   24 +++++++++++++-----
 dlls/winex11.drv/window.c |    4 +-
 dlls/winex11.drv/winpos.c |   59 ++++++++++++++++++++++-----------------------
 3 files changed, 48 insertions(+), 39 deletions(-)

diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index 98a1229..8e4e611 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -369,9 +369,9 @@ static const struct message WmCreateMaxPopupSeq[] = {
     { WM_MOVE, sent },
     { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
     { WM_GETMINMAXINFO, sent },
-    { WM_WINDOWPOSCHANGING, sent /*|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|0x8000*/ },
+    { 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_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 },
@@ -400,9 +400,9 @@ static const struct message WmCreateInvisibleMaxPopupSeq[] = {
     { WM_MOVE, sent },
     { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
     { WM_GETMINMAXINFO, sent },
-    { WM_WINDOWPOSCHANGING, sent /*|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|0x8000*/ },
+    { 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_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOZORDER|0x8000 },
     { WM_MOVE, sent|defwinproc },
     { WM_SIZE, sent|defwinproc },
     { 0 }
@@ -2996,7 +2996,7 @@ static void test_mdi_messages(void)
 
     trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n");
     ShowWindow(mdi_child2, SW_MAXIMIZE);
-    ok_sequence(WmMaximizeMDIchildInvisibleSeq2, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", TRUE);
+    ok_sequence(WmMaximizeMDIchildInvisibleSeq2, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE);
     ok(IsZoomed(mdi_child2), "MDI child should be maximized\n");
     ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
     ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
@@ -3492,7 +3492,7 @@ static void test_showwindow(void)
     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);
+    ok_sequence(WmShowVisMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE);
     trace("done\n");
     DestroyWindow(hwnd);
     flush_sequence();
@@ -3641,7 +3641,7 @@ static void test_messages(void)
     hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
                              0, 0, 10, 10, hparent, 0, 0, NULL);
     ok (hchild != 0, "Failed to create child window\n");
-    ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", TRUE);
+    ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", FALSE);
     DestroyWindow(hchild);
     flush_sequence();
 
@@ -3926,6 +3926,16 @@ static void invisible_parent_tests(void)
                              0, 0, 10, 10, hparent, 0, 0, NULL);
     flush_sequence();
 
+    ShowWindow( hchild, SW_RESTORE );
+    ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_RESTORE) 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");
+
+    DestroyWindow(hchild);
+    hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
+                             0, 0, 10, 10, hparent, 0, 0, NULL);
+    flush_sequence();
+
     ShowWindow( hchild, SW_SHOWMINIMIZED );
     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");
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 26bd8e1..1430563 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -1162,9 +1162,9 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
         RECT newPos;
         UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
         WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
-        WINPOS_MinMaximize( hwnd, swFlag, &newPos );
+        swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
 
-        swFlag = SWP_FRAMECHANGED | SWP_NOZORDER; /* Frame always gets changed */
+        swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
         if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
 
         SetWindowPos( hwnd, 0, newPos.left, newPos.top,
diff --git a/dlls/winex11.drv/winpos.c b/dlls/winex11.drv/winpos.c
index 6d04769..b1690df 100644
--- a/dlls/winex11.drv/winpos.c
+++ b/dlls/winex11.drv/winpos.c
@@ -490,12 +490,13 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
         else wndPtr->flags &= ~WIN_RESTORE_MAX;
         WIN_ReleasePtr( wndPtr );
 
-        WIN_SetStyle( hwnd, WS_MINIMIZE, WS_MAXIMIZE );
+        old_style = WIN_SetStyle( hwnd, WS_MINIMIZE, WS_MAXIMIZE );
 
         X11DRV_set_iconic_state( hwnd );
 
         wpl.ptMinPosition = WINPOS_FindIconPos( hwnd, wpl.ptMinPosition );
 
+        if (!(old_style & WS_MINIMIZE)) swpFlags |= SWP_STATECHANGED;
         SetRect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
                  GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
         swpFlags |= SWP_NOCOPYBITS;
@@ -513,9 +514,12 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
             WINPOS_ShowIconTitle( hwnd, FALSE );
             X11DRV_set_iconic_state( hwnd );
         }
+        if (!(old_style & WS_MAXIMIZE)) swpFlags |= SWP_STATECHANGED;
         SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y );
         break;
 
+    case SW_SHOWNOACTIVATE:
+    case SW_SHOWNORMAL:
     case SW_RESTORE:
         old_style = WIN_SetStyle( hwnd, 0, WS_MINIMIZE | WS_MAXIMIZE );
         if (old_style & WS_MINIMIZE)
@@ -533,12 +537,15 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
                 /* Restore to maximized position */
                 WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL);
                 WIN_SetStyle( hwnd, WS_MAXIMIZE, 0 );
+                swpFlags |= SWP_STATECHANGED;
                 SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y );
                 break;
             }
         }
         else if (!(old_style & WS_MAXIMIZE)) break;
 
+        swpFlags |= SWP_STATECHANGED;
+
         /* Restore to normal position */
 
         *rect = wpl.rcNormalPosition;
@@ -561,7 +568,7 @@ BOOL X11DRV_ShowWindow( HWND hwnd, INT cmd )
     HWND parent;
     LONG style = GetWindowLongW( hwnd, GWL_STYLE );
     BOOL wasVisible = (style & WS_VISIBLE) != 0;
-    BOOL showFlag = TRUE, state_change = FALSE;
+    BOOL showFlag = TRUE;
     RECT newPos = {0, 0, 0, 0};
     UINT swp = 0;
 
@@ -588,14 +595,13 @@ BOOL X11DRV_ShowWindow( HWND hwnd, INT cmd )
             swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
             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;
+            if (!wasVisible) swp |= SWP_SHOWWINDOW;
+            swp |= SWP_FRAMECHANGED;
             swp |= WINPOS_MinMaximize( hwnd, SW_MAXIMIZE, &newPos );
             if ((style & WS_MAXIMIZE) && wasVisible) return wasVisible;
-            state_change = TRUE;
             break;
 
 	case SW_SHOWNA:
@@ -608,52 +614,45 @@ BOOL X11DRV_ShowWindow( HWND hwnd, INT cmd )
             if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
 	    break;
 
-	case SW_RESTORE:
-	    swp |= SWP_FRAMECHANGED;
-            state_change = TRUE;
-            /* fall through */
 	case SW_SHOWNOACTIVATE:
             swp |= SWP_NOACTIVATE | SWP_NOZORDER;
             /* fall through */
+	case SW_RESTORE:
+	    swp |= SWP_FRAMECHANGED;
+	    if (!wasVisible) swp |= SWP_SHOWWINDOW;
+            /* fall through */
 	case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
 	case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
-	    swp |= SWP_SHOWWINDOW;
             if (style & (WS_MINIMIZE | WS_MAXIMIZE))
-		 swp |= WINPOS_MinMaximize( hwnd, SW_RESTORE, &newPos );
-            else swp |= SWP_NOSIZE | SWP_NOMOVE;
-            if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
+            {
+                swp |= SWP_FRAMECHANGED;
+                swp |= WINPOS_MinMaximize( hwnd, cmd, &newPos );
+            }
+            else
+            {
+                if (!wasVisible) swp |= SWP_SHOWWINDOW;
+                swp |= SWP_NOSIZE | SWP_NOMOVE;
+            }
+            if (style & WS_CHILD && !(swp & SWP_STATECHANGED)) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
 	    break;
     }
 
-    if ((showFlag != wasVisible || cmd == SW_SHOWNA) && !state_change)
+    if ((showFlag != wasVisible || cmd == SW_SHOWNA) && cmd != SW_SHOWMAXIMIZED && !(swp & SWP_STATECHANGED))
     {
         SendMessageW( hwnd, WM_SHOWWINDOW, showFlag, 0 );
         if (!IsWindow( hwnd )) return wasVisible;
     }
 
     parent = GetAncestor( hwnd, GA_PARENT );
-    if (parent && !IsWindowVisible( parent ) && !state_change)
+    if (parent && !IsWindowVisible( parent ) && !(swp & SWP_STATECHANGED))
     {
         /* if parent is not visible simply toggle WS_VISIBLE and return */
         if (showFlag) WIN_SetStyle( hwnd, WS_VISIBLE, 0 );
         else WIN_SetStyle( hwnd, 0, WS_VISIBLE );
     }
     else
-    {
-        if (style & WS_CHILD)
-        {
-            if (state_change)
-            {
-                /* it appears that Windows always adds an undocumented 0x8000
-                 * flag if the state of a window changes.
-                 */
-                swp |= SWP_STATECHANGED;
-            }
-        }
-
         SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
                       newPos.right, newPos.bottom, LOWORD(swp) );
-    }
 
     if (cmd == SW_HIDE)
     {
@@ -745,7 +744,7 @@ void X11DRV_MapNotify( HWND hwnd, XEvent *event )
         SendMessageW( hwnd, WM_SHOWWINDOW, SW_RESTORE, 0 );
         data->lock_changes++;
         SetWindowPos( hwnd, 0, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
-                      SWP_NOZORDER | SWP_FRAMECHANGED );
+                      SWP_NOZORDER | SWP_FRAMECHANGED | SWP_STATECHANGED );
         data->lock_changes--;
     }
     else WIN_ReleasePtr( win );
@@ -780,7 +779,7 @@ void X11DRV_UnmapNotify( HWND hwnd, XEvent *event )
         SendMessageW( hwnd, WM_SHOWWINDOW, SW_MINIMIZE, 0 );
         data->lock_changes++;
         SetWindowPos( hwnd, 0, 0, 0, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
-                      SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
+                      SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_STATECHANGED );
         data->lock_changes--;
     }
     else WIN_ReleasePtr( win );
-- 
1.4.4.2






More information about the wine-patches mailing list