[Win32SS]
[reactos.git] / reactos / win32ss / user / ntuser / painting.c
index 1a8d63b..43e8d88 100644 (file)
@@ -9,9 +9,6 @@
 #include <win32k.h>
 DBG_DEFAULT_CHANNEL(UserPainting);
 
-#define RDW_CLIPCHILDREN  4096
-#define RDW_NOUPDATEDIRTY 32768
-
 /* PRIVATE FUNCTIONS **********************************************************/
 
 /**
@@ -510,7 +507,7 @@ co_IntUpdateWindows(PWND Wnd, ULONG Flags, BOOL Recurse)
 {
    HWND hWnd = Wnd->head.h;
 
-   if ((Wnd->hrgnUpdate != NULL || Wnd->state & WNDS_INTERNALPAINT))
+   if ( Wnd->hrgnUpdate != NULL || Wnd->state & WNDS_INTERNALPAINT )
    {
       if (Wnd->hrgnUpdate)
       {
@@ -573,7 +570,7 @@ co_IntUpdateWindows(PWND Wnd, ULONG Flags, BOOL Recurse)
             if (Next) continue;
          }
 
-         if ( Child->style & WS_VISIBLE)
+         if (Child->style & WS_VISIBLE)
          {
              USER_REFERENCE_ENTRY Ref;
              UserRefObjectCo(Child, &Ref);
@@ -1004,6 +1001,106 @@ co_UserRedrawWindow(
    return TRUE;
 }
 
+VOID FASTCALL
+PaintSuspendedWindow(PWND pwnd, HRGN hrgnOrig)
+{
+   if (pwnd->hrgnUpdate)
+   {
+      HDC hDC;
+      INT Flags = DC_NC|DC_NOSENDMSG;
+      HRGN hrgnTemp;
+      RECT Rect;
+      INT type;
+      PREGION prgn;
+
+      if (pwnd->hrgnUpdate > HRGN_WINDOW)
+      {
+         hrgnTemp = NtGdiCreateRectRgn(0, 0, 0, 0);
+         type = NtGdiCombineRgn( hrgnTemp, pwnd->hrgnUpdate, 0, RGN_COPY);
+         if (type == ERROR)
+         {
+            GreDeleteObject(hrgnTemp);
+            hrgnTemp = HRGN_WINDOW;
+         }
+      }
+      else
+      {
+         hrgnTemp = GreCreateRectRgnIndirect(&pwnd->rcWindow);
+      }
+
+      if ( hrgnOrig &&
+           hrgnTemp > HRGN_WINDOW &&
+           NtGdiCombineRgn(hrgnTemp, hrgnTemp, hrgnOrig, RGN_AND) == NULLREGION)
+      {
+         GreDeleteObject(hrgnTemp);
+         return;
+      }
+
+      hDC = UserGetDCEx(pwnd, hrgnTemp, DCX_WINDOW|DCX_INTERSECTRGN|DCX_USESTYLE|DCX_KEEPCLIPRGN);
+
+      Rect = pwnd->rcWindow;
+      RECTL_vOffsetRect(&Rect, -pwnd->rcWindow.left, -pwnd->rcWindow.top);
+
+      // Clear out client area!
+      FillRect(hDC, &Rect, IntGetSysColorBrush(COLOR_WINDOW));
+
+      NC_DoNCPaint(pwnd, hDC, Flags); // Redraw without MENUs.
+
+      UserReleaseDC(pwnd, hDC, FALSE);
+
+      prgn = REGION_LockRgn(hrgnTemp);
+      IntInvalidateWindows(pwnd, prgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ALLCHILDREN);
+      REGION_UnlockRgn(prgn);
+
+      // Set updates for this window.
+      pwnd->state |= WNDS_SENDNCPAINT|WNDS_SENDERASEBACKGROUND|WNDS_UPDATEDIRTY;
+
+      // DCX_KEEPCLIPRGN is set. Check it anyway.
+      if (hrgnTemp > HRGN_WINDOW && GreIsHandleValid(hrgnTemp)) GreDeleteObject(hrgnTemp);
+   }
+}
+
+VOID FASTCALL
+UpdateTheadChildren(PWND pWnd, HRGN hRgn)
+{
+   PaintSuspendedWindow( pWnd, hRgn );
+
+   if (!(pWnd->style & WS_CLIPCHILDREN))
+      return;
+
+   pWnd = pWnd->spwndChild; // invalidate children if any.
+   while (pWnd)
+   {
+      UpdateTheadChildren( pWnd, hRgn );
+      pWnd = pWnd->spwndNext;
+   }
+}
+
+VOID FASTCALL
+UpdateThreadWindows(PWND pWnd, PTHREADINFO pti, HRGN hRgn)
+{
+   PWND pwndTemp;
+
+   for ( pwndTemp = pWnd;
+         pwndTemp;
+         pwndTemp = pwndTemp->spwndNext )
+   {
+      if (pwndTemp->head.pti == pti)
+      {
+          UserUpdateWindows(pwndTemp, RDW_ALLCHILDREN);
+      }
+      else
+      {
+          if (IsThreadSuspended(pwndTemp->head.pti))
+          {
+             UpdateTheadChildren(pwndTemp, hRgn);
+          }
+          else
+             UserUpdateWindows(pwndTemp, RDW_ALLCHILDREN);
+      }
+   }
+}
+
 BOOL FASTCALL
 IntIsWindowDirty(PWND Wnd)
 {
@@ -1060,6 +1157,16 @@ IntFindWindowToRepaint(PWND Window, PTHREADINFO Thread)
    return Window;
 }
 
+//
+// Internal painting of windows.
+//
+VOID FASTCALL
+IntPaintWindow( PWND Window )
+{
+   // Handle normal painting.
+   co_IntPaintWindows( Window, RDW_NOCHILDREN, FALSE );
+}
+
 BOOL FASTCALL
 IntGetPaintMessage(
    PWND Window,
@@ -1189,7 +1296,7 @@ IntFlashWindowEx(PWND pWnd, PFLASHWINFO pfwi)
 
    ASSERT(pfwi);
 
-   FlashState = (DWORD)UserGetProp(pWnd, AtomFlashWndState);
+   FlashState = (DWORD)UserGetProp(pWnd, AtomFlashWndState, TRUE);
 
    if (FlashState == FLASHW_FINISHED)
    {
@@ -1227,7 +1334,7 @@ IntFlashWindowEx(PWND pWnd, PFLASHWINFO pfwi)
       // Set previous window state.
       Ret = !!(FlashState & FLASHW_ACTIVE);
 
-      if ( pfwi->dwFlags & FLASHW_TIMERNOFG &&
+      if ( (pfwi->dwFlags & FLASHW_TIMERNOFG) == FLASHW_TIMERNOFG &&
            gpqForeground == pWnd->head.pti->MessageQueue )
       {
           // Flashing until foreground, set this to Stop.
@@ -1267,7 +1374,7 @@ IntFlashWindowEx(PWND pWnd, PFLASHWINFO pfwi)
          IntKillTimer(pWnd, ID_EVENT_SYSTIMER_FLASHWIN, TRUE);
       }
 
-      IntRemoveProp(pWnd, AtomFlashWndState);
+      UserRemoveProp(pWnd, AtomFlashWndState, TRUE);
    }
    else
    {  // Have a count and started, set timer.
@@ -1305,7 +1412,7 @@ IntFlashWindowEx(PWND pWnd, PFLASHWINFO pfwi)
          FlashState ^= (FlashState ^ pfwi->dwFlags) & (FLASHW_MASK & ~FLASHW_TIMER);
       }
       FlashState = MAKELONG(LOWORD(FlashState),uCount);
-      IntSetProp(pWnd, AtomFlashWndState, (HANDLE) FlashState);
+      UserSetProp(pWnd, AtomFlashWndState, (HANDLE)FlashState, TRUE);
    }
    return Ret;
 }
@@ -1536,30 +1643,27 @@ NtUserFlashWindowEx(IN PFLASHWINFO pfwi)
 {
    PWND pWnd;
    FLASHWINFO finfo = {0};
-   BOOL Ret = TRUE;
+   BOOL Ret = FALSE;
 
    UserEnterExclusive();
 
    _SEH2_TRY
    {
-      ProbeForRead(pfwi, sizeof(FLASHWINFO), sizeof(ULONG));
+      ProbeForRead(pfwi, sizeof(FLASHWINFO), 1);
       RtlCopyMemory(&finfo, pfwi, sizeof(FLASHWINFO));
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
       SetLastNtError(_SEH2_GetExceptionCode());
-      Ret = FALSE;
+      _SEH2_YIELD(goto Exit);
    }
    _SEH2_END
 
-   if (!Ret) goto Exit;
-
-   if (!( pWnd = (PWND)UserGetObject(gHandleTable, finfo.hwnd, TYPE_WINDOW)) ||
+   if (!( pWnd = ValidateHwndNoErr(finfo.hwnd)) ||
         finfo.cbSize != sizeof(FLASHWINFO) ||
         finfo.dwFlags & ~(FLASHW_ALL|FLASHW_TIMER|FLASHW_TIMERNOFG) )
    {
       EngSetLastError(ERROR_INVALID_PARAMETER);
-      Ret = FALSE;
       goto Exit;
    }
 
@@ -1631,7 +1735,7 @@ co_UserGetUpdateRgn(PWND Window, HRGN hRgn, BOOL bErase)
       {
          if (hrgnTemp) GreDeleteObject(hrgnTemp);
          NtGdiSetRectRgn(hRgn, 0, 0, 0, 0);
-         return NULLREGION;
+         return RegionType;
       }
 
       if (Window != UserGetDesktopWindow()) // Window->fnid == FNID_DESKTOP
@@ -1684,9 +1788,23 @@ co_UserGetUpdateRect(PWND Window, PRECT pRect, BOOL bErase)
 
       if (IntIntersectWithParents(Window, pRect))
       {
-         RECTL_vOffsetRect(pRect,
-                          -Window->rcClient.left,
-                          -Window->rcClient.top);
+         if (Window != UserGetDesktopWindow()) // Window->fnid == FNID_DESKTOP
+         {
+            RECTL_vOffsetRect(pRect,
+                              -Window->rcClient.left,
+                              -Window->rcClient.top);
+         }
+         if (Window->pcls->style & CS_OWNDC)
+         {
+            HDC hdc;
+            //DWORD layout;
+            hdc = UserGetDCEx(Window, NULL, DCX_USESTYLE);
+            //layout = NtGdiSetLayout(hdc, -1, 0);
+            //IntMapWindowPoints( 0, Window, (LPPOINT)pRect, 2 );
+            GreDPtoLP( hdc, (LPPOINT)pRect, 2 );
+            //NtGdiSetLayout(hdc, -1, layout);
+            UserReleaseDC(Window, hdc, FALSE);
+         }
       }
       else
       {
@@ -1887,7 +2005,7 @@ UserDrawCaptionText(
    TRACE("UserDrawCaptionText: %wZ\n", Text);
 
    nclm.cbSize = sizeof(nclm);
-   if(!UserSystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &nclm, 0))
+   if (!UserSystemParametersInfo(SPI_GETNONCLIENTMETRICS, nclm.cbSize, &nclm, 0))
    {
       ERR("UserSystemParametersInfo() failed!\n");
       return FALSE;
@@ -1990,14 +2108,14 @@ BOOL UserDrawCaption(
 
    RECTL_vMakeWellOrdered(lpRc);
 
+   /* Determine whether the icon needs to be displayed */
    if (!hIcon && pWnd != NULL)
    {
-     HasIcon = (uFlags & DC_ICON) && (pWnd->style & WS_SYSMENU)
-        && !(uFlags & DC_SMALLCAP) && !(pWnd->ExStyle & WS_EX_DLGMODALFRAME)
-        && !(pWnd->ExStyle & WS_EX_TOOLWINDOW);
+     HasIcon = (uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP) &&
+               (pWnd->style & WS_SYSMENU) && !(pWnd->ExStyle & WS_EX_TOOLWINDOW);
    }
    else
-     HasIcon = (hIcon != 0);
+     HasIcon = (hIcon != NULL);
 
    // Draw the caption background
    if((uFlags & DC_GRADIENT) && !(uFlags & DC_INBUTTON))
@@ -2081,7 +2199,7 @@ BOOL UserDrawCaption(
          LONG cx = UserGetSystemMetrics(SM_CXSMICON);
          LONG cy = UserGetSystemMetrics(SM_CYSMICON);
          LONG x = Rect.left - cx/2 + 1 + (Rect.bottom - Rect.top)/2; // this is really what Window does
-         LONG y = (Rect.top + Rect.bottom)/2 - cy/2; // center
+         LONG y = (Rect.top + Rect.bottom - cy)/2; // center
          UserDrawIconEx(hDc, x, y, pIcon, cx, cy, 0, NULL, DI_NORMAL);
          UserDereferenceObject(pIcon);
       }