[NtUser] Fix Theme Non Client Painting.
[reactos.git] / win32ss / user / ntuser / winpos.c
index d1f975e..6c54f3c 100644 (file)
@@ -888,14 +888,14 @@ UserGetWindowBorders(DWORD Style, DWORD ExStyle, SIZE *Size, BOOL WithClient)
 
    if (UserHasWindowEdge(Style, ExStyle))
       Border += 2;
-   else if (ExStyle & WS_EX_STATICEDGE)
-      Border += 1;
+   else if ((ExStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE)
+      Border += 1; /* for the outer frame always present */
    if ((ExStyle & WS_EX_CLIENTEDGE) && WithClient)
       Border += 2;
    if (Style & WS_CAPTION || ExStyle & WS_EX_DLGMODALFRAME)
-      Border ++;
+      Border ++; /* The other border */
    Size->cx = Size->cy = Border;
-   if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))
+   if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE)) /* The resize border */
    {
       Size->cx += UserGetSystemMetrics(SM_CXFRAME) - UserGetSystemMetrics(SM_CXDLGFRAME);
       Size->cy += UserGetSystemMetrics(SM_CYFRAME) - UserGetSystemMetrics(SM_CYDLGFRAME);
@@ -904,32 +904,27 @@ UserGetWindowBorders(DWORD Style, DWORD ExStyle, SIZE *Size, BOOL WithClient)
    Size->cy *= UserGetSystemMetrics(SM_CYBORDER);
 }
 
-BOOL WINAPI
-UserAdjustWindowRectEx(LPRECT lpRect,
-                       DWORD dwStyle,
-                       BOOL bMenu,
-                       DWORD dwExStyle)
+//
+// Fix CORE-5177
+// See winetests:user32:win.c:wine_AdjustWindowRectEx, 
+// Simplified version.
+//
+DWORD IntGetWindowBorders(DWORD Style, DWORD ExStyle)
 {
-   SIZE BorderSize;
+    DWORD adjust = 0;
 
-   if (bMenu)
-   {
-      lpRect->top -= UserGetSystemMetrics(SM_CYMENU);
-   }
-   if ((dwStyle & WS_CAPTION) == WS_CAPTION)
-   {
-      if (dwExStyle & WS_EX_TOOLWINDOW)
-         lpRect->top -= UserGetSystemMetrics(SM_CYSMCAPTION);
-      else
-         lpRect->top -= UserGetSystemMetrics(SM_CYCAPTION);
-   }
-   UserGetWindowBorders(dwStyle, dwExStyle, &BorderSize, TRUE);
-   RECTL_vInflateRect(
-      lpRect,
-      BorderSize.cx,
-      BorderSize.cy);
+    if ( ExStyle & WS_EX_WINDOWEDGE )      // 1st
+        adjust = 2; /* outer */
+    else if ( ExStyle & WS_EX_STATICEDGE ) // 2nd
+        adjust = 1; /* for the outer frame always present */
 
-   return TRUE;
+    if (ExStyle & WS_EX_CLIENTEDGE)
+       adjust += 2;
+
+    if ( Style & WS_CAPTION || ExStyle & WS_EX_DLGMODALFRAME )
+        adjust++; /* The other border */
+
+    return adjust;
 }
 
 UINT FASTCALL
@@ -943,6 +938,7 @@ co_WinPosGetMinMaxInfo(PWND Window, POINT* MaxSize, POINT* MaxPos,
     LONG adjustedStyle;
     LONG exstyle = Window->ExStyle;
     RECT rc;
+    DWORD adjust;
 
     ASSERT_REFS_CO(Window);
 
@@ -957,9 +953,26 @@ co_WinPosGetMinMaxInfo(PWND Window, POINT* MaxSize, POINT* MaxPos,
     else
         adjustedStyle = style;
 
-    if(Window->spwndParent)
+    if (Window->spwndParent)
         IntGetClientRect(Window->spwndParent, &rc);
-    UserAdjustWindowRectEx(&rc, adjustedStyle, ((style & WS_POPUP) && Window->IDMenu), exstyle);
+
+    adjust = IntGetWindowBorders(adjustedStyle, exstyle);
+
+    // Handle special case while maximized. CORE-15893
+    if ((adjustedStyle & WS_THICKFRAME) && !(adjustedStyle & WS_CHILD) && !(adjustedStyle & WS_MINIMIZE))
+         adjust += 2;
+
+    xinc = yinc = adjust;
+
+    if ((adjustedStyle & WS_THICKFRAME) && (adjustedStyle & WS_CHILD) && !(adjustedStyle & WS_MINIMIZE))
+    {
+        xinc += UserGetSystemMetrics(SM_CXFRAME) - UserGetSystemMetrics(SM_CXDLGFRAME);
+        yinc += UserGetSystemMetrics(SM_CYFRAME) - UserGetSystemMetrics(SM_CYDLGFRAME);
+    }
+
+    RECTL_vInflateRect( &rc,
+                        xinc * UserGetSystemMetrics(SM_CXBORDER),
+                        yinc * UserGetSystemMetrics(SM_CYBORDER) );
 
     xinc = -rc.left;
     yinc = -rc.top;
@@ -981,7 +994,7 @@ co_WinPosGetMinMaxInfo(PWND Window, POINT* MaxSize, POINT* MaxPos,
     MinMax.ptMaxPosition.x = -xinc;
     MinMax.ptMaxPosition.y = -yinc;
 
-   if (!EMPTYPOINT(Window->InternalPos.MaxPos)) MinMax.ptMaxPosition = Window->InternalPos.MaxPos;
+    if (!EMPTYPOINT(Window->InternalPos.MaxPos)) MinMax.ptMaxPosition = Window->InternalPos.MaxPos;
 
     co_IntSendMessage(Window->head.h, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax);
 
@@ -995,7 +1008,7 @@ co_WinPosGetMinMaxInfo(PWND Window, POINT* MaxSize, POINT* MaxPos,
         if (style & WS_MAXIMIZEBOX)
         {
             if ((style & WS_CAPTION) == WS_CAPTION || !(style & (WS_CHILD | WS_POPUP)))
-                rc_work = monitor->rcWork;
+               rc_work = monitor->rcWork;
         }
 
         if (MinMax.ptMaxSize.x == UserGetSystemMetrics(SM_CXSCREEN) + 2 * xinc &&
@@ -1011,43 +1024,37 @@ co_WinPosGetMinMaxInfo(PWND Window, POINT* MaxSize, POINT* MaxPos,
         }
         if (MinMax.ptMaxSize.x >= (monitor->rcMonitor.right - monitor->rcMonitor.left) &&
             MinMax.ptMaxSize.y >= (monitor->rcMonitor.bottom - monitor->rcMonitor.top) )
+        {
             Window->state |= WNDS_MAXIMIZESTOMONITOR;
+        }
         else
             Window->state &= ~WNDS_MAXIMIZESTOMONITOR;
     }
 
 
-   MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x,
-                                 MinMax.ptMinTrackSize.x);
-   MinMax.ptMaxTrackSize.y = max(MinMax.ptMaxTrackSize.y,
-                                 MinMax.ptMinTrackSize.y);
+    MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x,
+                                  MinMax.ptMinTrackSize.x);
+    MinMax.ptMaxTrackSize.y = max(MinMax.ptMaxTrackSize.y,
+                                  MinMax.ptMinTrackSize.y);
 
-   if (MaxSize)
-      *MaxSize = MinMax.ptMaxSize;
-   if (MaxPos)
-      *MaxPos = MinMax.ptMaxPosition;
-   if (MinTrack)
-      *MinTrack = MinMax.ptMinTrackSize;
-   if (MaxTrack)
-      *MaxTrack = MinMax.ptMaxTrackSize;
+    if (MaxSize)
+       *MaxSize = MinMax.ptMaxSize;
+    if (MaxPos)
+       *MaxPos = MinMax.ptMaxPosition;
+    if (MinTrack)
+       *MinTrack = MinMax.ptMinTrackSize;
+    if (MaxTrack)
+       *MaxTrack = MinMax.ptMaxTrackSize;
 
-   return 0; // FIXME: What does it return?
+    return 0; // FIXME: What does it return? Wine returns MINMAXINFO.
 }
 
 static
 BOOL
 IntValidateParent(PWND Child, PREGION ValidateRgn)
 {
-   PWND ParentWnd = Child;
+   PWND ParentWnd = Child->spwndParent;
 
-   if (ParentWnd->style & WS_CHILD)
-   {
-      do
-         ParentWnd = ParentWnd->spwndParent;
-      while (ParentWnd->style & WS_CHILD);
-   }
-
-   ParentWnd = Child->spwndParent;
    while (ParentWnd)
    {
       if (ParentWnd->style & WS_CLIPCHILDREN)
@@ -1883,8 +1890,7 @@ co_WinPosSetWindowPos(
              VisAfter != NULL &&
             !(WinPos.flags & SWP_NOCOPYBITS) &&
             ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)) &&
-            !(Window->ExStyle & WS_EX_TRANSPARENT) ) || 
-            ( !PosChanged && (WinPos.flags & SWP_FRAMECHANGED) && VisBefore) )
+            !(Window->ExStyle & WS_EX_TRANSPARENT) ) )
       {
 
          /*
@@ -1950,7 +1956,7 @@ co_WinPosSetWindowPos(
             REGION_UnlockRgn(DcRgnObj);
             Dc = UserGetDCEx( Window,
                               DcRgn,
-                              DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN);
+                              DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN); // DCX_WINDOW will set first, go read WinDC.c.
             NtGdiBitBlt( Dc,
                          CopyRect.left, CopyRect.top,
                          CopyRect.right - CopyRect.left,
@@ -1971,20 +1977,8 @@ co_WinPosSetWindowPos(
       {
          CopyRgn = NULL;
       }
-#if 0
-      /////// Fixes NoPopup tests but breaks msg_paint tests.
-      if ( !PosChanged && (WinPos.flags & SWP_FRAMECHANGED) && VisBefore)
-      {
-         PWND Parent = Window->spwndParent;
-         ERR("SWP_FRAMECHANGED no chg\n");
-         if ( !(Window->style & WS_CHILD) && (Parent) && (Parent->style & WS_CLIPCHILDREN))
-         {
-            ERR("SWP_FRAMECHANGED Parent WS_CLIPCHILDREN\n");
-            //IntInvalidateWindows( Window, VisBefore, /*RDW_ERASE |*/ RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
-         }
-      }
-#endif
-      /* We need to redraw what wasn't visible before */
+
+      /* We need to redraw what wasn't visible before or force a redraw */
       if (VisAfter != NULL)
       {
          PREGION DirtyRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
@@ -1999,7 +1993,7 @@ co_WinPosSetWindowPos(
                 RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY);
              }
 
-             if (RgnType != ERROR && RgnType != NULLREGION)
+             if (RgnType != ERROR && RgnType != NULLREGION) // Regions moved.
              {
             /* old code
                 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
@@ -2024,6 +2018,27 @@ co_WinPosSetWindowPos(
                    IntInvalidateWindows( Window, DirtyRgn, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
                 }
              }
+             else if ( RgnType != ERROR && RgnType == NULLREGION ) // Must be the same. See CORE-7166 & CORE-15934
+             {
+                if ( !PosChanged &&
+                     !(WinPos.flags & SWP_DEFERERASE) &&
+                      (WinPos.flags & SWP_FRAMECHANGED) )
+                {
+                    PWND pwnd = Window;
+                    PWND Parent = Window->spwndParent;
+
+                    if ( pwnd->style & WS_CHILD ) // Fix ProgMan menu bar drawing.
+                    {
+                        TRACE("SWP_FRAMECHANGED win child %p Parent %p\n",pwnd,Parent);
+                        pwnd = Parent ? Parent : pwnd;
+                    }
+
+                    if ( !(pwnd->style & WS_CHILD) )
+                    {
+                        IntSendNCPaint(pwnd, HRGN_WINDOW); // Paint the whole frame.
+                    }
+                }
+             }
              REGION_Delete(DirtyRgn);
          }
       }
@@ -2034,7 +2049,7 @@ co_WinPosSetWindowPos(
       }
 
       /* Expose what was covered before but not covered anymore */
-      if (VisBefore != NULL)
+      if ( VisBefore != NULL )
       {
          PREGION ExposedRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
          if (ExposedRgn)
@@ -2044,7 +2059,7 @@ co_WinPosSetWindowPos(
                                OldWindowRect.left - NewWindowRect.left,
                                OldWindowRect.top  - NewWindowRect.top);
 
-             if (VisAfter != NULL)
+             if ( VisAfter != NULL )
                 RgnType = IntGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
 
              if (RgnType != ERROR && RgnType != NULLREGION)
@@ -2275,11 +2290,11 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
 
                WinPosFindIconPos(Wnd, &wpl.ptMinPosition);
 
-               /*if (!(old_style & WS_MINIMIZE))
+               if (!(old_style & WS_MINIMIZE))
                {
                   SwpFlags |= SWP_STATECHANGED;
                   IntShowOwnedPopups(Wnd, FALSE);
-               }*/
+               }
 
                RECTL_vSetRect(NewPos, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
                              wpl.ptMinPosition.x + UserGetSystemMetrics(SM_CXMINIMIZED),
@@ -2325,7 +2340,7 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
                old_style = IntSetStyle( Wnd, 0, WS_MINIMIZE | WS_MAXIMIZE );
                if (old_style & WS_MINIMIZE)
                {
-                  //IntShowOwnedPopups(Wnd, TRUE);
+                  IntShowOwnedPopups(Wnd, TRUE);
 
                   if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED)
                   {
@@ -3326,7 +3341,7 @@ NtUserSetWindowPos(
       RETURN(FALSE);
    }
 
-   if ( hWndInsertAfter &&
+   if ( hWndInsertAfter != HWND_TOP &&
         hWndInsertAfter != HWND_BOTTOM &&
         hWndInsertAfter != HWND_TOPMOST &&
         hWndInsertAfter != HWND_NOTOPMOST )