Delay WM_NCPAINT message until the "painter's algorithm" kicks in.

diff --git a/include/win.h b/include/win.h
index 4b0c708..637b90c 100644
--- a/include/win.h
+++ b/include/win.h
@@ -49,6 +49,7 @@
 #define RDW_EX_DELETEHRGN	0x0002
 #define RDW_EX_XYWINDOW		0x0004
 #define RDW_EX_TOPFRAME		0x0010
+#define RDW_EX_DELAY_NCPAINT    0x0020
 
 struct tagCLASS;
 struct tagDCE;
@@ -163,6 +164,8 @@
 #define UNC_ENTIRE		0x0002
 #define UNC_REGION		0x0004
 #define UNC_UPDATE		0x0008
+#define UNC_DELAY_NCPAINT       0x0010
+#define UNC_IN_BEGINPAINT       0x0020
 
   /* Window functions */
 extern void   WIN_Init( void );
diff --git a/windows/painting.c b/windows/painting.c
index 569c3bf..35bb804 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -28,6 +28,84 @@
 
 
 /***********************************************************************
+ *           WIN_HaveToDelayNCPAINT
+ *
+ * Currently, in the Wine painting mechanism, the WM_NCPAINT message
+ * is generated as soon as a region intersecting the non-client area 
+ * of a window is invalidated.
+ *
+ * This technique will work fine for all windows whose parents
+ * have the WS_CLIPCHILDREN style. When the parents have that style,
+ * they are not going to override the contents of their children.
+ * However, when the parent doesn't have that style, Windows relies
+ * on a "painter's algorithm" to display the contents of the windows.
+ * That is, windows are painted from back to front. This includes the
+ * non-client area.
+ *
+ * This method looks at the current state of a window to determine
+ * if the sending of the WM_NCPAINT message should be delayed until 
+ * the BeginPaint call.
+ *
+ * PARAMS:
+ *   wndPtr   - A Locked window pointer to the window we're
+ *              examining.
+ *   uncFlags - This is the flag passed to the WIN_UpdateNCRgn
+ *              function. This is a shortcut for the cases when
+ *              we already know when to avoid scanning all the
+ *              parents of a window. If you already know that this
+ *              window's NCPAINT should be delayed, set the 
+ *              UNC_DELAY_NCPAINT flag for this parameter. 
+ *
+ *              This shortcut behavior is implemented in the
+ *              RDW_Paint() method.
+ * 
+ */
+static BOOL WIN_HaveToDelayNCPAINT(
+  WND* wndPtr, 
+  UINT uncFlags)
+{
+  WND* parentWnd = NULL;
+
+  /*
+   * Test the shortcut first. (duh)
+   */
+  if (uncFlags & UNC_DELAY_NCPAINT)
+    return TRUE;
+
+  /*
+   * The UNC_IN_BEGINPAINT flag is set in the BeginPaint
+   * method only. This is another shortcut to avoid going
+   * up the parent's chain of the window to finally
+   * figure-out that none of them has an invalid region.
+   */
+  if (uncFlags & UNC_IN_BEGINPAINT)
+    return FALSE;
+
+  /*
+   * Scan all the parents of this window to find a window
+   * that doesn't have the WS_CLIPCHILDREN style and that
+   * has an invalid region. 
+   */
+  parentWnd = WIN_LockWndPtr(wndPtr->parent);
+
+  while (parentWnd!=NULL)
+  {
+    if ( ((parentWnd->dwStyle & WS_CLIPCHILDREN) == 0) &&
+	 (parentWnd->hrgnUpdate != 0) )
+    {
+      WIN_ReleaseWndPtr(parentWnd);
+      return TRUE;
+    }
+
+    WIN_UpdateWndPtr(&parentWnd, parentWnd->parent);    
+  }
+
+  WIN_ReleaseWndPtr(parentWnd);
+
+  return FALSE;
+}
+
+/***********************************************************************
  *           WIN_UpdateNCRgn
  *
  *  Things to do:
@@ -72,7 +150,11 @@
 	uncFlags |= UNC_ENTIRE; 
     }
 
-    if( wnd->flags & WIN_NEEDS_NCPAINT )
+    /*
+     * If the window's non-client area needs to be painted, 
+     */
+    if ( ( wnd->flags & WIN_NEEDS_NCPAINT ) &&
+	 !WIN_HaveToDelayNCPAINT(wnd, uncFlags) )
     {
 	    RECT r2, r3;
 
@@ -184,7 +266,7 @@
     wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
 
     /* send WM_NCPAINT and make sure hrgnUpdate is a valid rgn handle */
-    WIN_UpdateNCRgn( wndPtr, 0, UNC_UPDATE );
+    WIN_UpdateNCRgn( wndPtr, 0, UNC_UPDATE | UNC_IN_BEGINPAINT);
 
     /*
      * Make sure the window is still a window. All window locks are suspended
@@ -626,6 +708,13 @@
 
     TRACE_(win)("\thwnd %04x [%04x] -> hrgn [%04x], flags [%04x]\n", hWnd, wndPtr->hrgnUpdate, hrgn, flags );
 
+    /*
+     * Check if this window should delay it's processing of WM_NCPAINT.
+     * See WIN_HaveToDelayNCPAINT for a description of the mechanism
+     */
+    if ((ex & RDW_EX_DELAY_NCPAINT) || WIN_HaveToDelayNCPAINT(wndPtr, 0) )
+	ex |= RDW_EX_DELAY_NCPAINT;
+
     if (flags & RDW_UPDATENOW)
     {
         if (wndPtr->hrgnUpdate) /* wm_painticon wparam is 1 */
@@ -634,8 +723,14 @@
     else if ((flags & RDW_ERASENOW) || (ex & RDW_EX_TOPFRAME))
     {
 	UINT dcx = DCX_INTERSECTRGN | DCX_USESTYLE | DCX_KEEPCLIPRGN | DCX_WINDOWPAINT | DCX_CACHE;
-	HRGN hrgnRet = WIN_UpdateNCRgn( wndPtr, hrgn, UNC_REGION | UNC_CHECK | 
-			    ((ex & RDW_EX_TOPFRAME) ? UNC_ENTIRE : 0) ); 
+	HRGN hrgnRet;
+
+	hrgnRet = WIN_UpdateNCRgn(wndPtr, 
+				  hrgn, 
+				  UNC_REGION | UNC_CHECK | 
+				  ((ex & RDW_EX_TOPFRAME) ? UNC_ENTIRE : 0) |
+				  ((ex & RDW_EX_DELAY_NCPAINT) ? UNC_DELAY_NCPAINT : 0) ); 
+
         if( hrgnRet )
 	{
 	    if( hrgnRet > 1 ) hrgn = hrgnRet; else hrgnRet = 0; /* entire client */
@@ -678,7 +773,7 @@
 		if (!IsWindow(wndPtr->hwndSelf)) continue;
 		    if ( (wndPtr->dwStyle & WS_VISIBLE) &&
 			 (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT)) )
-			hrgn = RDW_Paint( wndPtr, hrgn, flags, ex );
+		        hrgn = RDW_Paint( wndPtr, hrgn, flags, ex );
 	    }
             WIN_ReleaseWndPtr(wndPtr);
 	    WIN_ReleaseWinArray(list);