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/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 */