Author: jimtabor
Date: Thu Jul  5 22:04:47 2012
New Revision: 56839

URL: http://svn.reactos.org/svn/reactos?rev=56839&view=rev
Log:
[Win32SS]
- Paint updates and signaling flags.
- WIP: Implement WM_SYNCPAINT support, for synchronize painting to the 
top-level windows of other threads.
- Tested with wine tests and passes,
  http://www.winehq.org/pipermail/wine-patches/2012-June/114714.html
  http://www.winehq.org/pipermail/wine-patches/2012-June/114715.html

Modified:
    trunk/reactos/win32ss/user/ntuser/painting.c
    trunk/reactos/win32ss/user/user32/windows/defwnd.c

Modified: trunk/reactos/win32ss/user/ntuser/painting.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/painting.c?rev=56839&r1=56838&r2=56839&view=diff
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/painting.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/painting.c [iso-8859-1] Thu Jul  5 
22:04:47 2012
@@ -58,8 +58,18 @@
 BOOL FASTCALL
 IntValidateParent(PWND Child, HRGN hValidateRgn, BOOL Recurse)
 {
-   PWND ParentWnd = Child->spwndParent;
-
+   PWND ParentWnd = Child;
+
+   if (ParentWnd->style & WS_CHILD)
+   {
+      do
+         ParentWnd = ParentWnd->spwndParent;
+      while (ParentWnd->style & WS_CHILD);
+   }
+// Hax out for drawing issues.
+//   if (!(ParentWnd->state & WNDS_SYNCPAINTPENDING)) Recurse = FALSE;
+
+   ParentWnd = Child->spwndParent;
    while (ParentWnd)
    {
       if (ParentWnd->style & WS_CLIPCHILDREN)
@@ -79,6 +89,81 @@
    }
 
    return TRUE;
+}
+
+/*
+  Synchronize painting to the top-level windows of other threads.
+*/
+VOID FASTCALL
+IntSendSyncPaint(PWND Wnd, ULONG Flags)
+{
+   PTHREADINFO ptiCur;
+   PUSER_MESSAGE_QUEUE MessageQueue;
+   PUSER_SENT_MESSAGE Message;
+   PLIST_ENTRY Entry;
+   BOOL bSend = TRUE;
+
+   MessageQueue = Wnd->head.pti->MessageQueue;
+   ptiCur = PsGetCurrentThreadWin32Thread();
+   /*
+      Not the current thread, Wnd is in send Nonclient paint also in send 
erase background and it is visiable.
+   */
+   if ( Wnd->head.pti != ptiCur &&
+        Wnd->state & WNDS_SENDNCPAINT &&
+        Wnd->state & WNDS_SENDERASEBACKGROUND &&
+        Wnd->style & WS_VISIBLE)
+   {
+      // For testing, if you see this, break out the Champagne and have a 
party!
+      ERR("SendSyncPaint Wnd in State!\n");
+      if (!IsListEmpty(&MessageQueue->SentMessagesListHead))
+      {
+         // Scan sent queue messages to see if we received sync paint messages.
+         Entry = MessageQueue->SentMessagesListHead.Flink;
+         Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
+         do
+         {
+            ERR("LOOP it\n");
+            if (Message->Msg.message == WM_SYNCPAINT &&
+                Message->Msg.hwnd == UserHMGetHandle(Wnd))
+            {  // Already received so exit out.
+                ERR("SendSyncPaint Found one in the Sent Msg Queue!\n");
+                bSend = FALSE;
+                break;
+            }
+            Entry = Message->ListEntry.Flink;
+            Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
+         }
+         while (Entry != &MessageQueue->SentMessagesListHead);
+      }
+      if (bSend)
+      {
+         ERR("Sending WM_SYNCPAINT\n");
+         // This message has no parameters. But it does! Pass Flags along.
+         co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_SYNCPAINT, Flags, 0);
+         Wnd->state |= WNDS_SYNCPAINTPENDING;
+      }
+   }
+
+   // Send to all the children if this is the desktop window.
+   if ( Wnd == UserGetDesktopWindow() )
+   {
+      if ( Flags & RDW_ALLCHILDREN ||
+          ( !(Flags & RDW_NOCHILDREN) && Wnd->style & WS_CLIPCHILDREN))
+      {
+         PWND spwndChild = Wnd->spwndChild;
+         while(spwndChild)
+         {
+            if ( spwndChild->style & WS_CHILD &&
+                 spwndChild->head.pti != ptiCur)
+            {
+               spwndChild = spwndChild->spwndNext;
+               continue;
+            }
+            IntSendSyncPaint( spwndChild, Flags );
+            spwndChild = spwndChild->spwndNext;
+         }
+      }
+   }
 }
 
 /**
@@ -166,6 +251,7 @@
       {
          GreDeleteObject(hRgnWindow);
          GreDeleteObject(hRgnNonClient);
+         Window->state &= ~WNDS_UPDATEDIRTY;
          return NULL;
       }
 
@@ -181,6 +267,7 @@
          {
             IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
             GreDeleteObject(Window->hrgnUpdate);
+            Window->state &= ~WNDS_UPDATEDIRTY;
             Window->hrgnUpdate = NULL;
             if (!(Window->state & WNDS_INTERNALPAINT))
                MsqDecPaintCountQueue(Window->head.pti->MessageQueue);
@@ -210,6 +297,8 @@
    HWND hWnd = Wnd->head.h;
    HRGN TempRegion;
 
+   Wnd->state &= ~WNDS_PAINTNOTPROCESSED;
+
    if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
    {
       if (Wnd->hrgnUpdate)
@@ -220,20 +309,26 @@
 
       if (Flags & RDW_UPDATENOW)
       {
-         if (Wnd->hrgnUpdate != NULL ||
-             Wnd->state & WNDS_INTERNALPAINT)
+         if ((Wnd->hrgnUpdate != NULL ||
+              Wnd->state & WNDS_INTERNALPAINT))
          {
             Wnd->state2 |= WNDS2_WMPAINTSENT;
             co_IntSendMessage(hWnd, WM_PAINT, 0, 0);
          }
       }
-      else
+      else if (Wnd->head.pti == PsGetCurrentThreadWin32Thread())
       {
          if (Wnd->state & WNDS_SENDNCPAINT)
          {
             TempRegion = IntGetNCUpdateRgn(Wnd, TRUE);
             Wnd->state &= ~WNDS_SENDNCPAINT;
-            co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)TempRegion, 0);
+            if ( Wnd == GetW32ThreadInfo()->MessageQueue->spwndActive &&
+                !(Wnd->state & WNDS_ACTIVEFRAME))
+            {
+               Wnd->state |= WNDS_ACTIVEFRAME;
+               Wnd->state &= ~WNDS_NONCPAINT;
+            }
+            if (TempRegion) co_IntSendMessage(hWnd, WM_NCPAINT, 
(WPARAM)TempRegion, 0);
          }
 
          if (Wnd->state & WNDS_SENDERASEBACKGROUND)
@@ -254,6 +349,10 @@
             }
          }
       }
+   }
+   else
+   {
+      Wnd->state &= 
~(WNDS_SENDNCPAINT|WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
    }
 
    /*
@@ -306,6 +405,8 @@
 
    TRACE("IntInvalidateWindows start\n");
 
+   Wnd->state |= WNDS_PAINTNOTPROCESSED;
+
    /*
     * If the nonclient is not to be redrawn, clip the region to the client
     * rect
@@ -362,10 +463,14 @@
 
       if (Flags & RDW_INVALIDATE && RgnType != NULLREGION)
       {
+         Wnd->state &= ~WNDS_NONCPAINT;
+
          /* If not the same thread set it dirty. */
          if (Wnd->head.pti != PsGetCurrentThreadWin32Thread())
          {
             Wnd->state |= WNDS_UPDATEDIRTY;
+            if (Wnd->state2 & WNDS2_WMPAINTSENT)
+               Wnd->state2 |= WNDS2_ENDPAINTINVALIDATE;
          }
 
          if (Flags & RDW_FRAME)
@@ -572,6 +677,7 @@
 
    if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
    {
+      if (Flags & RDW_ERASENOW) IntSendSyncPaint(Window, Flags);
       co_IntPaintWindows(Window, Flags, FALSE);
    }
 
@@ -853,7 +959,7 @@
       co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0);
       if (hRgn != HRGN_WINDOW && hRgn != NULL && GreIsHandleValid(hRgn))
       {
-         /* NOTE: The region can already by deleted! */
+         /* NOTE: The region can already be deleted! */
          GreDeleteObject(hRgn);
       }
    }
@@ -928,7 +1034,7 @@
 CLEANUP:
    if (Window) UserDerefObjectCo(Window);
 
-   TRACE("Leave NtUserBeginPaint, ret=%i\n",_ret_);
+   TRACE("Leave NtUserBeginPaint, ret=%p\n",_ret_);
    UserLeave();
    END_CLEANUP;
 
@@ -1869,11 +1975,13 @@
    return Ret;
 }
 
+BOOL FASTCALL IntPaintDesktop(HDC hDC);
+
 INT
 FASTCALL
 UserRealizePalette(HDC hdc)
 {
-  HWND hWnd;
+  HWND hWnd, hWndDesktop;
   DWORD Ret;
 
   Ret = IntGdiRealizePalette(hdc);
@@ -1882,6 +1990,15 @@
       hWnd = IntWindowFromDC(hdc);
       if (hWnd) // Send broadcast if dc is associated with a window.
       {  // FYI: Thread locked in CallOneParam.
+         hWndDesktop = IntGetDesktopWindow();
+         if ( hWndDesktop != hWnd )
+         {
+            PWND pWnd = UserGetWindowObject(hWndDesktop);
+            ERR("RealizePalette Desktop.");
+            hdc = UserGetWindowDC(pWnd);
+            IntPaintDesktop(hdc);
+            UserReleaseDC(pWnd,hdc,FALSE);            
+         }
          UserSendNotifyMessage((HWND)HWND_BROADCAST, WM_PALETTECHANGED, 
(WPARAM)hWnd, 0);
       }
   }

Modified: trunk/reactos/win32ss/user/user32/windows/defwnd.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/user32/windows/defwnd.c?rev=56839&r1=56838&r2=56839&view=diff
==============================================================================
--- trunk/reactos/win32ss/user/user32/windows/defwnd.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/user32/windows/defwnd.c [iso-8859-1] Thu Jul  5 
22:04:47 2012
@@ -1209,13 +1209,20 @@
         case WM_PAINT:
         {
             PAINTSTRUCT Ps;
+
+            /* If already in Paint and Client area is not empty just return. */
+            if (pWnd->state2 & WNDS2_STARTPAINT && 
!IsRectEmpty(&pWnd->rcClient))
+            {
+               ERR("In Paint and Client area is not empty!\n");
+               return 0;
+            }
+
             HDC hDC = BeginPaint(hWnd, &Ps);
             if (hDC)
             {
                 HICON hIcon;
 
-                if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
-                    (hIcon = (HICON)GetClassLongPtrW(hWnd, GCL_HICON)) != NULL)
+                if (IsIconic(hWnd) && ((hIcon = (HICON)GetClassLongPtrW( hWnd, 
GCLP_HICON))))
                 {
                     RECT ClientRect;
                     INT x, y;


Reply via email to