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/controls/menu.c b/controls/menu.c
index 7c06d6d..cd406b4 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -3791,6 +3791,10 @@
  */
 void WINAPI EndMenu(void)
 {
+    /*
+     * FIXME: NOT ENOUGH! This has to cancel menu tracking right away.
+     */
+
     fEndMenu = TRUE;
 }
 
diff --git a/include/region.h b/include/region.h
index 42ddff8..db321b2 100644
--- a/include/region.h
+++ b/include/region.h
@@ -378,6 +378,7 @@
 
 extern BOOL REGION_DeleteObject( HRGN hrgn, RGNOBJ * obj );
 extern BOOL REGION_UnionRectWithRgn( HRGN hrgn, const RECT *lpRect );
+extern HRGN REGION_CropRgn( HRGN hDst, HRGN hSrc, const RECT *lpRect, const POINT *lpPt );
 extern BOOL REGION_FrameRgn( HRGN dest, HRGN src, INT x, INT y );
 extern BOOL REGION_LPTODP( HDC hdc, HRGN hDest, HRGN hSrc );
 
diff --git a/include/ts_xf86vmode.h b/include/ts_xf86vmode.h
index 0531d4c..f209e22 100644
--- a/include/ts_xf86vmode.h
+++ b/include/ts_xf86vmode.h
@@ -16,6 +16,7 @@
 #include "windef.h"
 #ifdef HAVE_LIBXXF86VM
 #define XMD_H
+#define INT32 INT
 
 #include <X11/Xlib.h>
 #include <X11/extensions/xf86vmode.h>
diff --git a/include/ts_xutil.h b/include/ts_xutil.h
index 73238e7..3099a0f 100644
--- a/include/ts_xutil.h
+++ b/include/ts_xutil.h
@@ -38,6 +38,7 @@
 extern int  TSXRectInRegion(Region, int, int, unsigned int, unsigned int);
 extern int  TSXSaveContext(Display*, XID, XContext, const  char*);
 extern int  TSXSetClassHint(Display*, Window, XClassHint*);
+extern int  TSXSetWMHints(Display*, Window, XWMHints*);
 extern void  TSXSetWMProperties(Display*, Window, XTextProperty*, XTextProperty*, char**, int, XSizeHints*, XWMHints*, XClassHint*);
 extern void  TSXSetWMSizeHints(Display*, Window, XSizeHints*, Atom);
 extern int  TSXSetRegion(Display*, GC, Region);
diff --git a/include/ttydrv.h b/include/ttydrv.h
index 5d47474..abef5bc 100644
--- a/include/ttydrv.h
+++ b/include/ttydrv.h
@@ -121,6 +121,7 @@
 extern void TTYDRV_WND_PostSizeMove(struct tagWND *wndPtr);
 extern void TTYDRV_WND_ScrollWindow(struct tagWND *wndPtr, struct tagDC *dcPtr, INT dx, INT dy, const RECT *clipRect, BOOL bUpdate);
 extern void TTYDRV_WND_SetDrawable(struct tagWND *wndPtr, struct tagDC *dc, WORD flags, BOOL bSetClipOrigin);
+extern BOOL TTYDRV_WND_SetHostAttr(struct tagWND *wndPtr, INT haKey, INT value);
 extern BOOL TTYDRV_WND_IsSelfClipping(struct tagWND *wndPtr);
 
 #endif /* !defined(__WINE_TTYDRV_H) */
diff --git a/include/win.h b/include/win.h
index 95133d7..5d166842 100644
--- a/include/win.h
+++ b/include/win.h
@@ -44,8 +44,10 @@
 } BUILTIN_CLASS32;
 
   /* PAINT_RedrawWindow() control flags */
-#define RDW_C_USEHRGN		0x0001
-#define RDW_C_DELETEHRGN	0x0002
+#define RDW_EX_USEHRGN		0x0001
+#define RDW_EX_DELETEHRGN	0x0002
+#define RDW_EX_XYWINDOW		0x0004
+#define RDW_EX_TOPFRAME		0x0010
 
 struct tagCLASS;
 struct tagDCE;
@@ -86,6 +88,25 @@
     DWORD          wExtra[1];     /* Window extra bytes */
 } WND;
 
+/* Host attributes */
+
+#define HAK_BITGRAVITY     1
+#define HAK_ACCEPTFOCUS	   2
+
+/* Bit Gravity */
+
+#define BGForget           0
+#define BGNorthWest        1
+#define BGNorth            2
+#define BGNorthEast        3
+#define BGWest             4
+#define BGCenter           5
+#define BGEast             6
+#define BGSouthWest        7
+#define BGSouth            8
+#define BGSouthEast        9
+#define BGStatic           10
+
 typedef struct _WND_DRIVER
 {
     void   (*pInitialize)(WND *);
@@ -100,8 +121,9 @@
     void   (*pSetFocus)(WND *);
     void   (*pPreSizeMove)(WND *);
     void   (*pPostSizeMove)(WND *);
-    void   (*pScrollWindow)(WND *, struct tagDC *, INT, INT, const RECT *, BOOL);
+    void   (*pSurfaceCopy)(WND *, struct tagDC *, INT, INT, const RECT *, BOOL);
     void   (*pSetDrawable)(WND *, struct tagDC *, WORD, BOOL);
+    BOOL   (*pSetHostAttr)(WND *, INT haKey, INT value);
     BOOL (*pIsSelfClipping)(WND *);
 } WND_DRIVER;
 
@@ -119,13 +141,12 @@
 #define WIN_NEEDS_NCPAINT      0x0004 /* WM_NCPAINT must be sent to window */
 #define WIN_RESTORE_MAX        0x0008 /* Maximize when restoring */
 #define WIN_INTERNAL_PAINT     0x0010 /* Internal WM_PAINT message pending */
-/* Used to have WIN_NO_REDRAW  0x0020 here */
+#define WIN_NATIVE	       0x0020 /* Directly mapped to the window provided by the driver */
 #define WIN_NEED_SIZE          0x0040 /* Internal WM_SIZE is needed */
 #define WIN_NCACTIVATED        0x0080 /* last WM_NCACTIVATE was positive */
-#define WIN_MANAGED            0x0100 /* Window managed by the X wm */
+#define WIN_MANAGED            0x0100 /* Window managed by the window system */
 #define WIN_ISDIALOG           0x0200 /* Window is a dialog */
 #define WIN_ISWIN32            0x0400 /* Understands Win32 messages */
-#define WIN_SAVEUNDER_OVERRIDE 0x0800
 
   /* BuildWinArray() flags */
 #define BWA_SKIPDISABLED	0x0001
@@ -170,7 +191,7 @@
 extern BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
                                   HRGN hrgnUpdate, UINT flags,
                                   UINT control );		      /* windows/painting.c */
-extern void WIN_UpdateNCArea(WND* wnd, BOOL bUpdate);
+extern HRGN WIN_UpdateNCRgn(WND* wnd, BOOL bUpdate, BOOL bForce);     /* windows/painting.c */
 
 
 /* controls/widgets.c */
diff --git a/include/x11drv.h b/include/x11drv.h
index 153b6c5..deb9270 100644
--- a/include/x11drv.h
+++ b/include/x11drv.h
@@ -328,6 +328,7 @@
 
 typedef struct _X11DRV_WND_DATA {
   Window window;
+  int bit_gravity;
 } X11DRV_WND_DATA;
 
 extern Window X11DRV_WND_GetXWindow(struct tagWND *wndPtr);
@@ -347,8 +348,9 @@
 extern void X11DRV_WND_SetFocus(struct tagWND *wndPtr);
 extern void X11DRV_WND_PreSizeMove(struct tagWND *wndPtr);
 extern void X11DRV_WND_PostSizeMove(struct tagWND *wndPtr);
-extern void X11DRV_WND_ScrollWindow(struct tagWND *wndPtr, struct tagDC *dcPtr, INT dx, INT dy, const RECT *clipRect, BOOL bUpdate);
+extern void X11DRV_WND_SurfaceCopy(struct tagWND *wndPtr, struct tagDC *dcPtr, INT dx, INT dy, const RECT *clipRect, BOOL bUpdate);
 extern void X11DRV_WND_SetDrawable(struct tagWND *wndPtr, struct tagDC *dc, WORD flags, BOOL bSetClipOrigin);
+extern BOOL X11DRV_WND_SetHostAttr(struct tagWND *wndPtr, INT haKey, INT value);
 extern BOOL X11DRV_WND_IsSelfClipping(struct tagWND *wndPtr);
 
 #endif  /* __WINE_X11DRV_H */
diff --git a/objects/region.c b/objects/region.c
index 3e32b81..6a92c21 100644
--- a/objects/region.c
+++ b/objects/region.c
@@ -4,6 +4,7 @@
  *
  * Copyright 1993, 1994, 1995 Alexandre Julliard
  * Modifications and additions: Copyright 1998 Huw Davies
+ *					  1999 Alex Korobka
  *
  */
 
@@ -99,6 +100,7 @@
 static void REGION_XorRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2);
 static void REGION_UnionRectWithRegion(const RECT *rect, WINEREGION *rgn);
 
+#define RGN_DEFAULT_RECTS	2
 
 /***********************************************************************
  *            REGION_DumpRegion
@@ -117,47 +119,50 @@
     return;
 }
 
+
 /***********************************************************************
  *            REGION_AllocWineRegion
  *            Create a new empty WINEREGION.
  */
-static WINEREGION *REGION_AllocWineRegion( void )    
+static WINEREGION *REGION_AllocWineRegion( INT n )
 {
     WINEREGION *pReg;
 
     if ((pReg = HeapAlloc(SystemHeap, 0, sizeof( WINEREGION ))))
     {
-	if ((pReg->rects = HeapAlloc(SystemHeap, 0, sizeof( RECT ))))
-	{
-	    pReg->size = 1;
-	    EMPTY_REGION(pReg);
-	    return pReg;
-	}
-	HeapFree(SystemHeap, 0, pReg);
+        if ((pReg->rects = HeapAlloc(SystemHeap, 0, n * sizeof( RECT ))))
+        {
+            pReg->size = n;
+            EMPTY_REGION(pReg);
+            return pReg;
+        }
+        HeapFree(SystemHeap, 0, pReg);
     }
     return NULL;
 }
 
+
 /***********************************************************************
  *          REGION_CreateRegion
  *          Create a new empty region.
  */
-static HRGN REGION_CreateRegion(void)
+static HRGN REGION_CreateRegion( INT n )
 {
     HRGN hrgn;
     RGNOBJ *obj;
-    
+
     if(!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )))
-	return 0;
+        return 0;
     obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
-    if(!(obj->rgn = REGION_AllocWineRegion())) {
-	GDI_FreeObject( hrgn );
-	return 0;
+    if(!(obj->rgn = REGION_AllocWineRegion(n))) {
+        GDI_FreeObject( hrgn );
+        return 0;
     }
     GDI_HEAP_UNLOCK( hrgn );
     return hrgn;
 }
 
+
 /***********************************************************************
  *           REGION_DestroyWineRegion
  */
@@ -194,14 +199,14 @@
 {
     RGNOBJ * obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
 
-    if (obj)
+    if (obj && (x || y))
     {
 	INT ret;
 	int nbox = obj->rgn->numRects;
 	RECT *pbox = obj->rgn->rects;
 	
 	TRACE(region, " %04x %d,%d\n", hrgn, x, y );
-	if(nbox && (x || y)) {
+	if(nbox) {
 	    while(nbox--) {
 	        pbox->left += x;
 		pbox->right += x;
@@ -264,7 +269,7 @@
 {
     HRGN16 hrgn;
 
-    if (!(hrgn = (HRGN16)REGION_CreateRegion()))
+    if (!(hrgn = (HRGN16)REGION_CreateRegion(RGN_DEFAULT_RECTS)))
 	return 0;
     TRACE(region, "\n");
     SetRectRgn16(hrgn, left, top, right, bottom);
@@ -279,7 +284,9 @@
 {
     HRGN hrgn;
 
-    if (!(hrgn = REGION_CreateRegion()))
+    /* Allocate 2 rects by default to reduce the number of reallocs */
+
+    if (!(hrgn = REGION_CreateRegion(RGN_DEFAULT_RECTS)))
 	return 0;
     TRACE(region, "\n");
     SetRectRgn(hrgn, left, top, right, bottom);
@@ -399,7 +406,8 @@
 
       /* Create region */
 
-    if (!(hrgn = REGION_CreateRegion())) return 0;
+    d = (ellipse_height < 128) ? ((3 * ellipse_height) >> 2) : 64;
+    if (!(hrgn = REGION_CreateRegion(d))) return 0;
     obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
     TRACE(region,"(%d,%d-%d,%d %dx%d): ret=%04x\n",
 	       left, top, right, bottom, ellipse_width, ellipse_height, hrgn );
@@ -574,34 +582,38 @@
  */
 HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA* rgndata)
 {
-    HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
-    RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
-    RECT *pCurRect, *pEndRect;
+    HRGN hrgn;
 
-    TRACE(region, " %p %ld %p. Returning %04x\n",
-		   lpXform, dwCount, rgndata, hrgn);
-    if(!hrgn)
-    {
-        WARN(region, "Can't create a region!\n");
-	return 0;
-    }
-    if(lpXform)
-        WARN(region, "Xform not implemented - ignoring\n");
+    TRACE(region, " %p %ld %p = ", lpXform, dwCount, rgndata );
+
+    if( lpXform )
+        WARN(region, "(Xform not implemented - ignored) ");
     
-    if(rgndata->rdh.iType != RDH_RECTANGLES)
+    if( rgndata->rdh.iType != RDH_RECTANGLES )
     {
-        WARN(region, "Type not RDH_RECTANGLES\n");
-	GDI_HEAP_UNLOCK( hrgn );
-	DeleteObject( hrgn );
-	return 0;
+	/* FIXME: We can use CreatePolyPolygonRgn() here
+	 *        for trapezoidal data */
+
+        WARN(region, "(Unsupported region data) ");
+	goto fail;
     }
 
-    pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
-    for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
-        REGION_UnionRectWithRegion( pCurRect, obj->rgn );
+    if( (hrgn = REGION_CreateRegion( rgndata->rdh.nCount )) )
+    {
+	RECT *pCurRect, *pEndRect;
+	RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
 
-    GDI_HEAP_UNLOCK( hrgn );
-    return hrgn;
+	pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
+	for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
+	    REGION_UnionRectWithRegion( pCurRect, obj->rgn );
+	GDI_HEAP_UNLOCK( hrgn );
+
+	TRACE(region,"%04x\n", hrgn );
+	return hrgn;
+    }
+fail:
+    WARN(region, "Failed\n");
+    return 0;
 }
 
 /***********************************************************************
@@ -1402,7 +1414,7 @@
      * Only do this stuff if the number of rectangles allocated is more than
      * twice the number of rectangles in the region (a simple optimization...).
      */
-    if (newReg->numRects < (newReg->size >> 1))
+    if ((newReg->numRects < (newReg->size >> 1)) && (newReg->numRects > 2))
     {
 	if (REGION_NOT_EMPTY(newReg))
 	{
@@ -1916,8 +1928,8 @@
 {
     WINEREGION *tra, *trb;
 
-    if ((! (tra = REGION_AllocWineRegion())) || 
-	(! (trb = REGION_AllocWineRegion())))
+    if ((! (tra = REGION_AllocWineRegion(sra->numRects + 1))) || 
+	(! (trb = REGION_AllocWineRegion(srb->numRects + 1))))
 	return;
     REGION_SubtractRegion(tra,sra,srb);
     REGION_SubtractRegion(trb,srb,sra);
@@ -2357,7 +2369,7 @@
     int numFullPtBlocks = 0;
     INT poly, total;
 
-    if(!(hrgn = REGION_CreateRegion()))
+    if(!(hrgn = REGION_CreateRegion(nbpolygons)))
         return 0;
     obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
     region = obj->rgn;
@@ -2568,3 +2580,205 @@
 
     return 0;
 }
+
+/***********************************************************************
+ *           REGION_CropAndOffsetRegion
+ */
+static BOOL REGION_CropAndOffsetRegion(const POINT* off, const RECT *rect, WINEREGION *rgnSrc, WINEREGION* rgnDst)
+{
+    if( IsRectEmpty(rect) || !EXTENTCHECK(rect, &rgnSrc->extents) )
+    {
+empty:
+	if( !rgnDst->rects )
+	{
+	    rgnDst->rects = HeapAlloc(SystemHeap, 0, sizeof( RECT ));
+	    if( rgnDst->rects )
+		rgnDst->size = 1;
+	    else
+		return FALSE;
+	}
+
+	TRACE(region,"cropped to empty!\n");
+	EMPTY_REGION(rgnDst);
+    }
+    else /* region box and clipping rect appear to intersect */
+    {
+	RECT *lpr;
+	INT i, j, clipa, clipb;
+	INT left = rgnSrc->extents.right + off->x;
+	INT right = rgnSrc->extents.left + off->x;
+
+	for( clipa = 0; rgnSrc->rects[clipa].bottom <= rect->top; clipa++ )
+	     ; /* skip bands above the clipping rectangle */
+
+	for( clipb = clipa; clipb < rgnSrc->numRects; clipb++ )
+	     if( rgnSrc->rects[clipb].top >= rect->bottom )
+		 break;    /* and below it */
+
+	/* clipa - index of the first rect in the first intersecting band
+	 * clipb - index of the last rect in the last intersecting band
+	 */
+
+	if((rgnDst != rgnSrc) && (rgnDst->size < (i = (clipb - clipa))))
+	{
+	    rgnDst->rects = HeapReAlloc( SystemHeap, 0, 
+				rgnDst->rects, i * sizeof(RECT));
+	    if( !rgnDst->rects ) return FALSE;
+	    rgnDst->size = i;
+	}
+
+	if( TRACE_ON(region) )
+	{
+	    REGION_DumpRegion( rgnSrc );
+	    TRACE(region,"\tclipa = %i, clipb = %i\n", clipa, clipb );
+	}
+
+	for( i = clipa, j = 0; i < clipb ; i++ )
+	{
+	     /* i - src index, j - dst index, j is always <= i for obvious reasons */
+
+	     lpr = rgnSrc->rects + i;
+	     if( lpr->left < rect->right && lpr->right > rect->left )
+	     {
+		 rgnDst->rects[j].top = lpr->top + off->y;
+		 rgnDst->rects[j].bottom = lpr->bottom + off->y;
+		 rgnDst->rects[j].left = ((lpr->left > rect->left) ? lpr->left : rect->left) + off->x;
+		 rgnDst->rects[j].right = ((lpr->right < rect->right) ? lpr->right : rect->right) + off->x;
+
+		 if( rgnDst->rects[j].left < left ) left = rgnDst->rects[j].left;
+		 if( rgnDst->rects[j].right > right ) right = rgnDst->rects[j].right;
+
+		 j++;
+	     }
+	}
+
+	if( j == 0 ) goto empty;
+
+        rgnDst->extents.left = left;
+        rgnDst->extents.right = right;
+
+	left = rect->top + off->y;
+	right = rect->bottom + off->y;
+
+	rgnDst->numRects = j--;
+	for( i = 0; i <= j; i++ )	/* fixup top band */
+	     if( rgnDst->rects[i].top < left )
+		 rgnDst->rects[i].top = left;
+	     else
+		 break;
+
+	for( i = j; i >= 0; i-- )	/* fixup bottom band */
+	     if( rgnDst->rects[i].bottom > right )
+		 rgnDst->rects[i].bottom = right;
+	     else
+		 break;
+
+	rgnDst->extents.top = rgnDst->rects[0].top;
+	rgnDst->extents.bottom = rgnDst->rects[j].bottom;
+
+	rgnDst->type = (j >= 1) ? COMPLEXREGION : SIMPLEREGION;
+
+	if( TRACE_ON(region) )
+	{
+	    TRACE(region,"result:\n");
+	    REGION_DumpRegion( rgnDst );
+	}
+    }
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *           REGION_CropRgn
+ *
+ *
+ * hSrc: 	Region to crop and offset.
+ * lpRect: 	Clipping rectangle.
+ * lpPt:	Points to offset the cropped region. Can be NULL.
+ *
+ * hDst: Region to hold the result (if 0 a new region is created).
+ *       Allowed to be the same region as hSrc (in place, no extra memory needed).
+ *
+ * Returns: hDst if success, 0 otherwise.
+ */
+HRGN REGION_CropRgn( HRGN hDst, HRGN hSrc, const RECT *lpRect, const POINT *lpPt )
+{
+/*  Optimization of the following generic code:
+
+    HRGN h = CreateRectRgn( lpRect->left, lpRect->top, lpRect->right, lpRect->bottom );
+    if( hDst == 0 ) hDst = h;
+    CombineRgn( hDst, hSrc, h, RGN_AND );
+    if( lpPt )
+	OffsetRgn( hDst, lpPt->x, lpPt->y );
+    if( hDst != h )
+	DeleteObject( h );
+    return hDst;
+
+*/
+
+    RGNOBJ *objSrc = (RGNOBJ *) GDI_HEAP_LOCK( hSrc );
+
+    if(objSrc)
+    {
+ 	RGNOBJ *objDst;
+	WINEREGION *rgnDst;
+
+	if( hDst )
+	{
+	    objDst = (RGNOBJ *) GDI_HEAP_LOCK( hDst );
+	    rgnDst = objDst->rgn;
+	}
+	else
+	{
+	    rgnDst = HeapAlloc(SystemHeap, 0, sizeof( WINEREGION ));
+	    if( rgnDst ) 
+	    {
+	        rgnDst->size = rgnDst->numRects = 0;
+	        rgnDst->rects = NULL;	/* back end will allocate exact number */
+	    }
+	}
+
+	if( rgnDst )
+	{
+	    POINT pt = { 0, 0 };
+
+	    if( !lpPt ) lpPt = &pt;
+
+	    TRACE(region, "src %p -> dst %p (%i,%i)-(%i,%i) by (%li,%li)\n", objSrc->rgn, rgnDst,
+			   lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, lpPt->x, lpPt->y );
+
+	    if( REGION_CropAndOffsetRegion( lpPt, lpRect, objSrc->rgn, rgnDst ) == FALSE )
+	    {
+		if( hDst ) /* existing rgn */
+		{
+		    GDI_HEAP_UNLOCK(hDst);
+		    hDst = 0;
+		    goto done;
+		}
+		goto fail;
+	    }
+	    else if( hDst == 0 )
+	    {
+		if(!(hDst = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )))
+		{
+fail:
+		    if( rgnDst->rects )
+			HeapFree( SystemHeap, 0, rgnDst->rects );
+		    HeapFree( SystemHeap, 0, rgnDst );
+		    goto done;
+		}
+
+		objDst = (RGNOBJ *) GDI_HEAP_LOCK( hDst );
+		objDst->rgn = rgnDst;
+	    }
+
+	    GDI_HEAP_UNLOCK(hDst);
+	}
+	else hDst = 0;
+done:
+	GDI_HEAP_UNLOCK(hSrc);
+	return hDst;
+    }
+    return 0;
+}
+
diff --git a/tools/make_X11wrappers b/tools/make_X11wrappers
index 477c694..4ecffae 100755
--- a/tools/make_X11wrappers
+++ b/tools/make_X11wrappers
@@ -69,7 +69,7 @@
     if($name eq "xf86vmode") {
      	$x11_incl = "#include <X11/Xlib.h>\n";
 	$extensions_dir = "extensions/";
-	$pre_file = "#include \"wintypes.h\"\n#ifdef HAVE_LIBXXF86VM\n#define XMD_H\n";
+	$pre_file = "#include \"windef.h\"\n#ifdef HAVE_LIBXXF86VM\n#define XMD_H\n#define INT32 INT\n";
 	$post_file = "#endif /* defined(HAVE_LIBXXF86VM) */\n";
     }
 
diff --git a/tsx11/X11_calls b/tsx11/X11_calls
index 96350b0..e570e69 100644
--- a/tsx11/X11_calls
+++ b/tsx11/X11_calls
@@ -131,6 +131,7 @@
 XSetSubwindowMode
 XSetTransientForHint
 XSetWindowColormap
+XSetWMHints
 XSetWMProperties
 XSetWMProtocols
 XSetWMSizeHints
diff --git a/tsx11/ts_xf86vmode.c b/tsx11/ts_xf86vmode.c
index 89e8dc9..c3775f9 100644
--- a/tsx11/ts_xf86vmode.c
+++ b/tsx11/ts_xf86vmode.c
@@ -11,7 +11,8 @@
 #include "windef.h"
 #ifdef HAVE_LIBXXF86VM
 #define XMD_H
-typedef int INT32;
+#define INT32 INT
+
 #include <X11/Xlib.h>
 #include <X11/extensions/xf86vmode.h>
 #include "debug.h"
diff --git a/tsx11/ts_xutil.c b/tsx11/ts_xutil.c
index 0f6e294..fa227cc 100644
--- a/tsx11/ts_xutil.c
+++ b/tsx11/ts_xutil.c
@@ -235,6 +235,17 @@
   return r;
 }
 
+int  TSXSetWMHints(Display* a0, Window a1, XWMHints* a2)
+{
+  int  r;
+  TRACE(x11, "Call XSetWMHints\n");
+  EnterCriticalSection( &X11DRV_CritSection );
+  r = XSetWMHints(a0, a1, a2);
+  LeaveCriticalSection( &X11DRV_CritSection );
+  TRACE(x11, "Ret XSetWMHints\n");
+  return r;
+}
+
 void  TSXSetWMProperties(Display* a0, Window a1, XTextProperty* a2, XTextProperty* a3, char** a4, int a5, XSizeHints* a6, XWMHints* a7, XClassHint* a8)
 {
   TRACE(x11, "Call XSetWMProperties\n");
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)