https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2161dd85dc743462916487366783389633a5a8f2

commit 2161dd85dc743462916487366783389633a5a8f2
Author:     jimtabor <[email protected]>
AuthorDate: Mon May 13 11:31:58 2019 -0500
Commit:     jimtabor <[email protected]>
CommitDate: Mon May 13 11:31:58 2019 -0500

    [NtUser] Fix Paint Messages
    
    This is a HACK for forcing painting of non client areas. Paint code
    seems very restricted.
    
    See CORE-7166 & CORE-15934.
---
 win32ss/user/ntuser/winpos.c | 84 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 80 insertions(+), 4 deletions(-)

diff --git a/win32ss/user/ntuser/winpos.c b/win32ss/user/ntuser/winpos.c
index 6c54f3c266..0eddff51cc 100644
--- a/win32ss/user/ntuser/winpos.c
+++ b/win32ss/user/ntuser/winpos.c
@@ -1653,6 +1653,68 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd)
    return TRUE;
 }
 
+//
+// This is a NC HACK fix for forcing painting of non client areas.
+// Further troubleshooting in painting.c is required to remove this hack.
+// See CORE-7166 & CORE-15934
+//
+VOID
+ForceNCPaintErase(PWND Wnd, HRGN hRgn, PREGION pRgn)
+{
+   HDC hDC;
+   PREGION RgnUpdate;
+   UINT RgnType;
+   BOOL Create = FALSE;
+
+   if (Wnd->hrgnUpdate == NULL)
+   {
+       Wnd->hrgnUpdate = NtGdiCreateRectRgn(0, 0, 0, 0);
+       IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_PUBLIC);
+       Create = TRUE;
+   }
+
+   if (Wnd->hrgnUpdate != HRGN_WINDOW)
+   {
+       RgnUpdate = REGION_LockRgn(Wnd->hrgnUpdate);
+       if (RgnUpdate)
+       {
+           RgnType = IntGdiCombineRgn(RgnUpdate, RgnUpdate, pRgn, RGN_OR);
+           REGION_UnlockRgn(RgnUpdate);
+           if (RgnType == NULLREGION)
+           {
+               IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
+               GreDeleteObject(Wnd->hrgnUpdate);
+               Wnd->hrgnUpdate = NULL;
+               Create = FALSE;
+           }
+       }
+   }
+
+   IntSendNCPaint( Wnd, hRgn ); // Region can be deleted by the application.
+
+   if (Wnd->hrgnUpdate)
+   {
+       hDC = UserGetDCEx( Wnd,
+                          Wnd->hrgnUpdate,
+                          
DCX_CACHE|DCX_USESTYLE|DCX_INTERSECTRGN|DCX_KEEPCLIPRGN);
+
+      Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
+      // Kill the loop, so Clear before we send.
+      if (!co_IntSendMessage(UserHMGetHandle(Wnd), WM_ERASEBKGND, (WPARAM)hDC, 
0))
+      {
+          Wnd->state |= (WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
+      }
+      UserReleaseDC(Wnd, hDC, FALSE);
+   }
+
+   if (Create)
+   {
+      IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
+      GreDeleteObject(Wnd->hrgnUpdate);
+      Wnd->hrgnUpdate = NULL;
+   }
+}
+
 /* x and y are always screen relative */
 BOOLEAN FASTCALL
 co_WinPosSetWindowPos(
@@ -1862,6 +1924,14 @@ co_WinPosSetWindowPos(
 
    DceResetActiveDCEs(Window); // For WS_VISIBLE changes.
 
+   // Change or update, set send non-client paint flag.
+   if ( Window->style & WS_VISIBLE &&
+       (WinPos.flags & SWP_STATECHANGED || (!(Window->state2 & 
WNDS2_WIN31COMPAT) && WinPos.flags & SWP_NOREDRAW ) ) )
+   {
+      TRACE("Set WNDS_SENDNCPAINT %p\n",Window);
+      Window->state |= WNDS_SENDNCPAINT;
+   }
+
    if (!(WinPos.flags & SWP_NOREDRAW))
    {
       /* Determine the new visible region */
@@ -2018,7 +2088,7 @@ 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
+             else if ( RgnType != ERROR && RgnType == NULLREGION ) // Must be 
the same. See CORE-7166 & CORE-15934, NC HACK fix.
              {
                 if ( !PosChanged &&
                      !(WinPos.flags & SWP_DEFERERASE) &&
@@ -2035,7 +2105,13 @@ co_WinPosSetWindowPos(
 
                     if ( !(pwnd->style & WS_CHILD) )
                     {
-                        IntSendNCPaint(pwnd, HRGN_WINDOW); // Paint the whole 
frame.
+                        HRGN DcRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
+                        PREGION DcRgnObj = REGION_LockRgn(DcRgn);
+                        TRACE("SWP_FRAMECHANGED win %p hRgn %p\n",pwnd, DcRgn);
+                        IntGdiCombineRgn(DcRgnObj, VisBefore, NULL, RGN_COPY);
+                        REGION_UnlockRgn(DcRgnObj);
+                        ForceNCPaintErase(pwnd, DcRgn, DcRgnObj);
+                        GreDeleteObject(DcRgn);
                     }
                 }
              }
@@ -2106,8 +2182,8 @@ co_WinPosSetWindowPos(
        PWND Parent = Window->spwndParent;
        if ( !(Window->style & WS_CHILD) && (Parent) && (Parent->style & 
WS_CLIPCHILDREN))
        {
-           TRACE("SWP_FRAMECHANGED Parent WS_CLIPCHILDREN\n");
-           UserSyncAndPaintWindows( Parent, RDW_CLIPCHILDREN);
+           TRACE("SWP_FRAMECHANGED Parent %p WS_CLIPCHILDREN 
%p\n",Parent,Window);
+           UserSyncAndPaintWindows( Parent, RDW_CLIPCHILDREN); // NC should 
redraw here, see NC HACK fix.
        }
    }
 

Reply via email to