Moved hrgnUpdate from client to window coordinates, made nonclient
painting depend on the update region, reworked SetWindowPos() and
RedrawWindow() to speed up update region calculation, made -desktop
work properly, added WM_CANCELMODE here and there, fixed several
window activation bugs that crept in since the last time.

diff --git a/windows/dce.c b/windows/dce.c
index a2e9175..e9d1de7 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -222,8 +222,9 @@
  *   DCE_InvalidateDCE
  *
  * It is called from SetWindowPos() - we have to mark as dirty all busy
- * DCE's for windows that have pWnd->parent as an ansector and whose client 
- * rect intersects with specified update rectangle. 
+ * DCEs for windows that have pWnd->parent as an ansector and whose client 
+ * rect intersects with specified update rectangle. In addition, pWnd->parent
+ * DCEs may need to be updated if DCX_CLIPCHILDREN flag is set.
  */
 BOOL DCE_InvalidateDCE(WND* pWnd, const RECT* pRectUpdate)
 {
@@ -248,17 +249,25 @@
 	    {
 		WND* wndCurrent = WIN_FindWndPtr(dce->hwndCurrent);
 
-		if( wndCurrent && wndCurrent != WIN_GetDesktop() )
+		if( wndCurrent )
 		{
 		    WND* wnd = NULL;
 		    INT xoffset = 0, yoffset = 0;
 
                     if( (wndCurrent == wndScope) && !(dce->DCXflags & DCX_CLIPCHILDREN) )
                     {
+			/* child window positions don't bother us */
                         WIN_ReleaseWndPtr(wndCurrent);
                         continue;
                     }
 
+		    if( !Options.desktopGeometry && wndCurrent == WIN_GetDesktop() )
+		    {
+			/* don't bother with fake desktop */
+			WIN_ReleaseDesktop();
+			continue;
+		    }
+
 		    /* check if DCE window is within the z-order scope */
 
 		    for( wnd = WIN_LockWndPtr(wndCurrent); wnd; WIN_UpdateWndPtr(&wnd,wnd->parent))
@@ -305,7 +314,6 @@
 		    }
 		}
                 WIN_ReleaseWndPtr(wndCurrent);
-                WIN_ReleaseDesktop();
 	    }
 	} /* dce list */
     }
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 0a71f83..5b7ba08 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -11,6 +11,7 @@
 #include "sysmetrics.h"
 #include "user.h"
 #include "heap.h"
+#include "dce.h"
 #include "cursoricon.h"
 #include "dialog.h"
 #include "menu.h"
@@ -1563,7 +1564,8 @@
 
     TRACE(nonclient, "%04x %d\n", hwnd, active );
 
-    if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
+    if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
+			      ((clip > 1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
 
     if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
 		        wndPtr->rectClient.top-wndPtr->rectWindow.top,
@@ -1665,7 +1667,7 @@
     BOOL  suppress_menupaint )
 {
     HDC hdc;
-    RECT rect;
+    RECT rfuzz, rect, rectClip;
     BOOL active;
     HWND hwnd = wndPtr->hwndSelf;
 
@@ -1676,7 +1678,15 @@
 
     TRACE(nonclient, "%04x %d\n", hwnd, active );
 
-    if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
+    /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in the call to
+     * GetDCEx implying that it is allowed not to use it either. However, the suggested
+     * GetDCEx(    , DCX_WINDOW | DCX_INTERSECTRGN) will cause clipRgn to be deleted
+     * after ReleaseDC(). Now, how is the "system" supposed to tell what happened?
+     */
+
+    if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
+			      ((clip > 1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
+
 
     if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
 		        wndPtr->rectClient.top-wndPtr->rectWindow.top,
@@ -1692,6 +1702,14 @@
     rect.right  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
     rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
 
+    if( clip > 1 )
+	GetRgnBox( clip, &rectClip );
+    else
+    {
+	clip = 0;
+	rectClip = rect;
+    }
+
     SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
 
     if(!(wndPtr->flags & WIN_MANAGED)) {
@@ -1716,8 +1734,9 @@
 		r.bottom = rect.top + sysMetrics[SM_CYCAPTION];
 		rect.top += sysMetrics[SM_CYCAPTION];
 	    }
-            NC_DrawCaption95 (hdc, &r, hwnd, wndPtr->dwStyle,
-                              wndPtr->dwExStyle, active);
+	    if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
+                NC_DrawCaption95 (hdc, &r, hwnd, wndPtr->dwStyle,
+                                  wndPtr->dwExStyle, active);
         }
     }
 
diff --git a/windows/painting.c b/windows/painting.c
index 8ca4063..5cc8d3f 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -2,12 +2,11 @@
  * Window painting functions
  *
  * Copyright 1993, 1994, 1995 Alexandre Julliard
+ *			 1999 Alex Korobka
  *
- * FIXME: Do not repaint full nonclient area all the time. Instead, compute 
- *	  intersection with hrgnUpdate (which should be moved from client to 
- *	  window coords as well, lookup 'the pain' comment in the winpos.c).
  */
 
+#include "region.h"
 #include "win.h"
 #include "queue.h"
 #include "dce.h"
@@ -15,74 +14,98 @@
 #include "debug.h"
 #include "wine/winuser16.h"
 
+/* client rect in window coordinates */
+
+#define GETCLIENTRECTW( wnd, r )	(r).left = (wnd)->rectClient.left - (wnd)->rectWindow.left; \
+					(r).top = (wnd)->rectClient.top - (wnd)->rectWindow.top; \
+					(r).right = (wnd)->rectClient.right - (wnd)->rectWindow.left; \
+					(r).bottom = (wnd)->rectClient.bottom - (wnd)->rectWindow.top
+
   /* Last CTLCOLOR id */
 #define CTLCOLOR_MAX   CTLCOLOR_STATIC
 
-/***********************************************************************
- *           WIN_UpdateNCArea
- *
- */
-void WIN_UpdateNCArea(WND* wnd, BOOL bUpdate)
-{
-    POINT16 pt = {0, 0}; 
-    HRGN hClip = 1;
 
-    TRACE(nonclient,"hwnd %04x, hrgnUpdate %04x\n", 
-                      wnd->hwndSelf, wnd->hrgnUpdate );
+/***********************************************************************
+ *           WIN_UpdateNCRgn
+ *
+ * NOTE: Caller is responsible for the returned region.
+ */
+HRGN WIN_UpdateNCRgn(WND* wnd, BOOL bUpdate, BOOL bForceEntire )
+{
+    HRGN hClip = 0;
+
+    TRACE(nonclient,"hwnd %04x, hrgnUpdate %04x, ncf %i\n", 
+                      wnd->hwndSelf, wnd->hrgnUpdate, (wnd->flags & WIN_NEEDS_NCPAINT)!=0 );
 
     /* desktop window doesn't have nonclient area */
     if(wnd == WIN_GetDesktop()) 
     {
         wnd->flags &= ~WIN_NEEDS_NCPAINT;
         WIN_ReleaseDesktop();
-        return;
+        return 0;
     }
     WIN_ReleaseDesktop();
 
-    if( wnd->hrgnUpdate > 1 )
+    if ((wnd->hwndSelf == GetActiveWindow()) &&
+        !(wnd->flags & WIN_NCACTIVATED) )
     {
-	ClientToScreen16(wnd->hwndSelf, &pt);
-
-        hClip = CreateRectRgn( 0, 0, 0, 0 );
-        if (!CombineRgn( hClip, wnd->hrgnUpdate, 0, RGN_COPY ))
-        {
-            DeleteObject(hClip);
-            hClip = 1;
-        }
-	else
-	    OffsetRgn( hClip, pt.x, pt.y );
-
-        if (bUpdate)
-        {
-	    /* exclude non-client area from update region */
-            HRGN hrgn = CreateRectRgn( 0, 0,
-                                 wnd->rectClient.right - wnd->rectClient.left,
-                                 wnd->rectClient.bottom - wnd->rectClient.top);
-
-            if (hrgn && (CombineRgn( wnd->hrgnUpdate, wnd->hrgnUpdate,
-                                       hrgn, RGN_AND) == NULLREGION))
-            {
-                DeleteObject( wnd->hrgnUpdate );
-                wnd->hrgnUpdate = 1;
-            }
-
-            DeleteObject( hrgn );
-        }
+	wnd->flags |= WIN_NCACTIVATED;
+	bForceEntire = TRUE;
     }
 
+    if( (wnd->flags & WIN_NEEDS_NCPAINT) && wnd->hrgnUpdate )
+    {
+	RECT r, r2, r3;
+
+	GETCLIENTRECTW( wnd, r );
+
+	TRACE(nonclient, "\tclient box (%i,%i-%i,%i)\n", r.left, r.top, r.right, r.bottom );
+
+	if( wnd->hrgnUpdate > 1 )
+	{
+	        GetRgnBox( wnd->hrgnUpdate, &r2 );
+	        UnionRect( &r3, &r2, &r );
+	        if( r3.left != r.left || r3.top != r.top || 
+		    r3.right != r.right || r3.bottom != r.bottom )
+	        {
+	 	    hClip = CreateRectRgn( 0, 0, 0, 0 );
+		    CombineRgn( hClip, wnd->hrgnUpdate, 0, RGN_COPY );
+	        }
+	}
+	else 
+		hClip = wnd->hrgnUpdate;
+
+	if( wnd->hrgnUpdate > 1 )
+	{
+	    REGION_CropRgn( wnd->hrgnUpdate, wnd->hrgnUpdate, &r, NULL );
+
+	    if( bUpdate )
+	    {
+		GetRgnBox( wnd->hrgnUpdate, &r3 );
+		if( IsRectEmpty( &r3 ) )
+		{
+		    /* delete update region since all invalid 
+		     * parts were in the nonclient area */
+
+		    DeleteObject( wnd->hrgnUpdate );
+		    wnd->hrgnUpdate = 0;
+		    if(!(wnd->flags & WIN_INTERNAL_PAINT))
+			QUEUE_DecPaintCount( wnd->hmemTaskQ );
+		    wnd->flags &= ~WIN_NEEDS_ERASEBKGND;
+		}
+	    }
+	}
+	else /* entire client rect */
+	   wnd->hrgnUpdate = CreateRectRgnIndirect( &r );
+    }
+
+    if(!hClip && bForceEntire ) hClip = 1;
     wnd->flags &= ~WIN_NEEDS_NCPAINT;
 
-    if ((wnd->hwndSelf == GetActiveWindow()) &&
-        !(wnd->flags & WIN_NCACTIVATED))
-    {
-        wnd->flags |= WIN_NCACTIVATED;
-        if( hClip > 1) DeleteObject( hClip );
-        hClip = 1;
-    }
+    if( hClip )
+	SendMessageA( wnd->hwndSelf, WM_NCPAINT, hClip, 0L );
 
-    if (hClip) SendMessage16( wnd->hwndSelf, WM_NCPAINT, hClip, 0L );
-
-    if (hClip > 1) DeleteObject( hClip );
+    return hClip;
 }
 
 
@@ -100,10 +123,10 @@
 
     wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
 
-    if (wndPtr->flags & WIN_NEEDS_NCPAINT) WIN_UpdateNCArea( wndPtr, TRUE );
+    if( (hrgnUpdate = WIN_UpdateNCRgn( wndPtr, FALSE, FALSE )) > 1 ) 
+	DeleteObject( hrgnUpdate );
 
-    if (((hrgnUpdate = wndPtr->hrgnUpdate) != 0) ||
-        (wndPtr->flags & WIN_INTERNAL_PAINT))
+    if( ((hrgnUpdate = wndPtr->hrgnUpdate) != 0) || (wndPtr->flags & WIN_INTERNAL_PAINT))
         QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
 
     wndPtr->hrgnUpdate = 0;
@@ -113,20 +136,19 @@
 
     TRACE(win,"hrgnUpdate = %04x, \n", hrgnUpdate);
 
-    /* When bIcon is TRUE hrgnUpdate is automatically in window coordinates
-     * (because rectClient == rectWindow for WS_MINIMIZE windows).
-     */
-
     if (wndPtr->class->style & CS_PARENTDC)
     {
         /* Don't clip the output to the update region for CS_PARENTDC window */
-	if(hrgnUpdate > 1)
+	if( hrgnUpdate > 1 )
 	    DeleteObject(hrgnUpdate);
         lps->hdc = GetDCEx16( hwnd, 0, DCX_WINDOWPAINT | DCX_USESTYLE |
                               (bIcon ? DCX_WINDOW : 0) );
     }
     else
     {
+	if( hrgnUpdate )
+	    OffsetRgn( hrgnUpdate, wndPtr->rectWindow.left - wndPtr->rectClient.left,
+			           wndPtr->rectWindow.top - wndPtr->rectClient.top );
         lps->hdc = GetDCEx16(hwnd, hrgnUpdate, DCX_INTERSECTRGN |
                              DCX_WINDOWPAINT | DCX_USESTYLE |
                              (bIcon ? DCX_WINDOW : 0) );
@@ -143,7 +165,7 @@
 
     GetClipBox16( lps->hdc, &lps->rcPaint );
 
-TRACE(win,"box = (%i,%i - %i,%i)\n", lps->rcPaint.left, lps->rcPaint.top,
+    TRACE(win,"box = (%i,%i - %i,%i)\n", lps->rcPaint.left, lps->rcPaint.top,
 		    lps->rcPaint.right, lps->rcPaint.bottom );
 
     if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
@@ -285,14 +307,14 @@
  * LOWORD(lParam) = hrgnClip
  * HIWORD(lParam) = hwndSkip  (not used; always NULL)
  *
- * All in all, a prime candidate for a rewrite.
  */
 BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
-                           HRGN hrgnUpdate, UINT flags, UINT control )
+                           HRGN hrgnUpdate, UINT flags, UINT ex )
 {
     BOOL bIcon;
-    HRGN hrgn;
-    RECT rectClient;
+    HRGN hrgn = 0, hrgn2 = 0;
+    RECT r, r2;
+    POINT pt;
     WND* wndPtr;
     WND **list, **ppWnd;
 
@@ -307,110 +329,165 @@
     bIcon = (wndPtr->dwStyle & WS_MINIMIZE && wndPtr->class->hIcon);
     if (rectUpdate)
     {
-        TRACE(win, "%04x %d,%d-%d,%d %04x flags=%04x\n",
-                    hwnd, rectUpdate->left, rectUpdate->top,
-                    rectUpdate->right, rectUpdate->bottom, hrgnUpdate, flags );
+        TRACE(win, "%04x (%04x) %d,%d-%d,%d %04x flags=%04x, exflags=%04x\n",
+                    hwnd, wndPtr->hrgnUpdate, rectUpdate->left, rectUpdate->top,
+                    rectUpdate->right, rectUpdate->bottom, hrgnUpdate, flags, ex );
     }
     else
     {
-        TRACE(win, "%04x NULL %04x flags=%04x\n", hwnd, hrgnUpdate, flags);
+	if( hrgnUpdate ) GetRgnBox( hrgnUpdate, &r );
+	else SetRectEmpty( &r );
+        TRACE(win, "%04x (%04x) NULL %04x box (%i,%i-%i,%i) flags=%04x, exflags=%04x\n", 
+	      hwnd, wndPtr->hrgnUpdate, hrgnUpdate, r.left, r.top, r.right, r.bottom, flags, ex);
     }
 
-    GetClientRect( hwnd, &rectClient );
+    if( flags & RDW_FRAME )
+	r = wndPtr->rectWindow;
+    else
+	r = wndPtr->rectClient;
+    if( ex & RDW_EX_XYWINDOW )
+        OffsetRect( &r, -wndPtr->rectWindow.left, -wndPtr->rectWindow.top );
+    else
+	OffsetRect( &r, -wndPtr->rectClient.left, -wndPtr->rectClient.top );
 
-    if (flags & RDW_INVALIDATE)  /* Invalidate */
+    /* r is the rectangle we crop the supplied update rgn/rect with */
+
+    GETCLIENTRECTW( wndPtr, r2 );
+    pt.x = r2.left; pt.y = r2.top;
+
+    if (flags & RDW_INVALIDATE)  /* ------------------------- Invalidate */
     {
-        int rgnNotEmpty = COMPLEXREGION;
+	BOOL bHasUpdateRgn = (BOOL)wndPtr->hrgnUpdate;
 
-        if (wndPtr->hrgnUpdate > 1)  /* Is there already an update region? */
-        {
-            if ((hrgn = hrgnUpdate) == 0)
-                hrgn = CreateRectRgnIndirect( rectUpdate ? rectUpdate :
-                                                &rectClient );
-            rgnNotEmpty = CombineRgn( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate,
-                                        hrgn, RGN_OR );
-            if (!hrgnUpdate) DeleteObject( hrgn );
-        }
-        else  /* No update region yet */
-        {
-            if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
-                QUEUE_IncPaintCount( wndPtr->hmemTaskQ );
-            if (hrgnUpdate)
-            {
-                wndPtr->hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
-                rgnNotEmpty = CombineRgn( wndPtr->hrgnUpdate, hrgnUpdate,
-                                            0, RGN_COPY );
-            }
-            else wndPtr->hrgnUpdate = CreateRectRgnIndirect( rectUpdate ?
-                                                    rectUpdate : &rectClient );
-        }
-	
-        if (flags & RDW_FRAME) wndPtr->flags |= WIN_NEEDS_NCPAINT;
+	/* wndPtr->hrgnUpdate is in window coordinates, parameters are
+	 * in client coordinates unless RDW_EX_XYWINDOW is set. 
+	 */
 
-        /* restrict update region to client area (FIXME: correct?) */
-        if (wndPtr->hrgnUpdate)
-        {
-            HRGN clientRgn = CreateRectRgnIndirect( &rectClient );
-            rgnNotEmpty = CombineRgn( wndPtr->hrgnUpdate, clientRgn, 
-                                        wndPtr->hrgnUpdate, RGN_AND );
-            DeleteObject( clientRgn );
-        }
+	if( hrgnUpdate )
+	{
+	    hrgn = REGION_CropRgn( 0, hrgnUpdate, &r, (ex & RDW_EX_XYWINDOW) ? NULL : &pt );
+	    GetRgnBox( hrgn, &r2 );
+	    if( IsRectEmpty( &r2 ) )
+		goto END;
 
-	/* check for bogus update region */ 
-	if ( rgnNotEmpty == NULLREGION )
-	   {
-	     wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
-	     DeleteObject( wndPtr->hrgnUpdate );
-	     wndPtr->hrgnUpdate=0;
-             if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
-                   QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
-	   }
-	else
-             if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
+	    if( wndPtr->hrgnUpdate == 0 )
+	    {
+		wndPtr->hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
+		CombineRgn( wndPtr->hrgnUpdate, hrgn, 0, RGN_COPY );
+	    }
+	    else
+		if( wndPtr->hrgnUpdate > 1 )
+		    CombineRgn( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate, hrgn, RGN_OR );
+	}
+	else if( rectUpdate )
+	{
+	    if( !IntersectRect( &r2, &r, rectUpdate ) )
+		goto END;
+	    if( !(ex & RDW_EX_XYWINDOW) )
+		OffsetRect( &r2, pt.x, pt.y );
+
+rect2i:     /* r2 contains a rect to add to the update region */
+
+	    hrgn = CreateRectRgnIndirect( &r2 );
+	    if( wndPtr->hrgnUpdate == 0 )
+		wndPtr->hrgnUpdate = CreateRectRgnIndirect( &r2 );
+	    else
+		if( wndPtr->hrgnUpdate > 1 )
+		    REGION_UnionRectWithRgn( wndPtr->hrgnUpdate, &r2 );
+	}
+	else /* entire window or client depending on RDW_FRAME */
+	{
+	    hrgn = 1;
+	    if( flags & RDW_FRAME )
+	    {
+		if( wndPtr->hrgnUpdate )
+		    DeleteObject( wndPtr->hrgnUpdate );
+		wndPtr->hrgnUpdate = 1;
+	    }
+	    else /* by default r2 contains client rect in window coordinates */
+		goto rect2i;
+	}
+
+	if( !bHasUpdateRgn && wndPtr->hrgnUpdate && !(wndPtr->flags & WIN_INTERNAL_PAINT))
+	    QUEUE_IncPaintCount( wndPtr->hmemTaskQ );
+
+	if (flags & RDW_FRAME) wndPtr->flags |= WIN_NEEDS_NCPAINT;
+        if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
 	flags |= RDW_FRAME;  /* Force children frame invalidation */
     }
-    else if (flags & RDW_VALIDATE)  /* Validate */
+    else if (flags & RDW_VALIDATE)  /* ------------------------- Validate */
     {
-          /* We need an update region in order to validate anything */
-        if (wndPtr->hrgnUpdate > 1)
+        if (wndPtr->hrgnUpdate) /* need an update region in order to validate anything */
         {
-            if (!hrgnUpdate && !rectUpdate)
+	    if( hrgnUpdate || rectUpdate )
+	    {
+		if( hrgnUpdate )
+		{
+		    hrgn = REGION_CropRgn( hrgn, hrgnUpdate,  &r, (ex & RDW_EX_XYWINDOW) ? NULL : &pt );
+		    GetRgnBox( hrgn, &r2 );
+		    if( IsRectEmpty( &r2 ) )
+			goto END;
+		}
+		else
+		{
+		    if( !IntersectRect( &r2, &r, rectUpdate ) )
+			goto END;
+		    if( !(ex & RDW_EX_XYWINDOW) )
+			OffsetRect( &r2, pt.x, pt.y );
+rect2v:
+		    hrgn = CreateRectRgnIndirect( &r2 );
+		}
+
+		if( wndPtr->hrgnUpdate == 1 )
+		{
+		    wndPtr->hrgnUpdate = CreateRectRgn( 0, 0,
+					 wndPtr->rectWindow.right - wndPtr->rectWindow.left,
+					 wndPtr->rectWindow.bottom - wndPtr->rectWindow.top );
+		}
+
+		if( CombineRgn( wndPtr->hrgnUpdate, 
+				wndPtr->hrgnUpdate, hrgn, RGN_DIFF ) == NULLREGION )
+		{
+		    DeleteObject( wndPtr->hrgnUpdate );
+		    wndPtr->hrgnUpdate = 0;
+		}
+	    }
+	    else /* entire window or client depending on RDW_FRAME */
             {
-                  /* Special case: validate everything */
-                DeleteObject( wndPtr->hrgnUpdate );
-                wndPtr->hrgnUpdate = 0;
+		wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
+
+		hrgn = 1;
+		if( flags & RDW_FRAME ) 
+		{
+		    if( wndPtr->hrgnUpdate != 1 )
+			DeleteObject( wndPtr->hrgnUpdate );
+		    wndPtr->hrgnUpdate = 0;
+		}
+		else /* by default r2 contains client rect in window coordinates */
+		    goto rect2v;
             }
-            else
-            {
-                if ((hrgn = hrgnUpdate) == 0)
-                    hrgn = CreateRectRgnIndirect( rectUpdate );
-                if (CombineRgn( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate,
-                                  hrgn, RGN_DIFF ) == NULLREGION)
-                {
-                    DeleteObject( wndPtr->hrgnUpdate );
-                    wndPtr->hrgnUpdate = 0;
-                }
-                if (!hrgnUpdate) DeleteObject( hrgn );
-            }
-            if (!wndPtr->hrgnUpdate)  /* No more update region */
-		if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
+
+            if (!wndPtr->hrgnUpdate &&  /* No more update region */
+		!(wndPtr->flags & WIN_INTERNAL_PAINT) )
 		    QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
         }
         if (flags & RDW_NOFRAME) wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
 	if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
     }
 
-      /* Set/clear internal paint flag */
+    /* At this point hrgn contains new update region in window coordinates */
+
+    /* Set/clear internal paint flag */
 
     if (flags & RDW_INTERNALPAINT)
     {
-	if ( wndPtr->hrgnUpdate <= 1 && !(wndPtr->flags & WIN_INTERNAL_PAINT))
+	if ( !wndPtr->hrgnUpdate && !(wndPtr->flags & WIN_INTERNAL_PAINT))
 	    QUEUE_IncPaintCount( wndPtr->hmemTaskQ );
 	wndPtr->flags |= WIN_INTERNAL_PAINT;	    
     }
     else if (flags & RDW_NOINTERNALPAINT)
     {
-	if ( wndPtr->hrgnUpdate <= 1 && (wndPtr->flags & WIN_INTERNAL_PAINT))
+	if ( !wndPtr->hrgnUpdate && (wndPtr->flags & WIN_INTERNAL_PAINT))
 	    QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
 	wndPtr->flags &= ~WIN_INTERNAL_PAINT;
     }
@@ -422,17 +499,29 @@
         if (wndPtr->hrgnUpdate) /* wm_painticon wparam is 1 */
             SendMessage16( hwnd, (bIcon) ? WM_PAINTICON : WM_PAINT, bIcon, 0 );
     }
-    else if (flags & RDW_ERASENOW)
+    else if ((flags & RDW_ERASENOW) || (ex & RDW_EX_TOPFRAME))
     {
-        if (wndPtr->flags & WIN_NEEDS_NCPAINT)
-	    WIN_UpdateNCArea( wndPtr, FALSE);
+	hrgn2 = WIN_UpdateNCRgn( wndPtr, TRUE, (ex & RDW_EX_TOPFRAME) );
 
-        if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
+        if( wndPtr->flags & WIN_NEEDS_ERASEBKGND )
         {
-            HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
-                                   DCX_INTERSECTRGN | DCX_USESTYLE |
-                                   DCX_KEEPCLIPRGN | DCX_WINDOWPAINT |
-                                   (bIcon ? DCX_WINDOW : 0) );
+            HDC hdc;
+
+	    if( hrgn2 > 1 )
+	    {
+		OffsetRgn( hrgn2, -pt.x, -pt.y );
+		GetRgnBox( hrgn2, &r2 );
+	    }
+	    else
+	    {
+		hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
+		CombineRgn( hrgn2, wndPtr->hrgnUpdate, 0, RGN_COPY );
+		OffsetRgn( hrgn2, -pt.x, -pt.y );
+	    }
+	    hdc = GetDCEx( hwnd, hrgn2,
+                                 DCX_INTERSECTRGN | DCX_USESTYLE |
+                                 DCX_KEEPCLIPRGN | DCX_WINDOWPAINT |
+                                 (bIcon ? DCX_WINDOW : 0) );
             if (hdc)
             {
                if (SendMessage16( hwnd, (bIcon) ? WM_ICONERASEBKGND
@@ -456,47 +545,40 @@
         ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)) &&
 	!(wndPtr->dwStyle & WS_MINIMIZE) )
     {
-        if ( hrgnUpdate || rectUpdate )
+        if( hrgnUpdate || rectUpdate )
 	{
-            if (!(hrgn = CreateRectRgn( 0, 0, 0, 0 )))
-	{
-                WIN_ReleaseWndPtr(wndPtr);
-                return TRUE;
-            }
-	   if( !hrgnUpdate )
-           {
-	        control |= (RDW_C_DELETEHRGN | RDW_C_USEHRGN);
- 	        if( !(hrgnUpdate = CreateRectRgnIndirect( rectUpdate )) )
-                {
-                    DeleteObject( hrgn );
-                    WIN_ReleaseWndPtr(wndPtr);
-                    return TRUE;
-                }
-           }
+	   if( hrgn2 <= 1 )
+	       hrgn2 = (ex & RDW_EX_USEHRGN) ? hrgnUpdate : 0;
+
            if( (list = WIN_BuildWinArray( wndPtr, 0, NULL )) )
 	   {
+		POINT	delta = pt;
+
 		for (ppWnd = list; *ppWnd; ppWnd++)
 		{
 		    WIN_UpdateWndPtr(&wndPtr,*ppWnd);
 		    if (!IsWindow(wndPtr->hwndSelf)) continue;
 		    if (wndPtr->dwStyle & WS_VISIBLE)
 		    {
-			SetRectRgn( hrgn, 
-				wndPtr->rectWindow.left, wndPtr->rectWindow.top, 
-				wndPtr->rectWindow.right, wndPtr->rectWindow.bottom );
-			if (CombineRgn( hrgn, hrgn, hrgnUpdate, RGN_AND ))
+			r.left = wndPtr->rectWindow.left + delta.x;
+			r.top = wndPtr->rectWindow.top + delta.y;
+			r.right = wndPtr->rectWindow.right + delta.x;
+			r.bottom = wndPtr->rectWindow.bottom + delta.y;
+
+			pt.x = -r.left; pt.y = -r.top;
+
+			hrgn2 = REGION_CropRgn( hrgn2, hrgn, &r, &pt );
+
+			GetRgnBox( hrgn2, &r2 );
+			if( !IsRectEmpty( &r2 ) )
 			{
-			    OffsetRgn( hrgn, -wndPtr->rectClient.left,
-                                        -wndPtr->rectClient.top );
-			    PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, hrgn, flags,
-                                         RDW_C_USEHRGN );
+			    PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, hrgn2, flags,
+						RDW_EX_USEHRGN | RDW_EX_XYWINDOW );
 			}
 		    }
 		}
                 WIN_ReleaseWinArray(list);
 	   }
-	   DeleteObject( hrgn );
-	   if (control & RDW_C_DELETEHRGN) DeleteObject( hrgnUpdate );
 	}
         else
         {
@@ -513,6 +595,12 @@
 	}
 
     }
+
+END:
+    if( hrgn2 > 1 && (hrgn2 != hrgnUpdate) )
+	DeleteObject( hrgn2 );
+    if( hrgn > 1 && (hrgn != hrgnUpdate) )
+	DeleteObject( hrgn );
     WIN_ReleaseWndPtr(wndPtr);
     return TRUE;
 }
@@ -680,9 +768,16 @@
 		}
 	    }
 	}
-	else SetRectEmpty( rect );
+	else
+	if( wndPtr->hrgnUpdate == 1 )
+	{
+	    GetClientRect( hwnd, rect );
+	    if (erase) RedrawWindow( hwnd, NULL, 0, RDW_FRAME | RDW_ERASENOW | RDW_NOCHILDREN );
+	}
+	else 
+	    SetRectEmpty( rect );
     }
-    retvalue = (wndPtr->hrgnUpdate > 1);
+    retvalue = (wndPtr->hrgnUpdate >= 1);
 END:
     WIN_ReleaseWndPtr(wndPtr);
     return retvalue;
@@ -699,7 +794,7 @@
 
 
 /***********************************************************************
- *           GetUpdateRgn32   (USER32.298)
+ *           GetUpdateRgn    (USER32.298)
  */
 INT WINAPI GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
 {
@@ -707,13 +802,25 @@
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return ERROR;
 
-    if (wndPtr->hrgnUpdate <= 1)
+    if (wndPtr->hrgnUpdate == 0)
     {
         SetRectRgn( hrgn, 0, 0, 0, 0 );
         retval = NULLREGION;
         goto END;
     }
-    retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY );
+    else
+    if (wndPtr->hrgnUpdate == 1)
+    {
+	SetRectRgn( hrgn, 0, 0, wndPtr->rectClient.right - wndPtr->rectClient.left,
+				wndPtr->rectClient.bottom - wndPtr->rectClient.top );
+	retval = SIMPLEREGION;
+    }
+    else
+    {
+	retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY );
+	OffsetRgn( hrgn, wndPtr->rectWindow.left - wndPtr->rectClient.left,
+			 wndPtr->rectWindow.top - wndPtr->rectClient.top );
+    }
     if (erase) RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW | RDW_NOCHILDREN );
 END:
     WIN_ReleaseWndPtr(wndPtr);
@@ -745,10 +852,14 @@
 	INT ret;
 	HRGN hrgn = CreateRectRgn(wndPtr->rectWindow.left - wndPtr->rectClient.left,
 				      wndPtr->rectWindow.top - wndPtr->rectClient.top,
-				      wndPtr->rectClient.right - wndPtr->rectClient.left,
-				      wndPtr->rectClient.bottom - wndPtr->rectClient.top);
+				      wndPtr->rectWindow.right - wndPtr->rectClient.left,
+				      wndPtr->rectWindow.bottom - wndPtr->rectClient.top);
 	if( wndPtr->hrgnUpdate > 1 )
+	{
 	    CombineRgn(hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY);
+	    OffsetRgn(hrgn, wndPtr->rectWindow.left - wndPtr->rectClient.left, 
+			    wndPtr->rectWindow.top - wndPtr->rectClient.top );
+	}
 
 	/* do ugly coordinate translations in dce.c */
 
diff --git a/windows/scroll.c b/windows/scroll.c
index bba77af..ddf6d7c 100644
--- a/windows/scroll.c
+++ b/windows/scroll.c
@@ -275,7 +275,7 @@
 	if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
 	{
             if (dc->w.hVisRgn) {
-                wnd->pDriver->pScrollWindow(wnd,dc,dx,dy,&rc,bUpdate);
+                wnd->pDriver->pSurfaceCopy(wnd,dc,dx,dy,&rc,bUpdate);
 
                 if( bUpdate )
                     {
diff --git a/windows/ttydrv/init.c b/windows/ttydrv/init.c
index a5203d7..b7e6396 100644
--- a/windows/ttydrv/init.c
+++ b/windows/ttydrv/init.c
@@ -81,6 +81,7 @@
   TTYDRV_WND_PostSizeMove,
   TTYDRV_WND_ScrollWindow,
   TTYDRV_WND_SetDrawable,
+  TTYDRV_WND_SetHostAttr,
   TTYDRV_WND_IsSelfClipping
 };
 
diff --git a/windows/ttydrv/wnd.c b/windows/ttydrv/wnd.c
index da2b184..7085ac9 100644
--- a/windows/ttydrv/wnd.c
+++ b/windows/ttydrv/wnd.c
@@ -117,6 +117,14 @@
 }
 
 /***********************************************************************
+ *              TTYDRV_WND_SetHostAttr
+ */
+BOOL TTYDRV_WND_SetHostAttr(WND *wndPtr, INT attr, INT value)
+{
+    return FALSE;
+}
+
+/***********************************************************************
  *		TTYDRV_WND_IsSelfClipping
  */
 BOOL TTYDRV_WND_IsSelfClipping(WND *wndPtr)
diff --git a/windows/win.c b/windows/win.c
index 2970fb9..5cf69a4 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -1666,14 +1666,24 @@
     {
 	  /* Enable window */
 	wndPtr->dwStyle &= ~WS_DISABLED;
+
+	if( wndPtr->flags & WIN_NATIVE )
+	    wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
+
 	SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
         retvalue = TRUE;
         goto end;
     }
     else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
     {
+	SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
+
 	  /* Disable window */
 	wndPtr->dwStyle |= WS_DISABLED;
+
+	if( wndPtr->flags & WIN_NATIVE )
+            wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
+
 	if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
         {
 	    SetFocus( 0 );  /* A disabled window can't have the focus */
diff --git a/windows/winpos.c b/windows/winpos.c
index dbe7ec1..910fb4a 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -2,7 +2,7 @@
  * Window position related functions.
  *
  * Copyright 1993, 1994, 1995 Alexandre Julliard
- *                       1995, 1996 Alex Korobka
+ *                       1995, 1996, 1999 Alex Korobka
  */
 
 #include "x11drv.h"
@@ -12,6 +12,7 @@
 #include "heap.h"
 #include "module.h"
 #include "user.h"
+#include "region.h"
 #include "win.h"
 #include "hook.h"
 #include "message.h"
@@ -46,10 +47,8 @@
 #define PLACE_MAX		0x0002
 #define PLACE_RECT		0x0004
 
-#define SMC_NOCOPY		0x0001
-#define SMC_NOPARENTERASE	0x0002
-#define SMC_DRAWFRAME		0x0004
-#define SMC_SETXPOS		0x0008
+#define SWP_EX_NOCOPY		0x0001
+#define SWP_EX_PAINTSELF	0x0002
 
 /* ----- internal variables ----- */
 
@@ -396,7 +395,14 @@
    
     if( wndScope->flags & WIN_MANAGED )
     {
-	/* this prevents mouse clicks from going "through" scrollbars in managed mode */
+	/* In managed mode we have to check wndScope first as it is also
+	 * a window which received the mouse event. */
+
+	if( wndScope->dwStyle & WS_DISABLED )
+	{
+	    retvalue = HTERROR;
+	    goto end;
+	}
 	if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
 	    pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
 	    goto hittest;
@@ -1688,6 +1694,9 @@
         if ( pNewActiveQueue )
             PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
     }
+    else /* have to do this or MDI frame activation goes to hell */
+	if( pOldActiveQueue )
+	    PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
 
     /* send palette messages */
     if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
@@ -1875,13 +1884,10 @@
  */
 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
 {
-    WND *wndPtr = WIN_FindWndPtr(hWnd);
-    WND *wndTemp;
+    WND *wndPtr, *wndTemp;
     BOOL retvalue;
     HWND hwndActive = 0;
 
-    if( !wndPtr ) return FALSE;
-
     /* Get current active window from the active queue */
     if ( hActiveQueue )
     {
@@ -1894,11 +1900,10 @@
     }
 
     if (!hWnd)
-    {
-        retvalue = WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
-        goto end;
-    }
+        return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
 
+    wndPtr = WIN_FindWndPtr(hWnd);
+    if( !wndPtr ) return FALSE;
 
     /* child windows get WM_CHILDACTIVATE message */
     if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
@@ -1907,20 +1912,6 @@
         goto end;
     }
 
-        /* owned popups imply owner activation - not sure */
-    if ((wndPtr->dwStyle & WS_POPUP) && wndPtr->owner &&
-        (wndPtr->owner->dwStyle & WS_VISIBLE ) &&
-        !(wndPtr->owner->dwStyle & WS_DISABLED ))
-    {
-        WIN_UpdateWndPtr(&wndPtr,wndPtr->owner);
-        if (!wndPtr)
-    {
-            retvalue = FALSE;
-            goto end;
-        }
-	hWnd = wndPtr->hwndSelf;
-    }
-
     if( hWnd == hwndActive )
     {
         retvalue = FALSE;
@@ -2025,291 +2016,322 @@
     return 0;
 }
 
-
 /***********************************************************************
- *           WINPOS_MoveWindowZOrder
- *
- * Move a window in Z order, invalidating everything that needs it.
- * Only necessary for windows without associated X window.
- */
-static void WINPOS_MoveWindowZOrder( HWND hwnd, HWND hwndAfter )
-{
-    BOOL movingUp;
-    WND *pWndAfter, *pWndCur, *wndPtr = WIN_FindWndPtr( hwnd );
-
-    /* We have two possible cases:
-     * - The window is moving up: we have to invalidate all areas
-     *   of the window that were covered by other windows
-     * - The window is moving down: we have to invalidate areas
-     *   of other windows covered by this one.
-     */
-
-    if (hwndAfter == HWND_TOP)
-    {
-        movingUp = TRUE;
-    }
-    else if (hwndAfter == HWND_BOTTOM)
-    {
-        if (!wndPtr->next) goto END;  /* Already at the bottom */
-        movingUp = FALSE;
-    }
-    else
-    {
-        if (!(pWndAfter = WIN_FindWndPtr( hwndAfter ))) goto END;
-        if (wndPtr->next == pWndAfter)
-    {
-            WIN_ReleaseWndPtr(pWndAfter);
-            goto END;  /* Already placed right */
-        }
-
-          /* Determine which window we encounter first in Z-order */
-        pWndCur = WIN_LockWndPtr(wndPtr->parent->child);
-        while ((pWndCur != wndPtr) && (pWndCur != pWndAfter))
-        {
-            WIN_UpdateWndPtr(&pWndCur,pWndCur->next);
-        }
-        movingUp = (pWndCur == pWndAfter);
-        WIN_ReleaseWndPtr(pWndCur);
-        WIN_ReleaseWndPtr(pWndAfter);
-    }
-
-    if (movingUp)
-    {
-        WND *pWndPrevAfter = WIN_LockWndPtr(wndPtr->next);
-        WIN_UnlinkWindow( hwnd );
-        WIN_LinkWindow( hwnd, hwndAfter );
-        pWndCur = WIN_LockWndPtr(wndPtr->next);
-        while (pWndCur != pWndPrevAfter)
-        {
-            RECT rect = { pWndCur->rectWindow.left,
-			    pWndCur->rectWindow.top,
-			    pWndCur->rectWindow.right,
-			    pWndCur->rectWindow.bottom };
-            OffsetRect( &rect, -wndPtr->rectClient.left,
-                          -wndPtr->rectClient.top );
-            PAINT_RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
-                              RDW_FRAME | RDW_ERASE, 0 );
-            WIN_UpdateWndPtr(&pWndCur,pWndCur->next);
-        }
-        WIN_ReleaseWndPtr(pWndPrevAfter);
-    }
-    else  /* Moving down */
-    {
-        pWndCur = WIN_LockWndPtr(wndPtr->next);
-        WIN_UnlinkWindow( hwnd );
-        WIN_LinkWindow( hwnd, hwndAfter );
-        while (pWndCur != wndPtr)
-        {
-            RECT rect = { pWndCur->rectWindow.left,
-                            pWndCur->rectWindow.top,
-                            pWndCur->rectWindow.right,
-                            pWndCur->rectWindow.bottom };
-            OffsetRect( &rect, -pWndCur->rectClient.left,
-                          -pWndCur->rectClient.top );
-            PAINT_RedrawWindow( pWndCur->hwndSelf, &rect, 0, RDW_INVALIDATE |
-                              RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
-            WIN_UpdateWndPtr(&pWndCur,pWndCur->next);
-        }
-    }
-END:
-    WIN_ReleaseWndPtr(wndPtr);
-}
-
-/***********************************************************************
- *           WINPOS_ReorderOwnedPopups
+ *           SWP_DoOwnedPopups
  *
  * fix Z order taking into account owned popups -
  * basically we need to maintain them above the window that owns them
+ *
+ * FIXME: hide/show owned popups when owner visibility changes.
  */
-HWND WINPOS_ReorderOwnedPopups(HWND hwndInsertAfter,WND* wndPtr,WORD flags)
+static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
 {
- WND*   pDesktop = WIN_GetDesktop();
- WND* 	w = WIN_LockWndPtr(pDesktop->child);
+    WND* 	w = WIN_LockWndPtr(pDesktop->child);
 
-  if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner )
-  {
-   /* implement "local z-order" between the top and owner window */
+    WARN(win, "(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
 
-     HWND hwndLocalPrev = HWND_TOP;
-
-     if( hwndInsertAfter != HWND_TOP )
-     {
-	while( w != wndPtr->owner )
-	{
-          if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
-	  if( hwndLocalPrev == hwndInsertAfter ) break;
-          WIN_UpdateWndPtr(&w,w->next);
-	}
-	hwndInsertAfter = hwndLocalPrev;
-     }
-
-  }
-  else if( wndPtr->dwStyle & WS_CHILD )
-      goto END;
-
-  WIN_UpdateWndPtr(&w,pDesktop->child);
-
-  while( w )
-  {
-    if( w == wndPtr ) break;
-
-    if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
+    if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
     {
-      SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
-                     SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
-      hwndInsertAfter = w->hwndSelf;
+	/* make sure this popup stays above the owner */
+
+	HWND hwndLocalPrev = HWND_TOP;
+
+	if( hwndInsertAfter != HWND_TOP )
+	{
+	    while( w != wndPtr->owner )
+	    {
+		if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
+		if( hwndLocalPrev == hwndInsertAfter ) break;
+		WIN_UpdateWndPtr(&w,w->next);
+	    }
+	    hwndInsertAfter = hwndLocalPrev;
+	}
     }
-    WIN_UpdateWndPtr(&w,w->next);
-  }
+    else if( wndPtr->dwStyle & WS_CHILD )
+	goto END; 
+
+    WIN_UpdateWndPtr(&w, pDesktop->child);
+
+    while( w )
+    {
+	if( w == wndPtr ) break; 
+
+	if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
+	{
+	    SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, 
+		 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
+	    hwndInsertAfter = w->hwndSelf;
+	}
+	WIN_UpdateWndPtr(&w, w->next);
+    }
 
 END:
-  WIN_ReleaseWndPtr(w);
-  WIN_ReleaseDesktop();
-  return hwndInsertAfter;
+    WIN_ReleaseWndPtr(w);
+    return hwndInsertAfter;
 }
 
 /***********************************************************************
- *	     WINPOS_SizeMoveClean
+ *	     SWP_CopyValidBits
  *
  * Make window look nice without excessive repainting
  *
- * the pain:
- *
- * visible regions are in window coordinates
- * update regions are in window client coordinates
+ * visible and update regions are in window coordinates
  * client and window rectangles are in parent client coordinates
  *
- * FIXME: Move visible and update regions to the same coordinate system
- *	 (either parent client or window). This is a lot of work though.
+ * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
+ *	  window rects have the same origin.
+ *
+ * Returns: uFlags and a dirty region in *pVisRgn.
  */
-static UINT WINPOS_SizeMoveClean( WND* Wnd, HRGN oldVisRgn,
-                                    LPRECT lpOldWndRect,
-                                    LPRECT lpOldClientRect, UINT uFlags )
+static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
+                               LPRECT lpOldWndRect,
+                               LPRECT lpOldClientRect, UINT uFlags )
 {
- HRGN newVisRgn = DCE_GetVisRgn(Wnd->hwndSelf,DCX_WINDOW | DCX_CLIPSIBLINGS,0,0);
- HRGN dirtyRgn = CreateRectRgn(0,0,0,0);
- int  other, my;
+ RECT r;
+ HRGN newVisRgn, dirtyRgn;
+ INT  my = COMPLEXREGION;
 
- TRACE(win,"cleaning up...new wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i)\n",
+ TRACE(win,"\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
 	      Wnd->rectWindow.left, Wnd->rectWindow.top,
 	      Wnd->rectWindow.right, Wnd->rectWindow.bottom,
 	      lpOldWndRect->left, lpOldWndRect->top,
-	      lpOldWndRect->right, lpOldWndRect->bottom);
+	      lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
  TRACE(win,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
 	      Wnd->rectClient.left, Wnd->rectClient.top,
 	      Wnd->rectClient.right, Wnd->rectClient.bottom,
 	      lpOldClientRect->left, lpOldClientRect->top,
 	      lpOldClientRect->right,lpOldClientRect->bottom );
 
- if( (lpOldWndRect->right - lpOldWndRect->left) != (Wnd->rectWindow.right - Wnd->rectWindow.left) ||
-     (lpOldWndRect->bottom - lpOldWndRect->top) != (Wnd->rectWindow.bottom - Wnd->rectWindow.top) )
-     uFlags |= SMC_DRAWFRAME;
+ if( Wnd->hrgnUpdate == 1 )
+     uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
 
- CombineRgn( dirtyRgn, newVisRgn, 0, RGN_COPY);
+ newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
+ dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
 
- if( !(uFlags & SMC_NOCOPY) )
-   CombineRgn( newVisRgn, newVisRgn, oldVisRgn, RGN_AND ); 
+ if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
+     my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
 
- /* map regions to the parent client area */
- 
- OffsetRgn( dirtyRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
- OffsetRgn( oldVisRgn, lpOldWndRect->left, lpOldWndRect->top );
+ if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
+ {
+nocopy:
 
- /* compute invalidated region outside Wnd - (in client coordinates of the parent window) */
+     TRACE(win,"\twon't copy anything!\n");
 
- other = CombineRgn(dirtyRgn, oldVisRgn, dirtyRgn, RGN_DIFF);
+     /* set dirtyRgn to the sum of old and new visible regions 
+      * in parent client coordinates */
 
- /* map visible region to the Wnd client area */
+     OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
+     OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
 
- OffsetRgn( newVisRgn, Wnd->rectWindow.left - Wnd->rectClient.left,
-                         Wnd->rectWindow.top - Wnd->rectClient.top );
+     CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
+ }
+ else			/* copy valid bits to a new location */
+ {
+     INT  dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
+     HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
 
- /* substract previously invalidated region from the Wnd visible region */
+     /* subtract already invalid region inside Wnd from the dst region */
 
- my =  (Wnd->hrgnUpdate > 1) ? CombineRgn( newVisRgn, newVisRgn,
-                                             Wnd->hrgnUpdate, RGN_DIFF)
-                             : COMPLEXREGION;
+     if( Wnd->hrgnUpdate )
+         if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
+	     goto nocopy;
 
- if( uFlags & SMC_NOCOPY )	/* invalidate Wnd visible region */
-   {
-     if (my != NULLREGION)
-	 PAINT_RedrawWindow( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
-	  RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
-     else if(uFlags & SMC_DRAWFRAME)
-	 Wnd->flags |= WIN_NEEDS_NCPAINT;
-   }
- else			/* bitblt old client area */
-   { 
-     HDC hDC;
-     int   update;
-     HRGN updateRgn;
-     int   xfrom,yfrom,xto,yto,width,height;
+     /* check if entire window can be copied */
 
-     if( uFlags & SMC_DRAWFRAME )
-       {
-	 /* copy only client area, frame will be redrawn anyway */
+     ow = lpOldWndRect->right - lpOldWndRect->left;
+     oh = lpOldWndRect->bottom - lpOldWndRect->top;
+     nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
+     nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
 
-         xfrom = lpOldClientRect->left; yfrom = lpOldClientRect->top;
-         xto = Wnd->rectClient.left; yto = Wnd->rectClient.top;
-         width = lpOldClientRect->right - xfrom; height = lpOldClientRect->bottom - yfrom;
-	 updateRgn = CreateRectRgn( 0, 0, width, height );
-	 CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
-	 SetRectRgn( updateRgn, 0, 0, Wnd->rectClient.right - xto,
-                       Wnd->rectClient.bottom - yto );
-       }
+     ocw = lpOldClientRect->right - lpOldClientRect->left;
+     och = lpOldClientRect->bottom - lpOldClientRect->top;
+     ncw = Wnd->rectClient.right  - Wnd->rectClient.left;
+     nch = Wnd->rectClient.bottom  - Wnd->rectClient.top;
+
+     if(  (ocw != ncw) || (och != nch) ||
+	  ( ow !=  nw) || ( oh !=  nw) ||
+	  ((lpOldClientRect->top - lpOldWndRect->top)   != 
+	   (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
+          ((lpOldClientRect->left - lpOldWndRect->left) !=
+           (Wnd->rectClient.left - Wnd->rectWindow.left)) )
+     {
+	dx = Wnd->rectClient.left - lpOldClientRect->left;
+	dy = Wnd->rectClient.top - lpOldClientRect->top;
+
+	/* restrict valid bits to the common client rect */
+
+	r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
+        r.top = Wnd->rectClient.top  - Wnd->rectWindow.top;
+	r.right = r.left + MIN( ocw, ncw );
+	r.bottom = r.top + MIN( och, nch );
+
+	REGION_CropRgn( hrgnValid, hrgnValid, &r, 
+			(uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
+	GetRgnBox( hrgnValid, &r );
+	if( IsRectEmpty( &r ) )
+	    goto nocopy;
+	r = *lpOldClientRect;
+     }
      else
-       {
-         xfrom = lpOldWndRect->left; yfrom = lpOldWndRect->top;
-         xto = Wnd->rectWindow.left; yto = Wnd->rectWindow.top;
-         width = lpOldWndRect->right - xfrom; height = lpOldWndRect->bottom - yfrom;
-	 updateRgn = CreateRectRgn( xto - Wnd->rectClient.left,
-				      yto - Wnd->rectClient.top,
-				Wnd->rectWindow.right - Wnd->rectClient.left,
-			        Wnd->rectWindow.bottom - Wnd->rectClient.top );
-       }
+     {
+	dx = Wnd->rectWindow.left - lpOldWndRect->left;
+	dy = Wnd->rectWindow.top -  lpOldWndRect->top;
+	if( !(uFlags & SWP_EX_PAINTSELF) )
+	    OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
+	r = *lpOldWndRect;
+     }
 
-     CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
+     if( !(uFlags & SWP_EX_PAINTSELF) )
+     {
+	/* Move remaining regions to parent coordinates */
+	OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
+	OffsetRgn( *pVisRgn,  lpOldWndRect->left, lpOldWndRect->top );
+     }
+     else
+	OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
 
-     /* substract new visRgn from target rect to get a region that won't be copied */
+     TRACE(win,"\tcomputing dirty region!\n");
 
-     update = CombineRgn( updateRgn, updateRgn, newVisRgn, RGN_DIFF );
+     /* Compute combined dirty region (old + new - valid) */
+     CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
+     CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
 
-     /* Blt valid bits using parent window DC */
+     /* Blt valid bits, r is the rect to copy  */
 
-     if( my != NULLREGION && (xfrom != xto || yfrom != yto) )
-       {
-	 
-	 /* compute clipping region in parent client coordinates */
+     if( dx || dy )
+     {
+	 DC* dc;
+         HDC hDC = ( uFlags & SWP_EX_PAINTSELF)
+		   ? GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
+			      DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS )
+		   : GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
+			      DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
+	 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
+	 {
+	    if( oh > nh ) r.bottom = r.top  + nh;
+	    if( ow < nw ) r.right = r.left  + nw;
 
-	 OffsetRgn( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top );
-	 CombineRgn( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
+	    Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
 
-         hDC = GetDCEx( Wnd->parent->hwndSelf, oldVisRgn,
-                          DCX_KEEPCLIPRGN | DCX_INTERSECTRGN |
-                          DCX_CACHE | DCX_CLIPSIBLINGS);
+	    GDI_HEAP_UNLOCK( hDC );
+	 }
+         ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ? 
+		     Wnd->hwndSelf :  Wnd->parent->hwndSelf, hDC); 
+     }
+ }
 
-         BitBlt( hDC, xto, yto, width, height, hDC, xfrom, yfrom, SRCCOPY );
-         ReleaseDC( Wnd->parent->hwndSelf, hDC); 
-       }
+ /* *pVisRgn now points to the invalidated region */
 
-     if( update != NULLREGION )
-         PAINT_RedrawWindow( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
-                         RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
-     else if( uFlags & SMC_DRAWFRAME ) Wnd->flags |= WIN_NEEDS_NCPAINT;
-     DeleteObject( updateRgn );
-   }
-
- /* erase uncovered areas */
-
- if( !(uFlags & SMC_NOPARENTERASE) && (other != NULLREGION ) )
-      PAINT_RedrawWindow( Wnd->parent->hwndSelf, NULL, dirtyRgn,
-                        RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
- DeleteObject(dirtyRgn);
  DeleteObject(newVisRgn);
+ DeleteObject(dirtyRgn);
  return uFlags;
 }
 
 /***********************************************************************
+ *           SWP_DoSimpleFrameChanged
+ */
+static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pNewClientRect, RECT* pOldClientRect )
+{
+    WORD wErase = 0;
+    RECT rect;
+
+    if( pNewClientRect->right > pOldClientRect->right ) /* redraw exposed client area on the right */
+    {
+	rect.top = 0; rect.bottom = pNewClientRect->bottom - pNewClientRect->top;
+	rect.left = pOldClientRect->right - pNewClientRect->left;
+	rect.right = pNewClientRect->right - pNewClientRect->left;
+	wErase = 1;
+	PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | 
+			    RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME );
+     }
+     if( pNewClientRect->bottom > pOldClientRect->bottom ) /* redraw exposed client area on the bottom */
+     {
+	rect.left = 0; rect.right = ((wErase)? pOldClientRect->right : pNewClientRect->right) - pNewClientRect->left;
+	rect.top = pOldClientRect->bottom - pNewClientRect->top;
+	rect.bottom = pNewClientRect->bottom - pNewClientRect->top;
+        wErase = 1;
+        PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | 
+			    RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME );
+     }
+     if( !wErase ) /* IMMEDIATELY update the nonclient area */
+     {
+	HRGN h;
+        if( (h = WIN_UpdateNCRgn(wndPtr, TRUE, TRUE)) > 1) DeleteObject( h );
+     }
+}
+
+/***********************************************************************
+ *           SWP_DoWinPosChanging
+ */
+static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos, 
+				  RECT* pNewWindowRect, RECT* pNewClientRect )
+{
+      /* Send WM_WINDOWPOSCHANGING message */
+
+    if (!(pWinpos->flags & SWP_NOSENDCHANGING))
+        SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
+
+      /* Calculate new position and size */
+
+    *pNewWindowRect = wndPtr->rectWindow;
+    *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
+                                                    : wndPtr->rectClient;
+
+    if (!(pWinpos->flags & SWP_NOSIZE))
+    {
+        pNewWindowRect->right  = pNewWindowRect->left + pWinpos->cx;
+        pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
+    }
+    if (!(pWinpos->flags & SWP_NOMOVE))
+    {
+        pNewWindowRect->left    = pWinpos->x;
+        pNewWindowRect->top     = pWinpos->y;
+        pNewWindowRect->right  += pWinpos->x - wndPtr->rectWindow.left;
+        pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
+
+        OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
+                                    pWinpos->y - wndPtr->rectWindow.top );
+    }
+
+    pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
+    return TRUE;
+}
+
+/***********************************************************************
+ *           SWP_DoNCCalcSize
+ */
+static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
+			      RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
+{
+    UINT wvrFlags = 0;
+
+      /* Send WM_NCCALCSIZE message to get new client area */
+    if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
+    {
+         wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
+                                    &wndPtr->rectWindow, &wndPtr->rectClient,
+                                    pWinpos, pNewClientRect );
+
+         /* FIXME: WVR_ALIGNxxx */
+
+         if( pNewClientRect->left != wndPtr->rectClient.left ||
+             pNewClientRect->top != wndPtr->rectClient.top )
+             pWinpos->flags &= ~SWP_NOCLIENTMOVE;
+
+         if( (pNewClientRect->right - pNewClientRect->left !=
+              wndPtr->rectClient.right - wndPtr->rectClient.left) ||
+             (pNewClientRect->bottom - pNewClientRect->top !=
+              wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
+             pWinpos->flags &= ~SWP_NOCLIENTSIZE;
+    }
+    else
+      if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
+                                pNewClientRect->top != wndPtr->rectClient.top) )
+            pWinpos->flags &= ~SWP_NOCLIENTMOVE;
+    return wvrFlags;
+}
+
+/***********************************************************************
  *           SetWindowPos   (USER.2)
  */
 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
@@ -2324,15 +2346,14 @@
 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
                               INT x, INT y, INT cx, INT cy, WORD flags)
 {
-    WINDOWPOS winpos;
+    WINDOWPOS 	winpos;
     WND *	wndPtr,*wndTemp;
-    RECT 	newWindowRect, newClientRect, oldWindowRect;
+    RECT 	newWindowRect, newClientRect;
+    RECT	oldWindowRect, oldClientRect;
     HRGN	visRgn = 0;
-    HWND	tempInsertAfter= 0;
-    int 	result = 0;
-    UINT 	uFlags = 0;
-    BOOL      resync = FALSE,retvalue;
-    HWND      hwndActive = 0;
+    UINT 	wvrFlags = 0, uFlags = 0;
+    BOOL	retvalue, resync = FALSE;
+    HWND	hwndActive = 0;
 
     /* Get current active window from the active queue */
     if ( hActiveQueue )
@@ -2345,58 +2366,60 @@
         }
     }
 
-    TRACE(win,"hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n", 
+    TRACE(win,"hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n", 
 						 hwnd, x, y, x+cx, y+cy, flags);  
+
+      /* ------------------------------------------------------------------------ CHECKS */
+
       /* Check window handle */
 
     if (hwnd == GetDesktopWindow()) return FALSE;
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
 
+    TRACE(win,"\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
+			  wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
+
+      /* Fix redundant flags */
+
     if(wndPtr->dwStyle & WS_VISIBLE)
         flags &= ~SWP_SHOWWINDOW;
     else
     {
-	uFlags |= SMC_NOPARENTERASE; 
+	if (!(flags & SWP_SHOWWINDOW)) 
+	      flags |= SWP_NOREDRAW;
 	flags &= ~SWP_HIDEWINDOW;
-	if (!(flags & SWP_SHOWWINDOW)) flags |= SWP_NOREDRAW;
     }
 
-/*     Check for windows that may not be resized 
-       FIXME: this should be done only for Windows 3.0 programs 
-       if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
-           flags |= SWP_NOSIZE | SWP_NOMOVE;
-*/
-      /* Check dimensions */
+    if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
 
-    if (cx <= 0) cx = 1;
-    if (cy <= 0) cy = 1;
-
-      /* Check flags */
-
-    if (hwnd == hwndActive) flags |= SWP_NOACTIVATE;   /* Already active */
     if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
         (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
         flags |= SWP_NOSIZE;    /* Already the right size */
+
     if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
         flags |= SWP_NOMOVE;    /* Already the right position */
 
+    if (hwnd == hwndActive)
+        flags |= SWP_NOACTIVATE;   /* Already active */
+    else
+    {
+        if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
+        {
+            flags &= ~SWP_NOZORDER;
+ 	    hwndInsertAfter = HWND_TOP;           
+	    goto Pos;
+        }
+    }
+
       /* Check hwndInsertAfter */
 
-    if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
-    {
-	  /* Ignore TOPMOST flags when activating a window */
-          /* _and_ moving it in Z order. */
-	if ((hwndInsertAfter == HWND_TOPMOST) ||
-            (hwndInsertAfter == HWND_NOTOPMOST))
-	    hwndInsertAfter = HWND_TOP;	
-    }
-      /* TOPMOST not supported yet */
+      /* FIXME: TOPMOST not supported yet */
     if ((hwndInsertAfter == HWND_TOPMOST) ||
         (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
 
       /* hwndInsertAfter must be a sibling of the window */
     if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
-       {
+    {
 	 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
 
 	 if( wnd ) {
@@ -2409,16 +2432,10 @@
 	   if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
 	 }
          WIN_ReleaseWndPtr(wnd);
-       }
-    else if (!X11DRV_WND_GetXWindow(wndPtr))
-    {
-         /* FIXME: the following optimization is no good for "X-ed" windows */
-       if (hwndInsertAfter == HWND_TOP)
-	   flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
-       else /* HWND_BOTTOM */
-	   flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
     }
 
+Pos:  /* ------------------------------------------------------------------------ MAIN part */
+
       /* Fill the WINDOWPOS structure */
 
     winpos.hwnd = hwnd;
@@ -2429,90 +2446,49 @@
     winpos.cy = cy;
     winpos.flags = flags;
     
-      /* Send WM_WINDOWPOSCHANGING message */
+    SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
 
-    if (!(winpos.flags & SWP_NOSENDCHANGING))
-	SendMessageA( hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
-
-      /* Calculate new position and size */
-
-    newWindowRect = wndPtr->rectWindow;
-    newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
-						    : wndPtr->rectClient;
-
-    if (!(winpos.flags & SWP_NOSIZE))
+    if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
     {
-        newWindowRect.right  = newWindowRect.left + winpos.cx;
-        newWindowRect.bottom = newWindowRect.top + winpos.cy;
-    }
-    if (!(winpos.flags & SWP_NOMOVE))
-    {
-        newWindowRect.left    = winpos.x;
-        newWindowRect.top     = winpos.y;
-        newWindowRect.right  += winpos.x - wndPtr->rectWindow.left;
-        newWindowRect.bottom += winpos.y - wndPtr->rectWindow.top;
-
-	OffsetRect( &newClientRect, winpos.x - wndPtr->rectWindow.left, 
-                                      winpos.y - wndPtr->rectWindow.top );
-    }
-
-    winpos.flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
-
-      /* Reposition window in Z order */
-
-    if (!(winpos.flags & SWP_NOZORDER))
-    {
-	/* reorder owned popups if hwnd is top-level window 
-         */
 	if( wndPtr->parent == WIN_GetDesktop() )
-        {
-	    hwndInsertAfter = WINPOS_ReorderOwnedPopups( hwndInsertAfter,
-							 wndPtr, winpos.flags );
-        }
-        WIN_ReleaseDesktop();
-        
-        if (X11DRV_WND_GetXWindow(wndPtr))
-
-        {
-            WIN_UnlinkWindow( winpos.hwnd );
-            WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
-        }
-        else
-	  WINPOS_MoveWindowZOrder( winpos.hwnd, hwndInsertAfter );
+	    hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
+					hwndInsertAfter, winpos.flags );
+	WIN_ReleaseDesktop();
     }
 
-    if ( !X11DRV_WND_GetXWindow(wndPtr) && !(winpos.flags & SWP_NOREDRAW) && 
-	((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED)) 
-		      != (SWP_NOMOVE | SWP_NOSIZE)) )
-          visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
-
-      /* Send WM_NCCALCSIZE message to get new client area */
-    if( (winpos.flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
+    if(!(wndPtr->flags & WIN_NATIVE) )
     {
-         result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
-				    &wndPtr->rectWindow, &wndPtr->rectClient,
-				    &winpos, &newClientRect );
+	if( hwndInsertAfter == HWND_TOP )
+           winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
+	else
+	if( hwndInsertAfter == HWND_BOTTOM )
+	   winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
+	else
+	if( !(winpos.flags & SWP_NOZORDER) )
+	   if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
+	       winpos.flags |= SWP_NOZORDER;
 
-         /* FIXME: WVR_ALIGNxxx */
+	if( !(winpos.flags & SWP_NOREDRAW) &&
+	    ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
+			  != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
+	{
+	    /* get a previous visible region for SWP_CopyValidBits() */
 
-         if( newClientRect.left != wndPtr->rectClient.left ||
-             newClientRect.top != wndPtr->rectClient.top )
-             winpos.flags &= ~SWP_NOCLIENTMOVE;
-
-         if( (newClientRect.right - newClientRect.left !=
-              wndPtr->rectClient.right - wndPtr->rectClient.left) ||
-	     (newClientRect.bottom - newClientRect.top !=
-	      wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
-	     winpos.flags &= ~SWP_NOCLIENTSIZE;
+	    visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
+	}
     }
-    else
-      if( !(flags & SWP_NOMOVE) && (newClientRect.left != wndPtr->rectClient.left ||
-				    newClientRect.top != wndPtr->rectClient.top) )
-	    winpos.flags &= ~SWP_NOCLIENTMOVE;
 
-    /* Update active DCEs 
-     * TODO: Optimize conditions that trigger DCE update.
-     */
+    /* Common operations */
+
+    SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
+
+    if(!(winpos.flags & SWP_NOZORDER))
+    {
+        WIN_UnlinkWindow( winpos.hwnd );
+        WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
+    }
+
+    /* Reset active DCEs */
 
     if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) && 
 					 wndPtr->dwStyle & WS_VISIBLE) || 
@@ -2524,199 +2500,209 @@
 	DCE_InvalidateDCE(wndPtr, &rect);
     }
 
-    /* change geometry */
-
     oldWindowRect = wndPtr->rectWindow;
+    oldClientRect = wndPtr->rectClient;
 
-    if (X11DRV_WND_GetXWindow(wndPtr))
+    if (wndPtr->flags & WIN_NATIVE) 	/* -------------------------------------------- hosted window */
     {
-        RECT oldClientRect = wndPtr->rectClient;
-
-        tempInsertAfter = winpos.hwndInsertAfter;
+	BOOL bCallDriver = TRUE;
+        HWND tempInsertAfter = winpos.hwndInsertAfter;
 
         winpos.hwndInsertAfter = hwndInsertAfter;
 
-	/* postpone geometry change */
-
-	if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
-	{
-              wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
-	      winpos.hwndInsertAfter = tempInsertAfter;
-	}
-	else  uFlags |= SMC_SETXPOS;
-
         wndPtr->rectWindow = newWindowRect;
         wndPtr->rectClient = newClientRect;
 
-	if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
+	if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
         {
-	  if( (oldClientRect.left - oldWindowRect.left !=
-	       newClientRect.left - newWindowRect.left) ||
-	      (oldClientRect.top - oldWindowRect.top !=
-	       newClientRect.top - newWindowRect.top) ||
-              (winpos.flags & SWP_NOCOPYBITS) )
+	  /* This is the only place where we need to force repainting of the contents
+	     of windows created by the host window system, all other cases go through the
+	     expose event handling */
+
+	    if( (winpos.flags & SWP_FRAMECHANGED) )
+	    {
+		INT x, y;
+
+		if( (x = (newWindowRect.right - newWindowRect.left)) == (oldWindowRect.right - oldWindowRect.left) &&
+		    (y = (newWindowRect.bottom - newWindowRect.top)) == (oldWindowRect.bottom - oldWindowRect.top) )
+		{
+
+		    wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
+		    winpos.hwndInsertAfter = tempInsertAfter;
+		    bCallDriver = FALSE;
+
+		    if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
+		        (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top)   )
+			SWP_DoSimpleFrameChanged(wndPtr, &newClientRect, &oldClientRect );
+		    else
+		    {
+		        /* client area moved but window extents remained the same, copy valid bits */
+
+		        visRgn = CreateRectRgn( 0, 0, x, y );
+		        uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect, &oldClientRect, SWP_EX_PAINTSELF);
+		    }
+		}
+	    }
+	}
+
+	if( bCallDriver )
+	{
+	  if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
 	  {
-	      /* if the client area moved as a result of WM_NCCALCSIZE returning 
-	       * obscure WVR_ALIGNxxx flags then we simply redraw the whole thing
-	       *
-	       * TODO: use WINPOS_SizeMoveClean() if there is no SWP_NOCOPYBITS 
-	       */
+	    if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
+		(oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top)   )
+	    {
+		if( !(wndPtr->flags & WIN_MANAGED) ) /* force outer frame redraw */
+		{
+		    HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
+						     newWindowRect.bottom - newWindowRect.top);
+		    RECT rcn = newClientRect;
+		    RECT rco = oldClientRect;
 
-	      PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE |
-                              RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
+		    OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
+		    OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
+		    IntersectRect( &rcn, &rcn, &rco );
+		    visRgn = CreateRectRgnIndirect( &rcn );
+		    CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
+		    DeleteObject( hrgn );
+		    uFlags = SWP_EX_PAINTSELF;
+		}
+		wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
+	    }
+	    else
+		wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
 	  }
-	  else
-	      if( winpos.flags & SWP_FRAMECHANGED )
-	      {
-		WORD wErase = 0;
-		RECT rect;
+	  wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
+	  winpos.hwndInsertAfter = tempInsertAfter;
+	}
 
-	        if( newClientRect.right > oldClientRect.right ) /* redraw exposed client area on the right */
-                {
-		    rect.top = 0; rect.bottom = newClientRect.bottom - newClientRect.top;
-		    rect.left = oldClientRect.right - newClientRect.left;
-		    rect.right = newClientRect.right - newClientRect.left;
-		    wErase = 1;
-		    PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
-                                      RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
+	if( winpos.flags & SWP_SHOWWINDOW )
+	{
+		HWND focus, curr;
+
+		wndPtr->dwStyle |= WS_VISIBLE;
+
+		if (wndPtr->flags & WIN_MANAGED) resync = TRUE; 
+
+		/* focus was set to unmapped window, reset host focus 
+		 * since the window is now visible */
+
+		focus = curr = GetFocus();
+		while (curr) 
+		{
+	    	    if (curr == hwnd) 
+	   	    {
+			WND *pFocus = WIN_FindWndPtr( focus );
+			if (pFocus)
+		    	    pFocus->pDriver->pSetFocus(pFocus);
+			WIN_ReleaseWndPtr(pFocus);
+			break;
+	    	    }
+                    curr = GetParent(curr);
                 }
-		if( newClientRect.bottom > oldClientRect.bottom ) /* redraw exposed client area on the bottom */
-                {
-		    rect.left = 0; rect.right = ((wErase)?oldClientRect.right:newClientRect.right) - newClientRect.left;
-		    rect.top = oldClientRect.bottom - newClientRect.top;
-		    rect.bottom = newClientRect.bottom - newClientRect.top;
-		    wErase = 1;
-		    PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
-                                      RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
-                }
-		if( !wErase ) /* just update the nonclient area */
-                    // the previous command (wndPtr->flags |= WIN_NEEDS_NCPAINT)
-                    // was not enough. Absolutly need a non client update at this point
-                    // Cannot wait for the next WM_PAINT message, particularly in the menu-bar redrawing
-                    WIN_UpdateNCArea(wndPtr,TRUE);
-	      }
         }
-	uFlags |= SMC_NOPARENTERASE; /* X windows do not have eraseable parents */
     }
-    else /* not an X window */
+    else 				/* -------------------------------------------- emulated window */
     {
-	RECT oldClientRect = wndPtr->rectClient;
-
         wndPtr->rectWindow = newWindowRect;
         wndPtr->rectClient = newClientRect;
 
 	if( oldClientRect.bottom - oldClientRect.top ==
-	    newClientRect.bottom - newClientRect.top ) result &= ~WVR_VREDRAW;
+	    newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
 
 	if( oldClientRect.right - oldClientRect.left ==
-	    newClientRect.right - newClientRect.left ) result &= ~WVR_HREDRAW;
+	    newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
 
-        if( !(flags & (SWP_NOREDRAW | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
-	{
-	    uFlags |=  ((winpos.flags & SWP_NOCOPYBITS) || 
-			(result >= WVR_HREDRAW && result < WVR_VALIDRECTS)) ? SMC_NOCOPY : 0;
-	    uFlags |=  (winpos.flags & SWP_FRAMECHANGED) ? SMC_DRAWFRAME : 0;
-
-	    if( (winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) != SWP_AGG_NOGEOMETRYCHANGE )
-		uFlags = WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect, 
-							      &oldClientRect, uFlags);
-	    else
-	    { 
-		/* adjust the frame and do not erase the parent */
-
-		if( winpos.flags & SWP_FRAMECHANGED ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
-		if( winpos.flags & SWP_NOZORDER ) uFlags |= SMC_NOPARENTERASE;
-	    }
-	}
-        DeleteObject(visRgn);
-    }
-
-    if (flags & SWP_SHOWWINDOW)
-    {
-	wndPtr->dwStyle |= WS_VISIBLE;
-        if (X11DRV_WND_GetXWindow(wndPtr))
-        {
-	    HWND focus, curr;
-
-	    wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
-	    if( uFlags & SMC_SETXPOS )
+	    if( winpos.flags & SWP_SHOWWINDOW )
 	    {
-              winpos.hwndInsertAfter = tempInsertAfter;
+		wndPtr->dwStyle |= WS_VISIBLE;
+		uFlags |= SWP_EX_PAINTSELF;
+		visRgn = 1;
 	    }
-
-            if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
-
-	    /* If focus was set to an unmapped window, reset X focus now */
-	    focus = curr = GetFocus();
-	    while (curr) {
-		if (curr == hwnd) {
-		    WND *pFocus = WIN_FindWndPtr( focus );
-		    if (pFocus)
-			pFocus->pDriver->pSetFocus(pFocus);
-                    WIN_ReleaseWndPtr(pFocus);
-		    break;
+	    else if( !(winpos.flags & SWP_NOREDRAW) )
+	    {
+		if( winpos.flags & SWP_HIDEWINDOW )
+		{
+		    if( visRgn > 1 ) /* map to parent */
+			OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
+		    else
+			visRgn = 0;
 		}
-		curr = GetParent(curr);
+		else
+		{
+		    uFlags |=  ((winpos.flags & SWP_NOCOPYBITS) || 
+			(wvrFlags >= WVR_HREDRAW && wvrFlags < WVR_VALIDRECTS)) ? SWP_EX_NOCOPY : 0;
+
+		    if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
+		         uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect, 
+							    &oldClientRect, uFlags);
+	            else
+		    {
+		        if( winpos.flags & SWP_FRAMECHANGED )
+			    SWP_DoSimpleFrameChanged( wndPtr, &newClientRect, &oldClientRect );
+		        if( visRgn )
+		        {
+			    DeleteObject( visRgn );
+			    visRgn = 0;
+		        } 
+		    }
+		}
 	    }
-        }
-        else
-        {
-            if (!(flags & SWP_NOREDRAW))
-                PAINT_RedrawWindow( winpos.hwnd, NULL, 0,
-                                RDW_INVALIDATE | RDW_ALLCHILDREN |
-                                RDW_FRAME | RDW_ERASENOW | RDW_ERASE, 0 );
-        }
     }
-    else if (flags & SWP_HIDEWINDOW)
+
+    if( winpos.flags & SWP_HIDEWINDOW )
     {
-        wndPtr->dwStyle &= ~WS_VISIBLE;
-        if (X11DRV_WND_GetXWindow(wndPtr))
-        {
-	    wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
-	    if( uFlags & SMC_SETXPOS )
-	    {
-              winpos.hwndInsertAfter = tempInsertAfter;
-	    }
-        }
-        else
-        {
-            if (!(flags & SWP_NOREDRAW))
-                PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &oldWindowRect,
-                                    0, RDW_INVALIDATE | RDW_ALLCHILDREN |
-                                       RDW_ERASE | RDW_ERASENOW, 0 );
-	    uFlags |= SMC_NOPARENTERASE;
-        }
+	wndPtr->dwStyle &= ~WS_VISIBLE;
 
 	if (hwnd == CARET_GetHwnd()) DestroyCaret();
 
-        /* FIXME: This will cause the window to be activated irrespective
-         * of whether it is owned by the same thread.
-         * Should this behaviour be allowed in SetWindowPos?
-         */
+	/* FIXME: This will cause the window to be activated irrespective
+	 * of whether it is owned by the same thread. Has to be done
+	 * asynchronously.
+	 */
+
 	if (winpos.hwnd == hwndActive)
 	    WINPOS_ActivateOtherWindow( wndPtr );
     }
 
+    /* ------------------------------------------------------------------------ FINAL */
+
       /* Activate the window */
 
     if (!(flags & SWP_NOACTIVATE))
 	    WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
     
-      /* Repaint the window */
-
-    if (X11DRV_WND_GetXWindow(wndPtr))
-        EVENT_Synchronize();  /* Wait for all expose events */
+    if (wndPtr->flags & WIN_NATIVE)
+        EVENT_Synchronize();  /* Synchronize with the host window system */
 
     if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
         EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
 
     wndTemp = WIN_GetDesktop();
-    if (!(flags & SWP_DEFERERASE) && !(uFlags & SMC_NOPARENTERASE) )
-        PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW, 0 );
-    else if( wndPtr->parent == wndTemp && wndPtr->parent->flags & WIN_NEEDS_ERASEBKGND )
+
+    /* repaint invalidated region (if any) */
+
+    if( visRgn )
     {
-	PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_NOCHILDREN | RDW_ERASENOW, 0 );
+	if( !(winpos.flags & SWP_NOREDRAW) )
+	{
+	    if( uFlags & SWP_EX_PAINTSELF )
+	    {
+		PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE | RDW_FRAME |
+				  ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
+				    RDW_ALLCHILDREN, RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
+	    }
+	    else
+	    {
+		PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE |
+				  ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
+				    RDW_ALLCHILDREN, RDW_EX_USEHRGN );
+	    }
+        }
+	if( visRgn != 1 )
+	    DeleteObject( visRgn );
     }
+
     WIN_ReleaseDesktop();
 
       /* And last, send the WM_WINDOWPOSCHANGED message */
diff --git a/windows/x11drv/event.c b/windows/x11drv/event.c
index 0abcbb4..711bc22 100644
--- a/windows/x11drv/event.c
+++ b/windows/x11drv/event.c
@@ -520,8 +520,7 @@
 /***********************************************************************
  *           EVENT_QueryZOrder
  *
- * Try to synchronize internal z-order with the window manager's.
- * Probably a futile endeavor.
+ * Synchronize internal z-order with the window manager's.
  */
 static BOOL __check_query_condition( WND** pWndA, WND** pWndB )
 {
@@ -540,19 +539,25 @@
 static Window __get_common_ancestor( Window A, Window B,
                                      Window** children, unsigned* total )
 {
-  /* find the real root window */
+    /* find the real root window */
   
-  Window      root, *childrenB;
-  unsigned    totalB;
+    Window      root, *childrenB;
+    unsigned    totalB;
   
-  do
+    do
     {
-      if( *children ) TSXFree( *children );
       TSXQueryTree( display, A, &root, &A, children, total );
       TSXQueryTree( display, B, &root, &B, &childrenB, &totalB );
       if( childrenB ) TSXFree( childrenB );
+      if( *children ) TSXFree( *children );
     } while( A != B && A && B );
-  return ( A && B ) ? A : 0 ;
+
+    if( A && B )
+    {
+	TSXQueryTree( display, A, &root, &B, children, total );
+	return A;
+    }
+    return 0 ;
 }
 
 static Window __get_top_decoration( Window w, Window ancestor )
@@ -573,7 +578,7 @@
 static unsigned __td_lookup( Window w, Window* list, unsigned max )
 {
   unsigned    i;
-  for( i = 0; i < max; i++ ) if( list[i] == w ) break;
+  for( i = max - 1; i >= 0; i-- ) if( list[i] == w ) break;
   return i;
 }
 
@@ -591,32 +596,42 @@
 				  X11DRV_WND_GetXWindow(pWnd),
 				  &children, &total );
   if( parent && children )
-    {
+  {
+      /* w is the ancestor if pWndCheck that is a direct descendant of 'parent' */
+
       w = __get_top_decoration( X11DRV_WND_GetXWindow(pWndCheck), parent );
-      if( w != children[total - 1] )
-        {
+
+      if( w != children[total-1] ) /* check if at the top */
+      {
+	  /* X child at index 0 is at the bottom, at index total-1 is at the top */
 	  check = __td_lookup( w, children, total );
 	  best = total;
+
 	  for( pWnd = pWndZ; pWnd; pWnd = pWnd->next )
-            {
+          {
+	      /* go through all windows in Wine z-order... */
+
 	      if( pWnd != pWndCheck )
-                {
+              {
 		  if( !(pWnd->flags & WIN_MANAGED) ||
 		      !(w = __get_top_decoration( X11DRV_WND_GetXWindow(pWnd), parent )) )
 		    continue;
 		  pos = __td_lookup( w, children, total );
 		  if( pos < best && pos > check )
-                    {
+                  {
+		      /* find a nearest Wine window precedes 
+		       * pWndCheck in the real z-order... */
 		      best = pos;
 		      hwndInsertAfter = pWnd->hwndSelf;
-                    }
-		  if( check - best == 1 ) break;
-                }
-            }
-	  WIN_UnlinkWindow( pWndCheck->hwndSelf );
-	  WIN_LinkWindow( pWndCheck->hwndSelf, hwndInsertAfter);
-        }
-    }
+                  }
+		  if( best - check == 1 ) break;
+              }
+          }
+	  /* and link pWndCheck right behind it in the local z-order */
+      }
+      WIN_UnlinkWindow( pWndCheck->hwndSelf );
+      WIN_LinkWindow( pWndCheck->hwndSelf, hwndInsertAfter);
+  }
   if( children ) TSXFree( children );
   return bRet;
 }
@@ -867,14 +882,17 @@
  */
 static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event )
 {
-  if (event->detail != NotifyPointer)
+    if (event->detail != NotifyPointer)
     {
-      HWND	hwnd = pWnd->hwndSelf;
-      
-      if (hwnd == GetActiveWindow()) 
-	WINPOS_ChangeActiveWindow( 0, FALSE );
-      if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
-	SetFocus( 0 );
+        HWND	hwnd = pWnd->hwndSelf;
+
+        if (hwnd == GetActiveWindow()) 
+	{
+	    SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
+	    WINPOS_ChangeActiveWindow( 0, FALSE );
+	}
+        if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
+	    SetFocus( 0 );
     }
 }
 
@@ -910,13 +928,13 @@
   if (!TSXGetGeometry( display, win, &root, px, py, pwidth, pheight,
                        &border, &depth )) return;
   if (win == X11DRV_GetXRootWindow())
-    {
+  {
       *px = *py = 0;
       return;
-    }
+  }
   
   for (;;)
-    {
+  {
       if (!TSXQueryTree(display, win, &root, &parent, &children, &nb_children))
 	return;
       TSXFree( children );
@@ -926,7 +944,7 @@
                            &width, &height, &border, &depth )) return;
       *px += xpos;
       *py += ypos;
-    }
+  }
 }
 
 
@@ -940,7 +958,7 @@
 {
   WINDOWPOS winpos;
   RECT newWindowRect, newClientRect;
-  HRGN hrgnOldPos, hrgnNewPos;
+  RECT oldWindowRect, oldClientRect;
   Window above = event->above;
   int x, y;
   unsigned int width, height;
@@ -953,6 +971,9 @@
    */
   EVENT_GetGeometry( event->window, &x, &y, &width, &height );
     
+TRACE(win, "%04x adjusted to (%i,%i)-(%i,%i)\n", pWnd->hwndSelf, 
+	    x, y, x + width, y + height );
+
   /* Fill WINDOWPOS struct */
   winpos.flags = SWP_NOACTIVATE | SWP_NOZORDER;
   winpos.hwnd = pWnd->hwndSelf;
@@ -991,15 +1012,20 @@
   
   if (!IsWindow( winpos.hwnd )) return;
   
-  hrgnOldPos = CreateRectRgnIndirect( &pWnd->rectWindow );
-  hrgnNewPos = CreateRectRgnIndirect( &newWindowRect );
-  CombineRgn( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
-  DeleteObject(hrgnOldPos);
-  DeleteObject(hrgnNewPos);
-  
+  oldWindowRect = pWnd->rectWindow;
+  oldClientRect = pWnd->rectClient;
+
   /* Set new size and position */
   pWnd->rectWindow = newWindowRect;
   pWnd->rectClient = newClientRect;
+
+  /* FIXME: Copy valid bits */
+
+  if( oldClientRect.top - oldWindowRect.top != newClientRect.top - newWindowRect.top ||
+      oldClientRect.left - oldWindowRect.left != newClientRect.left - newWindowRect.left )
+      RedrawWindow( winpos.hwnd, 0, NULL, RDW_FRAME | RDW_ALLCHILDREN |
+                                          RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW );
+
   SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
   
   if (!IsWindow( winpos.hwnd )) return;
diff --git a/windows/x11drv/init.c b/windows/x11drv/init.c
index e7ac2db..ead5570 100644
--- a/windows/x11drv/init.c
+++ b/windows/x11drv/init.c
@@ -84,8 +84,9 @@
   X11DRV_WND_SetFocus,
   X11DRV_WND_PreSizeMove,
   X11DRV_WND_PostSizeMove,
-  X11DRV_WND_ScrollWindow,
+  X11DRV_WND_SurfaceCopy,
   X11DRV_WND_SetDrawable,
+  X11DRV_WND_SetHostAttr,
   X11DRV_WND_IsSelfClipping
 };
 
diff --git a/windows/x11drv/wnd.c b/windows/x11drv/wnd.c
index a6485bd..fece839 100644
--- a/windows/x11drv/wnd.c
+++ b/windows/x11drv/wnd.c
@@ -170,7 +170,9 @@
   
   if (!(cs->style & WS_CHILD) && 
       (X11DRV_WND_GetXRootWindow(wndPtr) == DefaultRootWindow(display)))
-    {
+  {
+      Window    wGroupLeader;
+      XWMHints* wm_hints;
       XSetWindowAttributes win_attr;
       
       if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
@@ -191,10 +193,15 @@
 	    FocusChangeMask;
 	  win_attr.override_redirect = TRUE;
 	}
+      wndPtr->flags |= WIN_NATIVE;
+
+      win_attr.bit_gravity   = BGNorthWest;
       win_attr.colormap      = X11DRV_COLOR_GetColormap();
       win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
       win_attr.save_under    = ((classPtr->style & CS_SAVEBITS) != 0);
       win_attr.cursor        = X11DRV_MOUSE_XCursor;
+
+      ((X11DRV_WND_DATA *) wndPtr->pDriverData)->bit_gravity = BGNorthWest;
       ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = 
 	TSXCreateWindow( display, 
 			 X11DRV_WND_GetXRootWindow(wndPtr), 
@@ -203,9 +210,10 @@
 			 InputOutput, CopyFromParent,
 			 CWEventMask | CWOverrideRedirect |
 			 CWColormap | CWCursor | CWSaveUnder |
-			 CWBackingStore, &win_attr );
+			 CWBackingStore | CWBitGravity, 
+			 &win_attr );
       
-      if(!X11DRV_WND_GetXWindow(wndPtr))
+      if(!(wGroupLeader = X11DRV_WND_GetXWindow(wndPtr)))
 	return FALSE;
 
       if (wndPtr->flags & WIN_MANAGED) {
@@ -233,14 +241,36 @@
       }
       
       if (cs->hwndParent)  /* Get window owner */
-	{
+      {
+	  Window w;
           WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
-	  Window win = X11DRV_WND_FindXWindow( tmpWnd );
-	  if (win) TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), win );
+
+	  w = X11DRV_WND_FindXWindow( tmpWnd );
+	  if (w != None)
+	  {
+	      TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), w );
+	      wGroupLeader = w;
+	  }
           WIN_ReleaseWndPtr(tmpWnd);
-	}
+      }
+
+      wm_hints = TSXAllocWMHints();
+      {
+	  wm_hints->flags = InputHint | StateHint | WindowGroupHint;
+	  wm_hints->input = True;
+	  if( wndPtr->dwStyle & WS_VISIBLE )
+	      wm_hints->initial_state = (wndPtr->dwStyle & WS_MINIMIZE &&
+					wndPtr->flags & WIN_MANAGED ) ? 
+					IconicState : NormalState;
+	  else
+	      wm_hints->initial_state = WithdrawnState;
+	  wm_hints->window_group = wGroupLeader;
+
+	  TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
+	  TSXFree(wm_hints);
+      }
       X11DRV_WND_RegisterWindow( wndPtr );
-    }
+  }
   return TRUE;
 }
 
@@ -400,26 +430,26 @@
  *
  * SetWindowPos() for an X window. Used by the real SetWindowPos().
  */
-void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bSMC_SETXPOS)
+void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bChangePos)
 {
-  XWindowChanges winChanges;
-  int changeMask = 0;
-  WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
+    XWindowChanges winChanges;
+    int changeMask = 0;
+    WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
 
-  if(!wndPtr->hwndSelf) wndPtr = NULL; /* FIXME: WND destroyed, shouldn't happend!!! */
+    if(!wndPtr->hwndSelf) wndPtr = NULL; /* FIXME: WND destroyed, shouldn't happend!!! */
   
-  if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
+    if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
     {
       if(X11DRV_WND_GetXWindow(wndPtr)) 
 	TSXUnmapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
     }
 
-  if(bSMC_SETXPOS)
+    if(bChangePos)
     {
       if ( !(winpos->flags & SWP_NOSIZE))
 	{
-	  winChanges.width     = winpos->cx;
-	  winChanges.height    = winpos->cy;
+	  winChanges.width     = (winpos->cx > 0 ) ? winpos->cx : 1;
+	  winChanges.height    = (winpos->cy > 0 ) ? winpos->cy : 1;
 	  changeMask |= CWWidth | CWHeight;
 	  
 	  /* Tweak dialog window size hints */
@@ -477,11 +507,11 @@
 	}
     }
 
-  if ( winpos->flags & SWP_SHOWWINDOW )
+    if ( winpos->flags & SWP_SHOWWINDOW )
     {
       if(X11DRV_WND_GetXWindow(wndPtr)) TSXMapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
     }
-  WIN_ReleaseWndPtr(winposPtr);
+    WIN_ReleaseWndPtr(winposPtr);
 }
 
 /*****************************************************************
@@ -555,31 +585,32 @@
 }
 
 /*****************************************************************
- *		 X11DRV_WND_ScrollWindow
+ *		 X11DRV_WND_SurfaceCopy
+ *
+ * Copies rect to (rect.left + dx, rect.top + dy). 
  */
-void X11DRV_WND_ScrollWindow(
-  WND *wndPtr, DC *dcPtr, INT dx, INT dy, 
-  const RECT *rect, BOOL bUpdate)
+void X11DRV_WND_SurfaceCopy(WND* wndPtr, DC *dcPtr, INT dx, INT dy, 
+			    const RECT *rect, BOOL bUpdate)
 {
-  X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
-  POINT dst, src;
+    X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
+    POINT dst, src;
   
-  dst.x = (src.x = dcPtr->w.DCOrgX + rect->left) + dx;
-  dst.y = (src.y = dcPtr->w.DCOrgY + rect->top) + dy;
+    dst.x = (src.x = dcPtr->w.DCOrgX + rect->left) + dx;
+    dst.y = (src.y = dcPtr->w.DCOrgY + rect->top) + dy;
   
-  if (bUpdate) /* handles non-Wine windows hanging over the scrolled area */
-    TSXSetGraphicsExposures( display, physDev->gc, True );
-  TSXSetFunction( display, physDev->gc, GXcopy );
-  TSXCopyArea( display, physDev->drawable, physDev->drawable,
-               physDev->gc, src.x, src.y,
-               rect->right - rect->left,
-               rect->bottom - rect->top,
-               dst.x, dst.y );
-  if (bUpdate)
-    TSXSetGraphicsExposures( display, physDev->gc, False );
+    if (bUpdate) /* handles non-Wine windows hanging over the copied area */
+	TSXSetGraphicsExposures( display, physDev->gc, True );
+    TSXSetFunction( display, physDev->gc, GXcopy );
+    TSXCopyArea( display, physDev->drawable, physDev->drawable,
+                 physDev->gc, src.x, src.y,
+                 rect->right - rect->left,
+                 rect->bottom - rect->top,
+                 dst.x, dst.y );
+    if (bUpdate)
+	TSXSetGraphicsExposures( display, physDev->gc, False );
 
-  if (bUpdate) /* Make sure exposure events have been processed */
-    EVENT_Synchronize();
+    if (bUpdate) /* Make sure exposure events have been processed */
+	EVENT_Synchronize();
 }
 
 /***********************************************************************
@@ -634,6 +665,50 @@
 }
 
 /***********************************************************************
+ *              X11DRV_WND_SetHostAttr
+ */
+BOOL X11DRV_WND_SetHostAttr(WND* wnd, INT ha, INT value)
+{
+    Window w;
+
+    if( (w = X11DRV_WND_GetXWindow(wnd)) )
+    {
+	XSetWindowAttributes win_attr;
+
+	switch( ha )
+	{
+	case HAK_BITGRAVITY:
+
+		    if( ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity != value )
+		    {
+		        win_attr.bit_gravity = value;
+		        ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity = value;
+		        TSXChangeWindowAttributes( display, w, CWBitGravity, &win_attr );
+		    }
+		    return TRUE;
+
+	case HAK_ACCEPTFOCUS:
+
+		if( (wnd->flags & WIN_MANAGED) )
+		{
+		    XWMHints* wm_hints = TSXAllocWMHints();
+
+		    if( wm_hints )
+		    {
+			wm_hints->flags = InputHint;
+			wm_hints->input = value;
+			TSXSetWMHints( display, X11DRV_WND_GetXWindow(wnd), wm_hints );
+			TSXFree( wm_hints );
+			return TRUE;
+		    }
+		}
+		break;
+	}
+    }
+    return FALSE;
+}
+
+/***********************************************************************
  *		X11DRV_WND_IsSelfClipping
  */
 BOOL X11DRV_WND_IsSelfClipping(WND *wndPtr)