diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am
index 57e2010..e8b6103 100644
--- a/hw/xwin/Makefile.am
+++ b/hw/xwin/Makefile.am
@@ -100,6 +100,8 @@ SRCS =	InitInput.c \
 	winshaddd.c \
 	winshadddnl.c \
 	winshadgdi.c \
+	winshadow.h \
+	winshadow.c \
 	wintrayicon.c \
 	winvalargs.c \
 	winwakeup.c \
diff --git a/hw/xwin/win.h b/hw/xwin/win.h
index 09a9fb2..163d1dc 100644
--- a/hw/xwin/win.h
+++ b/hw/xwin/win.h
@@ -196,7 +196,7 @@
  * Windows headers
  */
 #include "winms.h"
-#include "./winresource.h"
+#include "winresource.h"
 
 
 /*
@@ -209,6 +209,7 @@
 
 
 /* Local includes */
+#include "winshadow.h"
 #include "winwindow.h"
 #include "winmsg.h"
 
@@ -546,6 +547,7 @@ typedef struct _winPrivScreenRec
   
   /* Engine specific functions */
   winAllocateFBProcPtr			pwinAllocateFB;
+  winRefreshAreaProcPtr			pwinRefreshArea;
   winShadowUpdateProcPtr		pwinShadowUpdate;
   winCloseScreenProcPtr			pwinCloseScreen;
   winInitVisualsProcPtr			pwinInitVisuals;
diff --git a/hw/xwin/winscrinit.c b/hw/xwin/winscrinit.c
index a9b061a..b02308a 100644
--- a/hw/xwin/winscrinit.c
+++ b/hw/xwin/winscrinit.c
@@ -447,6 +447,11 @@ winFinishScreenInitFB (int index,
 	  ErrorF ("winFinishScreenInitFB - shadowInit () failed\n");
 	  return FALSE;
 	}
+      if (!winShadowSetup (pScreen, NULL, pScreenPriv->pwinRefreshArea))
+      {
+	  ErrorF ("winFinishScreenInitFB - winShadowSetup () failed\n");
+	  return FALSE;
+      }
     }
 
 #ifdef XWIN_MULTIWINDOWEXTWM
diff --git a/hw/xwin/winshaddd.c b/hw/xwin/winshaddd.c
index a2c1dc9..75084db 100644
--- a/hw/xwin/winshaddd.c
+++ b/hw/xwin/winshaddd.c
@@ -71,6 +71,10 @@ static Bool
 winAllocateFBShadowDD (ScreenPtr pScreen);
 
 static void
+winRefreshAreaDD (ScreenPtr pScreen,
+		  RegionPtr region);
+
+static void
 winShadowUpdateDD (ScreenPtr pScreen, 
 		   shadowBufPtr pBuf);
 
@@ -498,22 +502,16 @@ winAllocateFBShadowDD (ScreenPtr pScreen)
 }
 
 
-/*
- * Transfer the damaged regions of the shadow framebuffer to the display.
- */
-
-static void
-winShadowUpdateDD (ScreenPtr pScreen, 
-		   shadowBufPtr pBuf)
+winRefreshAreaDD (ScreenPtr pScreen,
+		  RegionPtr region)
 {
   winScreenPriv(pScreen);
   winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
-  RegionPtr		damage = &pBuf->damage;
   HRESULT		ddrval = DD_OK;
   RECT			rcDest, rcSrc;
   POINT			ptOrigin;
-  DWORD			dwBox = REGION_NUM_RECTS (damage);
-  BoxPtr		pBox = REGION_RECTS (damage);
+  DWORD			dwBox = REGION_NUM_RECTS (region);
+  BoxPtr		pBox = REGION_RECTS (region);
   HRGN			hrgnTemp = NULL, hrgnCombined = NULL;
 
   /*
@@ -575,7 +573,7 @@ winShadowUpdateDD (ScreenPtr pScreen,
     }
   else
     {
-      BoxPtr		pBoxExtents = REGION_EXTENTS (pScreen, damage);
+      BoxPtr		pBoxExtents = REGION_EXTENTS (pScreen, region);
 
       /* Compute a GDI region from the damaged region */
       hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
@@ -662,6 +660,20 @@ winShadowUpdateDD (ScreenPtr pScreen,
 
 
 /*
+ * Transfer the damaged regions of the shadow framebuffer to the display.
+ */
+
+static void
+winShadowUpdateDD (ScreenPtr pScreen, 
+		   shadowBufPtr pBuf)
+{
+  RegionPtr damage = shadowDamage (pBuf);
+  
+  winRefreshAreaDD(pScreen, damage);
+}
+
+
+/*
  * Call the wrapped CloseScreen function.
  * 
  * Free our resources and private structures.
@@ -1412,6 +1424,7 @@ winSetEngineFunctionsShadowDD (ScreenPtr pScreen)
   
   /* Set our pointers */
   pScreenPriv->pwinAllocateFB = winAllocateFBShadowDD;
+  pScreenPriv->pwinRefreshArea = winRefreshAreaDD;
   pScreenPriv->pwinShadowUpdate = winShadowUpdateDD;
   pScreenPriv->pwinCloseScreen = winCloseScreenShadowDD;
   pScreenPriv->pwinInitVisuals = winInitVisualsShadowDD;
diff --git a/hw/xwin/winshadddnl.c b/hw/xwin/winshadddnl.c
index 47cc382..d069630 100644
--- a/hw/xwin/winshadddnl.c
+++ b/hw/xwin/winshadddnl.c
@@ -72,6 +72,9 @@ static Bool
 winAllocateFBShadowDDNL (ScreenPtr pScreen);
 
 static void
+winRefreshAreaDDNL (ScreenPtr pScreen,
+		    RegionPtr region);
+static void
 winShadowUpdateDDNL (ScreenPtr pScreen, 
 		     shadowBufPtr pBuf);
 
@@ -574,22 +577,17 @@ winFinishCreateWindowsWindowDDNL (WindowPtr pWin)
 #endif
 
 
-/*
- * Transfer the damaged regions of the shadow framebuffer to the display.
- */
-
 static void
-winShadowUpdateDDNL (ScreenPtr pScreen, 
-		     shadowBufPtr pBuf)
+winRefreshAreaDDNL (ScreenPtr pScreen,
+		    RegionPtr region)
 {
   winScreenPriv(pScreen);
   winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
-  RegionPtr		damage = &pBuf->damage;
   HRESULT		ddrval = DD_OK;
   RECT			rcDest, rcSrc;
   POINT			ptOrigin;
-  DWORD			dwBox = REGION_NUM_RECTS (damage);
-  BoxPtr		pBox = REGION_RECTS (damage);
+  DWORD			dwBox = REGION_NUM_RECTS (region);
+  BoxPtr		pBox = REGION_RECTS (region);
   HRGN			hrgnTemp = NULL, hrgnCombined = NULL;
 
   /*
@@ -664,7 +662,7 @@ winShadowUpdateDDNL (ScreenPtr pScreen,
     }
   else
     {
-      BoxPtr		pBoxExtents = REGION_EXTENTS (pScreen, damage);
+      BoxPtr		pBoxExtents = REGION_EXTENTS (pScreen, region);
 
       /* Compute a GDI region from the damaged region */
       hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
@@ -716,6 +714,20 @@ winShadowUpdateDDNL (ScreenPtr pScreen,
 
 
 /*
+ * Transfer the damaged regions of the shadow framebuffer to the display.
+ */
+
+static void
+winShadowUpdateDDNL (ScreenPtr pScreen, 
+		     shadowBufPtr pBuf)
+{
+    RegionPtr damage = shadowDamage (pBuf);
+
+    winRefreshAreaDDNL(pScreen, damage);
+}
+
+
+/*
  * Call the wrapped CloseScreen function.
  *
  * Free our resources and private structures.
@@ -1424,6 +1436,7 @@ winSetEngineFunctionsShadowDDNL (ScreenPtr pScreen)
   
   /* Set our pointers */
   pScreenPriv->pwinAllocateFB = winAllocateFBShadowDDNL;
+  pScreenPriv->pwinRefreshArea = winRefreshAreaDDNL;
   pScreenPriv->pwinShadowUpdate = winShadowUpdateDDNL;
   pScreenPriv->pwinCloseScreen = winCloseScreenShadowDDNL;
   pScreenPriv->pwinInitVisuals = winInitVisualsShadowDDNL;
diff --git a/hw/xwin/winshadgdi.c b/hw/xwin/winshadgdi.c
index 04cc2f7..d5dc4c4 100644
--- a/hw/xwin/winshadgdi.c
+++ b/hw/xwin/winshadgdi.c
@@ -60,6 +60,10 @@ static Bool
 winAllocateFBShadowGDI (ScreenPtr pScreen);
 
 static void
+winRefreshAreaGDI (ScreenPtr pScreen,
+		   RegionPtr region);
+
+static void
 winShadowUpdateGDI (ScreenPtr pScreen, 
 		    shadowBufPtr pBuf);
 
@@ -487,20 +491,14 @@ winAllocateFBShadowGDI (ScreenPtr pScreen)
   return fReturn;
 }
 
-
-/*
- * Blit the damaged regions of the shadow fb to the screen
- */
-
 static void
-winShadowUpdateGDI (ScreenPtr pScreen, 
-		    shadowBufPtr pBuf)
+winRefreshAreaGDI (ScreenPtr pScreen,
+		   RegionPtr region)
 {
   winScreenPriv(pScreen);
   winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
-  RegionPtr		damage = &pBuf->damage;
-  DWORD			dwBox = REGION_NUM_RECTS (damage);
-  BoxPtr		pBox = REGION_RECTS (damage);
+  DWORD			dwBox = REGION_NUM_RECTS (region);
+  BoxPtr		pBox = REGION_RECTS (region);
   int			x, y, w, h;
   HRGN			hrgnTemp = NULL, hrgnCombined = NULL;
 #ifdef XWIN_UPDATESTATS
@@ -508,7 +506,7 @@ winShadowUpdateGDI (ScreenPtr pScreen,
   static DWORD		s_dwTotalUpdates = 0;
   static DWORD		s_dwTotalBoxes = 0;
 #endif
-  BoxPtr		pBoxExtents = REGION_EXTENTS (pScreen, damage);
+  BoxPtr		pBoxExtents = REGION_EXTENTS (pScreen, region);
 
   /*
    * Return immediately if the app is not active
@@ -611,7 +609,18 @@ winShadowUpdateGDI (ScreenPtr pScreen,
 #endif
 }
 
+/*
+ * Blit the damaged regions of the shadow fb to the screen
+ */
 
+static void
+winShadowUpdateGDI (ScreenPtr pScreen, 
+		    shadowBufPtr pBuf)
+{
+  RegionPtr damage = shadowDamage (pBuf);
+  
+  winRefreshAreaGDI(pScreen, damage);
+}
 /* See Porting Layer Definition - p. 33 */
 /*
  * We wrap whatever CloseScreen procedure was specified by fb;
@@ -1292,6 +1301,7 @@ winSetEngineFunctionsShadowGDI (ScreenPtr pScreen)
   
   /* Set our pointers */
   pScreenPriv->pwinAllocateFB = winAllocateFBShadowGDI;
+  pScreenPriv->pwinRefreshArea = winRefreshAreaGDI;
   pScreenPriv->pwinShadowUpdate = winShadowUpdateGDI;
   pScreenPriv->pwinCloseScreen = winCloseScreenShadowGDI;
   pScreenPriv->pwinInitVisuals = winInitVisualsShadowGDI;
diff --git a/hw/xwin/winshadow.c b/hw/xwin/winshadow.c
new file mode 100644
index 0000000..f9fddc2
--- /dev/null
+++ b/hw/xwin/winshadow.c
@@ -0,0 +1,1798 @@
+/*
+ * Copyright © 2007 Jie Luo
+ *
+ * Portions of this file are copied from miext/shadow/shadow.c
+ * which contains the following copyright:
+ *
+ * Copyright © 2000 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Portions of this file are copied from hw/xfree86/shadowfb/shadow.c
+ * which contains the following copyright:
+ *
+ * Copyright (C) 1999.  The XFree86 Project Inc.
+ *
+ * Written by Mark Vojkovich (mvojkovi@ucsd.edu)
+ *
+ * Pre-fb-write callbacks and RENDER support - Nolan Leake (nolan@vmware.com)
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include    <X11/X.h>
+#include    "scrnintstr.h"
+#include    "windowstr.h"
+#include    <X11/fonts/font.h>
+#include    "dixfontstr.h"
+#include    <X11/fonts/fontstruct.h>
+#include    "mi.h"
+#include    "regionstr.h"
+#include    "globals.h"
+#include    "gcstruct.h"
+#include    "winshadow.h"
+
+#ifdef RENDER
+# include "picturestr.h"
+#endif
+
+
+typedef struct _winShadowScrPriv {
+    winRefreshAreaProcPtr	    preRefresh;
+    winRefreshAreaProcPtr	    postRefresh;
+    CloseScreenProcPtr		    CloseScreen;
+    PaintWindowBackgroundProcPtr    PaintWindowBackground;
+    PaintWindowBorderProcPtr	    PaintWindowBorder;
+    CopyWindowProcPtr		    CopyWindow;
+    CreateGCProcPtr		    CreateGC;
+    BSFuncRec			    BackingStoreFuncs;
+#ifdef RENDER
+    CompositeProcPtr		    Composite;
+#endif
+} winShadowScrPrivRec, *winShadowScrPrivPtr;
+
+typedef struct {
+   GCOps   *ops;
+   GCFuncs *funcs;
+} winShadowGCPrivRec, *winShadowGCPrivPtr;
+
+
+static int winShadowScrPrivateIndex = -1;
+static int winShadowGCPrivateIndex = -1;
+static int winShadowGeneration = 0;
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define MAX(a,b) (((a)>(b))?(a):(b))
+
+#define wrap(priv, real, mem, func) {\
+    priv->mem = real->mem; \
+    real->mem = func; \
+}
+
+#define unwrap(priv, real, mem) {\
+    real->mem = priv->mem; \
+}
+
+#define IS_VISIBLE(pWin) 1
+
+#define TRIM_BOX(box, pGC) { \
+    BoxPtr extents = &pGC->pCompositeClip->extents;\
+    if(box.x1 < extents->x1) box.x1 = extents->x1; \
+    if(box.x2 > extents->x2) box.x2 = extents->x2; \
+    if(box.y1 < extents->y1) box.y1 = extents->y1; \
+    if(box.y2 > extents->y2) box.y2 = extents->y2; \
+    }
+
+#define TRANSLATE_BOX(box, pDraw) { \
+    box.x1 += pDraw->x; \
+    box.x2 += pDraw->x; \
+    box.y1 += pDraw->y; \
+    box.y2 += pDraw->y; \
+    }
+
+#define TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC) { \
+    TRANSLATE_BOX(box, pDraw); \
+    TRIM_BOX(box, pGC); \
+    }
+
+#define BOX_NOT_EMPTY(box) \
+    (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
+
+#define winShadowGetScrPriv(pScr) \
+    ((winShadowScrPrivPtr) (pScr)->devPrivates[winShadowScrPrivateIndex].ptr)
+
+#define winShadowScrPriv(pScr) \
+    winShadowScrPrivPtr    pScrPriv = winShadowGetScrPriv(pScr)
+
+#define winShadowGetGCPriv(pGC) \
+    ((winShadowGCPrivPtr) (pGC)->devPrivates[winShadowGCPrivateIndex].ptr)
+
+#define winShadowGCPriv(pGC) \
+    winShadowGCPrivPtr  pGCPriv = winShadowGetGCPriv(pGC)
+
+#define SHADOW_GC_OP_PROLOGUE(pGC) \
+    ScreenPtr pScreen = pGC->pScreen; \
+    winShadowScrPriv(pScreen); \
+    winShadowGCPriv(pGC);  \
+    GCFuncs *oldFuncs = pGC->funcs; \
+    unwrap(pGCPriv, pGC, funcs);  \
+    unwrap(pGCPriv, pGC, ops); \
+
+#define SHADOW_GC_OP_EPILOGUE(pGC) \
+    wrap(pGCPriv, pGC, funcs, oldFuncs); \
+    wrap(pGCPriv, pGC, ops, &winShadowGCOps)
+
+#define SHADOW_GC_FUNC_PROLOGUE(pGC) \
+    winShadowGCPriv(pGC); \
+    unwrap(pGCPriv, pGC, funcs); \
+    if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)
+
+#define SHADOW_GC_FUNC_EPILOGUE(pGC) \
+    wrap(pGCPriv, pGC, funcs, &winShadowGCFuncs);  \
+    if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &winShadowGCOps)
+
+
+
+static void winShadowValidateGC(GCPtr, unsigned long, DrawablePtr);
+static void winShadowChangeGC(GCPtr, unsigned long);
+static void winShadowCopyGC(GCPtr, unsigned long, GCPtr);
+static void winShadowDestroyGC(GCPtr);
+static void winShadowChangeClip(GCPtr, int, pointer, int);
+static void winShadowDestroyClip(GCPtr);
+static void winShadowCopyClip(GCPtr, GCPtr);
+
+
+GCFuncs winShadowGCFuncs = {
+    winShadowValidateGC, winShadowChangeGC, winShadowCopyGC, winShadowDestroyGC,
+    winShadowChangeClip, winShadowDestroyClip, winShadowCopyClip
+};
+
+
+extern GCOps winShadowGCOps;
+
+static Bool
+winShadowCreateGC(GCPtr pGC)
+{
+    ScreenPtr pScreen = pGC->pScreen;
+    winShadowScrPriv(pScreen);
+    winShadowGCPriv(pGC);
+    Bool ret;
+   
+    unwrap (pScrPriv, pScreen, CreateGC);
+    if((ret = (*pScreen->CreateGC) (pGC))) {
+	pGCPriv->ops = NULL;
+	pGCPriv->funcs = pGC->funcs;
+	pGC->funcs = &winShadowGCFuncs;
+    }
+    wrap (pScrPriv, pScreen, CreateGC, winShadowCreateGC);
+
+    return ret;
+}
+
+static void
+winShadowValidateGC(
+   GCPtr         pGC,
+   unsigned long changes,
+   DrawablePtr   pDraw 
+){
+    SHADOW_GC_FUNC_PROLOGUE (pGC);
+    (*pGC->funcs->ValidateGC)(pGC, changes, pDraw);
+    if(pDraw->type == DRAWABLE_WINDOW)
+	pGCPriv->ops = pGC->ops;  /* just so it's not NULL */
+    else 
+	pGCPriv->ops = NULL;
+    SHADOW_GC_FUNC_EPILOGUE (pGC);
+}
+
+
+static void
+winShadowDestroyGC(GCPtr pGC)
+{
+    SHADOW_GC_FUNC_PROLOGUE (pGC);
+    (*pGC->funcs->DestroyGC)(pGC);
+    SHADOW_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+winShadowChangeGC (
+    GCPtr	    pGC,
+    unsigned long   mask
+){
+    SHADOW_GC_FUNC_PROLOGUE (pGC);
+    (*pGC->funcs->ChangeGC) (pGC, mask);
+    SHADOW_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+winShadowCopyGC (
+    GCPtr	    pGCSrc, 
+    unsigned long   mask,
+    GCPtr	    pGCDst
+){
+    SHADOW_GC_FUNC_PROLOGUE (pGCDst);
+    (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
+    SHADOW_GC_FUNC_EPILOGUE (pGCDst);
+}
+
+static void
+winShadowChangeClip (
+    GCPtr   pGC,
+    int		type,
+    pointer	pvalue,
+    int		nrects 
+){
+    SHADOW_GC_FUNC_PROLOGUE (pGC);
+    (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
+    SHADOW_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+winShadowCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
+{
+    SHADOW_GC_FUNC_PROLOGUE (pgcDst);
+    (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
+    SHADOW_GC_FUNC_EPILOGUE (pgcDst);
+}
+
+static void
+winShadowDestroyClip(GCPtr pGC)
+{
+    SHADOW_GC_FUNC_PROLOGUE (pGC);
+    (* pGC->funcs->DestroyClip)(pGC);
+    SHADOW_GC_FUNC_EPILOGUE (pGC);
+}
+
+
+static void
+winShadowFillSpans(
+    DrawablePtr pDraw,
+    GC		*pGC,
+    int		nInit,	
+    DDXPointPtr pptInit,	
+    int 	*pwidthInit,		
+    int 	fSorted 
+){
+    SHADOW_GC_OP_PROLOGUE(pGC);    
+
+    if(IS_VISIBLE(pDraw) && nInit) {
+	DDXPointPtr ppt = pptInit;
+	int *pwidth = pwidthInit;
+	int i = nInit;
+	BoxRec box;
+	RegionRec rgn;
+        Bool boxNotEmpty = FALSE;
+
+	box.x1 = ppt->x;
+	box.x2 = box.x1 + *pwidth;
+	box.y2 = box.y1 = ppt->y;
+
+	while(--i) {
+	   ppt++;
+	   pwidth++;
+	   if(box.x1 > ppt->x) box.x1 = ppt->x;
+	   if(box.x2 < (ppt->x + *pwidth)) 
+		box.x2 = ppt->x + *pwidth;
+	   if(box.y1 > ppt->y) box.y1 = ppt->y;
+	   else if(box.y2 < ppt->y) box.y2 = ppt->y;
+	}
+
+	box.y2++;
+
+        if(!pGC->miTranslate) {
+           TRANSLATE_BOX(box, pDraw);
+        }
+        TRIM_BOX(box, pGC); 
+
+	if(BOX_NOT_EMPTY(box)) {
+	    REGION_INIT(pScreen, &rgn, &box, 1);
+            if(pScrPriv->preRefresh)
+                (*pScrPriv->preRefresh)(pScreen, &rgn);
+            boxNotEmpty = TRUE;
+        }
+
+	(*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);
+
+        if(boxNotEmpty ) {
+	    if (pScrPriv->postRefresh)
+		(*pScrPriv->postRefresh)(pScreen, &rgn);
+	    REGION_UNINIT(pScreen, &rgn);
+	}
+    } else
+	(*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);
+
+    SHADOW_GC_OP_EPILOGUE(pGC);
+}
+
+static void
+winShadowSetSpans(
+    DrawablePtr		pDraw,
+    GCPtr		pGC,
+    char		*pcharsrc,
+    DDXPointPtr 	pptInit,
+    int			*pwidthInit,
+    int			nspans,
+    int			fSorted 
+){
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw) && nspans) {
+	DDXPointPtr ppt = pptInit;
+	int *pwidth = pwidthInit;
+	int i = nspans;
+	BoxRec box;
+	RegionRec rgn;
+        Bool boxNotEmpty = FALSE;
+
+	box.x1 = ppt->x;
+	box.x2 = box.x1 + *pwidth;
+	box.y2 = box.y1 = ppt->y;
+
+	while(--i) {
+	   ppt++;
+	   pwidth++;
+	   if(box.x1 > ppt->x) box.x1 = ppt->x;
+	   if(box.x2 < (ppt->x + *pwidth)) 
+		box.x2 = ppt->x + *pwidth;
+	   if(box.y1 > ppt->y) box.y1 = ppt->y;
+	   else if(box.y2 < ppt->y) box.y2 = ppt->y;
+	}
+
+	box.y2++;
+
+        if(!pGC->miTranslate) {
+           TRANSLATE_BOX(box, pDraw);
+        }
+        TRIM_BOX(box, pGC);
+
+	if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+	      (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+
+	(*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit, 
+				pwidthInit, nspans, fSorted);
+
+	if(boxNotEmpty) {
+	    if (pScrPriv->postRefresh)
+		(*pScrPriv->postRefresh)(pScreen, &rgn);
+	    REGION_UNINIT(pScreen, &rgn);
+	}
+    } else
+	(*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit, 
+				pwidthInit, nspans, fSorted);
+
+    SHADOW_GC_OP_EPILOGUE(pGC);
+}
+
+static void
+winShadowPutImage(
+    DrawablePtr pDraw,
+    GCPtr	pGC,
+    int		depth, 
+    int x, int y, int w, int h,
+    int		leftPad,
+    int		format,
+    char 	*pImage 
+){
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+    
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw)) {
+	box.x1 = x + pDraw->x;
+	box.x2 = box.x1 + w;
+	box.y1 = y + pDraw->y;
+	box.y2 = box.y1 + h;
+
+	TRIM_BOX(box, pGC);
+	if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+	      (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+    }
+
+    (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h, 
+		leftPad, format, pImage);
+                
+    if(boxNotEmpty) {
+        if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }
+    
+    SHADOW_GC_OP_EPILOGUE(pGC);
+
+}
+
+static RegionPtr
+winShadowCopyArea(
+    DrawablePtr pSrc,
+    DrawablePtr pDst,
+    GC *pGC,
+    int srcx, int srcy,
+    int width, int height,
+    int dstx, int dsty 
+){
+    RegionPtr ret;
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+    
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDst)) {
+	box.x1 = dstx + pDst->x;
+	box.x2 = box.x1 + width;
+	box.y1 = dsty + pDst->y;
+	box.y2 = box.y1 + height;
+
+	TRIM_BOX(box, pGC);
+	if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+	      (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+    }
+    
+    ret = (*pGC->ops->CopyArea)(pSrc, pDst,
+            pGC, srcx, srcy, width, height, dstx, dsty);
+
+    if(boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }
+    
+    SHADOW_GC_OP_EPILOGUE(pGC);
+
+    return ret;
+}
+
+static RegionPtr
+winShadowCopyPlane(
+    DrawablePtr	pSrc,
+    DrawablePtr	pDst,
+    GCPtr pGC,
+    int	srcx, int srcy,
+    int	width, int height,
+    int	dstx, int dsty,
+    unsigned long bitPlane 
+){
+    RegionPtr ret;
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+    
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDst)) {
+	box.x1 = dstx + pDst->x;
+	box.x2 = box.x1 + width;
+	box.y1 = dsty + pDst->y;
+	box.y2 = box.y1 + height;
+
+	TRIM_BOX(box, pGC);
+	if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+	      (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+    }
+    
+    ret = (*pGC->ops->CopyPlane)(pSrc, pDst,
+	       pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
+    
+    if(boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }
+    
+    SHADOW_GC_OP_EPILOGUE(pGC);
+
+    return ret;
+}
+
+static void
+winShadowPolyPoint(
+    DrawablePtr pDraw,
+    GCPtr pGC,
+    int mode,
+    int nptInit,
+    xPoint *pptInit 
+){
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+    
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw) && nptInit) {
+        xPoint *ppt = pptInit;
+        int npt = nptInit;
+
+	box.x2 = box.x1 = pptInit->x;
+	box.y2 = box.y1 = pptInit->y;
+
+	/* this could be slow if the points were spread out */
+
+	while(--npt) {
+	   ppt++;
+	   if(box.x1 > ppt->x) box.x1 = ppt->x;
+	   else if(box.x2 < ppt->x) box.x2 = ppt->x;
+	   if(box.y1 > ppt->y) box.y1 = ppt->y;
+	   else if(box.y2 < ppt->y) box.y2 = ppt->y;
+	}
+
+	box.x2++;
+	box.y2++;
+
+	TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
+	if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+	      (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+    }
+    
+    (*pGC->ops->PolyPoint)(pDraw, pGC, mode, nptInit, pptInit);
+    
+    if(boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }
+
+    SHADOW_GC_OP_EPILOGUE(pGC);
+}
+
+static void
+winShadowPolylines(
+    DrawablePtr pDraw,
+    GCPtr	pGC,
+    int		mode,		
+    int		nptInit,		
+    DDXPointPtr pptInit 
+){
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+    
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw) && nptInit) {
+        DDXPointPtr ppt = pptInit;
+        int npt = nptInit;
+	int extra = pGC->lineWidth >> 1;
+
+	box.x2 = box.x1 = pptInit->x;
+	box.y2 = box.y1 = pptInit->y;
+
+	if(npt > 1) {
+	   if(pGC->joinStyle == JoinMiter)
+		extra = 6 * pGC->lineWidth;
+	   else if(pGC->capStyle == CapProjecting)
+		extra = pGC->lineWidth;
+        }
+
+	if(mode == CoordModePrevious) {
+	   int x = box.x1;
+	   int y = box.y1;
+	   while(--npt) {
+		ppt++;
+		x += ppt->x;
+		y += ppt->y;
+		if(box.x1 > x) box.x1 = x;
+		else if(box.x2 < x) box.x2 = x;
+		if(box.y1 > y) box.y1 = y;
+		else if(box.y2 < y) box.y2 = y;
+	    }
+	} else {
+	   while(--npt) {
+		ppt++;
+		if(box.x1 > ppt->x) box.x1 = ppt->x;
+		else if(box.x2 < ppt->x) box.x2 = ppt->x;
+		if(box.y1 > ppt->y) box.y1 = ppt->y;
+		else if(box.y2 < ppt->y) box.y2 = ppt->y;
+	    }
+	}
+
+	box.x2++;
+	box.y2++;
+
+	if(extra) {
+	   box.x1 -= extra;
+	   box.x2 += extra;
+	   box.y1 -= extra;
+	   box.y2 += extra;
+        }
+
+	TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
+	if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+	      (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+    }
+    
+    (*pGC->ops->Polylines)(pDraw, pGC, mode, nptInit, pptInit);
+
+    if(boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }
+
+    SHADOW_GC_OP_EPILOGUE(pGC);
+}
+
+static void 
+winShadowPolySegment(
+    DrawablePtr	pDraw,
+    GCPtr	pGC,
+    int		nsegInit,
+    xSegment	*pSegInit 
+){
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+   
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw) && nsegInit) {
+	int extra = pGC->lineWidth;
+        xSegment *pSeg = pSegInit;
+        int nseg = nsegInit;
+
+        if(pGC->capStyle != CapProjecting)	
+	   extra >>= 1;
+
+	if(pSeg->x2 > pSeg->x1) {
+	    box.x1 = pSeg->x1;
+	    box.x2 = pSeg->x2;
+	} else {
+	    box.x2 = pSeg->x1;
+	    box.x1 = pSeg->x2;
+	}
+
+	if(pSeg->y2 > pSeg->y1) {
+	    box.y1 = pSeg->y1;
+	    box.y2 = pSeg->y2;
+	} else {
+	    box.y2 = pSeg->y1;
+	    box.y1 = pSeg->y2;
+	}
+
+	while(--nseg) {
+	    pSeg++;
+	    if(pSeg->x2 > pSeg->x1) {
+		if(pSeg->x1 < box.x1) box.x1 = pSeg->x1;
+		if(pSeg->x2 > box.x2) box.x2 = pSeg->x2;
+	    } else {
+		if(pSeg->x2 < box.x1) box.x1 = pSeg->x2;
+		if(pSeg->x1 > box.x2) box.x2 = pSeg->x1;
+	    }
+	    if(pSeg->y2 > pSeg->y1) {
+		if(pSeg->y1 < box.y1) box.y1 = pSeg->y1;
+		if(pSeg->y2 > box.y2) box.y2 = pSeg->y2;
+	    } else {
+		if(pSeg->y2 < box.y1) box.y1 = pSeg->y2;
+		if(pSeg->y1 > box.y2) box.y2 = pSeg->y1;
+	    }
+	}
+
+	box.x2++;
+	box.y2++;
+
+	if(extra) {
+	   box.x1 -= extra;
+	   box.x2 += extra;
+	   box.y1 -= extra;
+	   box.y2 += extra;
+        }
+
+	TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
+	if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+              (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+    }
+    
+    (*pGC->ops->PolySegment)(pDraw, pGC, nsegInit, pSegInit);
+
+    if(boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }
+
+    SHADOW_GC_OP_EPILOGUE(pGC);
+}
+
+static void
+winShadowPolyRectangle(
+    DrawablePtr  pDraw,
+    GCPtr        pGC,
+    int	         nRectsInit,
+    xRectangle  *pRectsInit 
+){
+    BoxRec box;
+    RegionRec rgn;
+    BoxPtr pBoxInit = NULL;
+    Bool boxNotEmpty = FALSE;
+    int num = 0;
+    
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw) && nRectsInit) {
+        xRectangle *pRects = pRectsInit;
+        int nRects = nRectsInit;
+
+	if(nRects >= 32) {
+	    int extra = pGC->lineWidth >> 1;
+
+	    box.x1 = pRects->x;
+	    box.x2 = box.x1 + pRects->width;
+	    box.y1 = pRects->y;
+	    box.y2 = box.y1 + pRects->height;
+
+	    while(--nRects) {
+		pRects++;
+		if(box.x1 > pRects->x) box.x1 = pRects->x;
+		if(box.x2 < (pRects->x + pRects->width))
+			box.x2 = pRects->x + pRects->width;
+		if(box.y1 > pRects->y) box.y1 = pRects->y;
+		if(box.y2 < (pRects->y + pRects->height))
+			box.y2 = pRects->y + pRects->height;
+	    }
+
+	    if(extra) {
+		box.x1 -= extra;
+		box.x2 += extra;
+		box.y1 -= extra;
+		box.y2 += extra;
+	    }
+
+	    box.x2++;
+	    box.y2++;
+
+	    TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
+	    if(BOX_NOT_EMPTY(box)) {
+		REGION_INIT(pScreen, &rgn, &box, 1);
+                if(pScrPriv->preRefresh)
+                   (*pScrPriv->preRefresh)(pScreen, &rgn);
+                boxNotEmpty = TRUE;
+            }
+	} else {
+	    BoxPtr pbox;
+	    int offset1, offset2, offset3;
+
+	    offset2 = pGC->lineWidth;
+	    if(!offset2) offset2 = 1;
+	    offset1 = offset2 >> 1;
+	    offset3 = offset2 - offset1;
+
+	    pBoxInit = (BoxPtr)ALLOCATE_LOCAL(nRects * 4 * sizeof(BoxRec));
+	    pbox = pBoxInit;
+
+	    while(nRects--) {
+		pbox->x1 = pRects->x - offset1;
+		pbox->y1 = pRects->y - offset1;
+		pbox->x2 = pbox->x1 + pRects->width + offset2;
+		pbox->y2 = pbox->y1 + offset2;		
+		TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
+		if(BOX_NOT_EMPTY((*pbox))) {
+		   num++;
+		   pbox++;
+		}
+
+		pbox->x1 = pRects->x - offset1;
+		pbox->y1 = pRects->y + offset3;
+		pbox->x2 = pbox->x1 + offset2;
+		pbox->y2 = pbox->y1 + pRects->height - offset2;		
+		TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
+		if(BOX_NOT_EMPTY((*pbox))) {
+		   num++;
+		   pbox++;
+		}
+
+		pbox->x1 = pRects->x + pRects->width - offset1;
+		pbox->y1 = pRects->y + offset3;
+		pbox->x2 = pbox->x1 + offset2;
+		pbox->y2 = pbox->y1 + pRects->height - offset2;		
+		TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
+		if(BOX_NOT_EMPTY((*pbox))) {
+		   num++;
+		   pbox++;
+		}
+
+		pbox->x1 = pRects->x - offset1;
+		pbox->y1 = pRects->y + pRects->height - offset1;
+		pbox->x2 = pbox->x1 + pRects->width + offset2;
+		pbox->y2 = pbox->y1 + offset2;		
+		TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
+		if(BOX_NOT_EMPTY((*pbox))) {
+		   num++;
+		   pbox++;
+		}
+
+		pRects++;
+	    }
+	    
+	    if(num) {
+		REGION_INIT(pScreen, &rgn, pBoxInit, num);
+                if(pScrPriv->preRefresh)
+                    (*pScrPriv->preRefresh)(pScreen, &rgn);
+            } else {
+                DEALLOCATE_LOCAL(pBoxInit);
+            }                
+	}
+    }
+
+    (*pGC->ops->PolyRectangle)(pDraw, pGC, nRectsInit, pRectsInit);
+
+    if(boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    } else if(num) {
+       if(pScrPriv->postRefresh)
+          (*pScrPriv->postRefresh)(pScreen, &rgn);
+       REGION_UNINIT(pScreen, &rgn);
+       DEALLOCATE_LOCAL(pBoxInit);
+    }
+    
+    SHADOW_GC_OP_EPILOGUE(pGC);
+}
+
+static void
+winShadowPolyArc(
+    DrawablePtr	pDraw,
+    GCPtr	pGC,
+    int		narcsInit,
+    xArc	*parcsInit 
+){
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+   
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw) && narcsInit) {
+        int narcs = narcsInit;
+        xArc *parcs = parcsInit;
+        int extra = pGC->lineWidth >> 1;
+
+	box.x1 = parcs->x;
+	box.x2 = box.x1 + parcs->width;
+	box.y1 = parcs->y;
+	box.y2 = box.y1 + parcs->height;
+
+	/* should I break these up instead ? */
+
+	while(--narcs) {
+	   parcs++;
+	   if(box.x1 > parcs->x) box.x1 = parcs->x;
+	   if(box.x2 < (parcs->x + parcs->width))
+		box.x2 = parcs->x + parcs->width;
+	   if(box.y1 > parcs->y) box.y1 = parcs->y;
+	   if(box.y2 < (parcs->y + parcs->height))
+		box.y2 = parcs->y + parcs->height;
+        }
+
+	if(extra) {
+	   box.x1 -= extra;
+	   box.x2 += extra;
+	   box.y1 -= extra;
+	   box.y2 += extra;
+        }
+
+	box.x2++;
+	box.y2++;
+
+	TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
+	if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+              (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+    }
+    
+    (*pGC->ops->PolyArc)(pDraw, pGC, narcsInit, parcsInit);
+
+    if(boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }
+    
+    SHADOW_GC_OP_EPILOGUE(pGC);
+
+}
+
+static void
+winShadowFillPolygon(
+    DrawablePtr	pDraw,
+    GCPtr	pGC,
+    int		shape,
+    int		mode,
+    int		count,
+    DDXPointPtr	pptInit 
+){
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw) && (count > 2)) {
+	DDXPointPtr ppt = pptInit;
+	int i = count;
+	BoxRec box;
+	RegionRec rgn;
+        Bool boxNotEmpty = FALSE;
+
+	box.x2 = box.x1 = ppt->x;
+	box.y2 = box.y1 = ppt->y;
+
+	if(mode != CoordModeOrigin) {
+	   int x = box.x1;
+	   int y = box.y1;
+	   while(--i) {
+		ppt++;
+		x += ppt->x;
+		y += ppt->y;
+		if(box.x1 > x) box.x1 = x;
+		else if(box.x2 < x) box.x2 = x;
+		if(box.y1 > y) box.y1 = y;
+		else if(box.y2 < y) box.y2 = y;
+	    }
+	} else {
+	   while(--i) {
+		ppt++;
+		if(box.x1 > ppt->x) box.x1 = ppt->x;
+		else if(box.x2 < ppt->x) box.x2 = ppt->x;
+		if(box.y1 > ppt->y) box.y1 = ppt->y;
+		else if(box.y2 < ppt->y) box.y2 = ppt->y;
+	    }
+	}
+
+	box.x2++;
+	box.y2++;
+
+	TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
+	if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+              (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+
+	(*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit);
+
+        if(boxNotEmpty) {
+	    if (pScrPriv->postRefresh)
+		(*pScrPriv->postRefresh)(pScreen, &rgn);
+	    REGION_UNINIT(pScreen, &rgn);
+	}        
+    } else
+	(*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit);
+
+    SHADOW_GC_OP_EPILOGUE(pGC);
+}
+
+
+static void 
+winShadowPolyFillRect(
+    DrawablePtr	pDraw,
+    GCPtr	pGC,
+    int		nRectsInit, 
+    xRectangle	*pRectsInit 
+){
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw) && nRectsInit) {
+	BoxRec box;
+	RegionRec rgn;
+        Bool boxNotEmpty = FALSE;
+	xRectangle *pRects = pRectsInit;
+	int nRects = nRectsInit;
+
+	box.x1 = pRects->x;
+	box.x2 = box.x1 + pRects->width;
+	box.y1 = pRects->y;
+	box.y2 = box.y1 + pRects->height;
+
+	while(--nRects) {
+	    pRects++;
+	    if(box.x1 > pRects->x) box.x1 = pRects->x;
+	    if(box.x2 < (pRects->x + pRects->width))
+		box.x2 = pRects->x + pRects->width;
+	    if(box.y1 > pRects->y) box.y1 = pRects->y;
+	    if(box.y2 < (pRects->y + pRects->height))
+		box.y2 = pRects->y + pRects->height;
+	}
+
+	/* cfb messes with the pRectsInit so we have to do our
+	   calculations first */
+
+	TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
+	if(BOX_NOT_EMPTY(box)) {
+	    REGION_INIT(pScreen, &rgn, &box, 1);
+            if(pScrPriv->preRefresh)
+                (*pScrPriv->preRefresh)(pScreen, &rgn);
+            boxNotEmpty = TRUE;
+        }
+
+	(*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit);
+
+        if(boxNotEmpty) {
+	    if (pScrPriv->postRefresh)
+		(*pScrPriv->postRefresh)(pScreen, &rgn);
+	    REGION_UNINIT(pScreen, &rgn);
+	}
+    } else
+	(*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit);
+
+    SHADOW_GC_OP_EPILOGUE(pGC);
+}
+
+
+static void
+winShadowPolyFillArc(
+    DrawablePtr	pDraw,
+    GCPtr	pGC,
+    int		narcsInit,
+    xArc	*parcsInit 
+){
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+   
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw) && narcsInit) {
+        xArc *parcs = parcsInit;
+        int narcs = narcsInit;
+
+	box.x1 = parcs->x;
+	box.x2 = box.x1 + parcs->width;
+	box.y1 = parcs->y;
+	box.y2 = box.y1 + parcs->height;
+
+	/* should I break these up instead ? */
+
+	while(--narcs) {
+	   parcs++;
+	   if(box.x1 > parcs->x) box.x1 = parcs->x;
+	   if(box.x2 < (parcs->x + parcs->width))
+		box.x2 = parcs->x + parcs->width;
+	   if(box.y1 > parcs->y) box.y1 = parcs->y;
+	   if(box.y2 < (parcs->y + parcs->height))
+		box.y2 = parcs->y + parcs->height;
+        }
+
+	TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
+	if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+              (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+    }
+
+    (*pGC->ops->PolyFillArc)(pDraw, pGC, narcsInit, parcsInit);
+
+    if(boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }       
+    
+    SHADOW_GC_OP_EPILOGUE(pGC);
+}
+
+static void
+winShadowTextExtent(FontPtr pFont, int count, char* chars,
+                 FontEncoding fontEncoding, BoxPtr box)
+{
+    unsigned long n, i;
+    int w;
+    CharInfoPtr charinfo[255];	/* encoding only has 1 byte for count */
+
+    GetGlyphs(pFont, (unsigned long)count, (unsigned char *)chars,
+	      fontEncoding, &n, charinfo);
+    w = 0;
+    for (i=0; i < n; i++) {
+        w += charinfo[i]->metrics.characterWidth;
+    }
+    if (i) {
+    	w += charinfo[i - 1]->metrics.rightSideBearing;
+    }
+    
+    box->x1 = 0;
+    if (n) {
+	if (charinfo[0]->metrics.leftSideBearing < 0) {
+            box->x1 = charinfo[0]->metrics.leftSideBearing;
+        }
+    }
+    box->x2 = w;
+    box->y1 = -FONTMAXBOUNDS(pFont,ascent);
+    box->y2 = FONTMAXBOUNDS(pFont,descent);
+}
+
+
+
+static void
+winShadowFontToBox(BoxPtr BB, DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+                int count, char *chars, int wide)
+{
+    FontPtr pFont;
+
+    pFont = pGC->font;
+    if (pFont->info.constantWidth) {
+        int ascent, descent, left, right = 0;
+
+	ascent = MAX(pFont->info.fontAscent, pFont->info.maxbounds.ascent);
+	descent = MAX(pFont->info.fontDescent, pFont->info.maxbounds.descent);
+	left = pFont->info.maxbounds.leftSideBearing;
+	if (count > 0) {
+	    right = (count - 1) * pFont->info.maxbounds.characterWidth;
+	}
+	right += pFont->info.maxbounds.rightSideBearing;
+	BB->x1 =
+	    MAX(pDrawable->x + x - left, (REGION_EXTENTS(pGC->pScreen,
+		&((WindowPtr) pDrawable)->winSize))->x1);
+	BB->y1 =
+	    MAX(pDrawable->y + y - ascent,
+	    (REGION_EXTENTS(pGC->pScreen,
+             &((WindowPtr) pDrawable)->winSize))->y1);
+	BB->x2 =
+	    MIN(pDrawable->x + x + right,
+	    (REGION_EXTENTS(pGC->pScreen,
+             &((WindowPtr) pDrawable)->winSize))->x2);
+	BB->y2 =
+	    MIN(pDrawable->y + y + descent,
+	    (REGION_EXTENTS(pGC->pScreen,
+             &((WindowPtr) pDrawable)->winSize))->y2);
+    } else {
+    	winShadowTextExtent(pFont, count, chars, wide ? (FONTLASTROW(pFont) == 0)
+                         ? Linear16Bit : TwoD16Bit : Linear8Bit, BB);
+	BB->x1 =
+	    MAX(pDrawable->x + x + BB->x1, (REGION_EXTENTS(pGC->pScreen,
+		&((WindowPtr) pDrawable)->winSize))->x1);
+	BB->y1 =
+	    MAX(pDrawable->y + y + BB->y1,
+	    (REGION_EXTENTS(pGC->pScreen,
+             &((WindowPtr) pDrawable)->winSize))->y1);
+	BB->x2 =
+	    MIN(pDrawable->x + x + BB->x2,
+	    (REGION_EXTENTS(pGC->pScreen,
+	     &((WindowPtr) pDrawable)->winSize))->x2);
+	BB->y2 =
+	    MIN(pDrawable->y + y + BB->y2,
+	    (REGION_EXTENTS(pGC->pScreen, 
+	     &((WindowPtr) pDrawable)->winSize))->y2);
+    }
+}
+
+static int
+winShadowPolyText8(
+    DrawablePtr pDraw,
+    GCPtr	pGC,
+    int		x, 
+    int 	y,
+    int 	count,
+    char	*chars 
+){
+    int width;
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+    
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw)) {
+        winShadowFontToBox(&box, pDraw, pGC, x, y, count, chars, 0);
+       
+        TRIM_BOX(box, pGC);
+        if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+              (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+    }
+    
+    width = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars);
+
+    if(boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }
+    
+    SHADOW_GC_OP_EPILOGUE(pGC);
+
+    return width;
+}
+
+static int
+winShadowPolyText16(
+    DrawablePtr pDraw,
+    GCPtr	pGC,
+    int		x,
+    int		y,
+    int 	count,
+    unsigned short *chars 
+){
+    int width;
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw)) {
+        winShadowFontToBox(&box, pDraw, pGC, x, y, count, (char*)chars, 1);
+       
+        TRIM_BOX(box, pGC);
+        if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+              (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+    }
+
+    width = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars);
+
+    if(boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }
+
+    SHADOW_GC_OP_EPILOGUE(pGC);
+
+    return width;
+}
+
+static void
+winShadowImageText8(
+    DrawablePtr pDraw,
+    GCPtr	pGC,
+    int		x, 
+    int		y,
+    int 	count,
+    char	*chars 
+){
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw) && count) {
+	int top, bot, Min, Max;
+
+	top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+	bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+	Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
+	if(Min > 0) Min = 0;
+	Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);	
+	if(Max < 0) Max = 0;
+
+	/* ugh */
+	box.x1 = pDraw->x + x + Min +
+		FONTMINBOUNDS(pGC->font, leftSideBearing);
+	box.x2 = pDraw->x + x + Max + 
+		FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+	box.y1 = pDraw->y + y - top;
+	box.y2 = pDraw->y + y + bot;
+
+	TRIM_BOX(box, pGC);
+	if(BOX_NOT_EMPTY(box)) {
+	    REGION_INIT(pScreen, &rgn, &box, 1);
+            if(pScrPriv->preRefresh) 
+               (*pScrPriv->preRefresh)(pScreen, &rgn);
+            boxNotEmpty = TRUE;
+        }
+    }
+    
+    (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars);
+
+    if(boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }
+    
+    SHADOW_GC_OP_EPILOGUE(pGC);
+}
+static void
+winShadowImageText16(
+    DrawablePtr pDraw,
+    GCPtr	pGC,
+    int		x,
+    int		y,
+    int 	count,
+    unsigned short *chars 
+){
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw) && count) {
+	int top, bot, Min, Max;
+
+	top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+	bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+	Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
+	if(Min > 0) Min = 0;
+	Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);	
+	if(Max < 0) Max = 0;
+
+	/* ugh */
+	box.x1 = pDraw->x + x + Min +
+		FONTMINBOUNDS(pGC->font, leftSideBearing);
+	box.x2 = pDraw->x + x + Max + 
+		FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+	box.y1 = pDraw->y + y - top;
+	box.y2 = pDraw->y + y + bot;
+
+	TRIM_BOX(box, pGC);
+	if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+              (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+    }
+    
+    (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars);
+
+    if(boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }   
+    
+    SHADOW_GC_OP_EPILOGUE(pGC);
+}
+
+
+static void
+winShadowImageGlyphBlt(
+    DrawablePtr pDraw,
+    GCPtr pGC,
+    int x, int y,
+    unsigned int nglyphInit,
+    CharInfoPtr *ppciInit,
+    pointer pglyphBase 
+){
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw) && nglyphInit) {
+        CharInfoPtr *ppci = ppciInit;
+        unsigned int nglyph = nglyphInit;
+	int top, bot, width = 0;
+
+	top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+	bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+	box.x1 = ppci[0]->metrics.leftSideBearing;
+	if(box.x1 > 0) box.x1 = 0;
+	box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing - 
+		ppci[nglyph - 1]->metrics.characterWidth;
+	if(box.x2 < 0) box.x2 = 0;
+
+	box.x2 += pDraw->x + x;
+	box.x1 += pDraw->x + x;
+	   
+	while(nglyph--) {
+	    width += (*ppci)->metrics.characterWidth;
+	    ppci++;
+	}
+
+	if(width > 0) 
+	   box.x2 += width;
+	else 
+	   box.x1 += width;
+
+	box.y1 = pDraw->y + y - top;
+	box.y2 = pDraw->y + y + bot;
+
+	TRIM_BOX(box, pGC);
+	if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+              (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+    }
+
+    (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, nglyphInit, 
+					ppciInit, pglyphBase);
+
+    if(boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }
+
+    SHADOW_GC_OP_EPILOGUE(pGC);
+}
+
+static void
+winShadowPolyGlyphBlt(
+    DrawablePtr pDraw,
+    GCPtr pGC,
+    int x, int y,
+    unsigned int nglyphInit,
+    CharInfoPtr *ppciInit,
+    pointer pglyphBase 
+){
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw) && nglyphInit) {
+        CharInfoPtr *ppci = ppciInit;
+        unsigned int nglyph = nglyphInit;
+
+	/* ugh */
+	box.x1 = pDraw->x + x + ppci[0]->metrics.leftSideBearing;
+	box.x2 = pDraw->x + x + ppci[nglyph - 1]->metrics.rightSideBearing;
+
+	if(nglyph > 1) {
+	    int width = 0;
+
+	    while(--nglyph) { 
+		width += (*ppci)->metrics.characterWidth;
+		ppci++;
+	    }
+	
+	    if(width > 0) box.x2 += width;
+	    else box.x1 += width;
+	}
+
+	box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+	box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+	TRIM_BOX(box, pGC);
+	if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+              (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+    }
+    
+    (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, x, y, nglyphInit, 
+				ppciInit, pglyphBase);
+
+    if(boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }
+
+    SHADOW_GC_OP_EPILOGUE(pGC);
+}
+
+static void
+winShadowPushPixels(
+    GCPtr	pGC,
+    PixmapPtr	pBitMap,
+    DrawablePtr pDraw,
+    int	dx, int dy, int xOrg, int yOrg 
+){
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+    
+    SHADOW_GC_OP_PROLOGUE(pGC);
+
+    if(IS_VISIBLE(pDraw)) {
+	box.x1 = xOrg;
+	box.y1 = yOrg;
+
+        if(!pGC->miTranslate) {
+           box.x1 += pDraw->x;          
+           box.y1 += pDraw->y;          
+        }
+
+	box.x2 = box.x1 + dx;
+	box.y2 = box.y1 + dy;
+
+	TRIM_BOX(box, pGC);
+	if(BOX_NOT_EMPTY(box)) {
+	   REGION_INIT(pScreen, &rgn, &box, 1);
+           if(pScrPriv->preRefresh)
+              (*pScrPriv->preRefresh)(pScreen, &rgn);
+           boxNotEmpty = TRUE;
+        }
+    }
+
+    (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg);
+
+    if(boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }
+
+    SHADOW_GC_OP_EPILOGUE(pGC);
+}
+
+
+GCOps winShadowGCOps = {
+    winShadowFillSpans, winShadowSetSpans, 
+    winShadowPutImage, winShadowCopyArea, 
+    winShadowCopyPlane, winShadowPolyPoint, 
+    winShadowPolylines, winShadowPolySegment, 
+    winShadowPolyRectangle, winShadowPolyArc, 
+    winShadowFillPolygon, winShadowPolyFillRect, 
+    winShadowPolyFillArc, winShadowPolyText8, 
+    winShadowPolyText16, winShadowImageText8, 
+    winShadowImageText16, winShadowImageGlyphBlt, 
+    winShadowPolyGlyphBlt, winShadowPushPixels,
+#ifdef NEED_LINEHELPER
+    NULL,
+#endif
+    {NULL}		/* devPrivate */
+};
+
+static void
+winShadowPaintWindow(
+  WindowPtr pWin,
+  RegionPtr prgn,
+  int what 
+){
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+    winShadowScrPriv(pScreen);
+    int num = 0;
+
+    if((num = REGION_NUM_RECTS(prgn)) && pScrPriv->preRefresh)
+        (*pScrPriv->preRefresh)(pScreen, prgn);
+
+    if(what == PW_BACKGROUND) {
+	unwrap (pScrPriv, pScreen, PaintWindowBackground);
+	(*pScreen->PaintWindowBackground) (pWin, prgn, what);
+	wrap (pScrPriv, pScreen, PaintWindowBackground, winShadowPaintWindow);
+    } else {
+	unwrap (pScrPriv, pScreen, PaintWindowBorder);
+	(*pScreen->PaintWindowBorder) (pWin, prgn, what);
+	wrap (pScrPriv, pScreen, PaintWindowBorder, winShadowPaintWindow);
+    }
+
+    if(num && pScrPriv->postRefresh)
+        (*pScrPriv->postRefresh)(pScreen, prgn);    
+}
+
+
+static void 
+winShadowCopyWindow(
+   WindowPtr pWin,
+   DDXPointRec ptOldOrg,
+   RegionPtr prgn 
+){
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+    winShadowScrPriv(pScreen);
+    int num = 0;
+    RegionRec rgnDst;
+
+    REGION_NULL(pWin->drawable.pScreen, &rgnDst);
+    REGION_COPY(pWin->drawable.pScreen, &rgnDst, prgn);
+        
+    REGION_TRANSLATE(pWin->drawable.pScreen, &rgnDst,
+                     pWin->drawable.x - ptOldOrg.x,
+                     pWin->drawable.y - ptOldOrg.y);
+    REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, &rgnDst);
+    if ((num = REGION_NUM_RECTS(&rgnDst))) {
+        if(pScrPriv->preRefresh)
+            (*pScrPriv->preRefresh)(pScreen, &rgnDst);
+    } else {
+        REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
+    }
+    
+    unwrap (pScrPriv, pScreen, CopyWindow);
+    (*pScreen->CopyWindow) (pWin, ptOldOrg, prgn);
+    wrap (pScrPriv, pScreen, CopyWindow, winShadowCopyWindow);
+    
+    if (num) {
+        if (pScrPriv->postRefresh)
+            (*pScrPriv->postRefresh)(pScreen, &rgnDst);
+        REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
+    }
+}
+
+
+static void
+winShadowRestoreAreas (    
+    PixmapPtr pPixmap,
+    RegionPtr prgn,
+    int       xorg,
+    int       yorg,
+    WindowPtr pWin 
+){
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+    winShadowScrPriv(pScreen);
+    int num = 0;
+
+    if((num = REGION_NUM_RECTS(prgn)) && pScrPriv->preRefresh)
+        (*pScrPriv->preRefresh)(pScreen, prgn);
+
+    unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas);
+    (*pScreen->BackingStoreFuncs.RestoreAreas) (
+                pPixmap, prgn, xorg, yorg, pWin);
+    wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas,
+			     winShadowRestoreAreas);
+
+    if(num && pScrPriv->postRefresh)
+	(*pScrPriv->postRefresh)(pScreen, prgn);
+}
+
+#ifdef RENDER
+static void
+winShadowComposite(
+    CARD8 op,
+    PicturePtr pSrc,
+    PicturePtr pMask,
+    PicturePtr pDst,
+    INT16 xSrc,
+    INT16 ySrc,
+    INT16 xMask,
+    INT16 yMask,
+    INT16 xDst,
+    INT16 yDst,
+    CARD16 width,
+    CARD16 height
+){
+    ScreenPtr pScreen = pDst->pDrawable->pScreen;
+    winShadowScrPriv(pScreen);
+    PictureScreenPtr ps = GetPictureScreen(pScreen);
+    BoxRec box;
+    RegionRec rgn;
+    Bool boxNotEmpty = FALSE;
+
+    if (pDst->pDrawable->type == DRAWABLE_WINDOW) {
+
+	box.x1 = pDst->pDrawable->x + xDst;
+	box.y1 = pDst->pDrawable->y + yDst;
+	box.x2 = box.x1 + width;
+	box.y2 = box.y1 + height;
+
+	TRIM_BOX(box, pDst);
+	
+	if (BOX_NOT_EMPTY(box)) {
+	    REGION_INIT(pScreen, &rgn, &box, 1);
+	    if (pScrPriv->preRefresh)
+		(*pScrPriv->preRefresh)(pScreen, &rgn);
+	    boxNotEmpty = TRUE;
+	}
+    }
+    
+    unwrap (pScrPriv, ps, Composite);
+    (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc,
+		     xMask, yMask, xDst, yDst, width, height);
+    wrap (pScrPriv, ps, Composite, winShadowComposite);
+
+    if (boxNotEmpty) {
+	if (pScrPriv->postRefresh)
+	    (*pScrPriv->postRefresh)(pScreen, &rgn);
+	REGION_UNINIT(pScreen, &rgn);
+    }
+}
+#endif /* RENDER */
+
+
+static Bool
+winShadowCloseScreen (int i, ScreenPtr pScreen)
+{
+    winShadowScrPriv(pScreen);
+#ifdef RENDER
+    PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+#endif /* RENDER */
+
+    unwrap (pScrPriv, pScreen, CloseScreen);
+    unwrap (pScrPriv, pScreen, PaintWindowBackground);
+    unwrap (pScrPriv, pScreen, PaintWindowBorder);
+    unwrap (pScrPriv, pScreen, CopyWindow);
+    unwrap (pScrPriv, pScreen, CreateGC);
+    unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas);
+#ifdef RENDER
+    if (ps) {
+	unwrap (pScrPriv, ps, Composite);
+    }
+#endif /* RENDER */
+
+    xfree (pScrPriv);
+    return (*pScreen->CloseScreen) (i, pScreen);
+}
+
+Bool
+winShadowSetup (ScreenPtr pScreen, 
+	winRefreshAreaProcPtr preRefresh, 
+	winRefreshAreaProcPtr postRefresh)
+{
+    winShadowScrPrivPtr	pScrPriv;
+#ifdef RENDER
+    PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+#endif /* RENDER */
+
+    if(!preRefresh && !postRefresh) return FALSE;
+
+    if (winShadowGeneration != serverGeneration)
+    {
+	winShadowScrPrivateIndex = AllocateScreenPrivateIndex ();
+	if (winShadowScrPrivateIndex == -1)
+	    return FALSE;
+	winShadowGCPrivateIndex = AllocateGCPrivateIndex ();
+	if (winShadowGCPrivateIndex == -1)
+	    return FALSE;
+	winShadowGeneration = serverGeneration;
+    }
+    if (!AllocateGCPrivate (pScreen, winShadowGCPrivateIndex, sizeof (winShadowGCPrivRec)))
+	return FALSE;
+    pScrPriv = (winShadowScrPrivPtr) xalloc (sizeof (winShadowScrPrivRec));
+    if (!pScrPriv)
+	return FALSE;
+
+    wrap (pScrPriv, pScreen, CloseScreen, winShadowCloseScreen);
+    wrap (pScrPriv, pScreen, PaintWindowBackground, winShadowPaintWindow);
+    wrap (pScrPriv, pScreen, PaintWindowBorder, winShadowPaintWindow);
+    wrap (pScrPriv, pScreen, CopyWindow, winShadowCopyWindow);
+    wrap (pScrPriv, pScreen, CreateGC, winShadowCreateGC);
+    wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas, winShadowRestoreAreas);
+#ifdef RENDER
+    if (ps) {
+	wrap (pScrPriv, ps, Composite, winShadowComposite);
+    }
+#endif /* RENDER */
+
+    pScrPriv->preRefresh = preRefresh;
+    pScrPriv->postRefresh = postRefresh;
+
+    pScreen->devPrivates[winShadowScrPrivateIndex].ptr = (pointer) pScrPriv;
+
+    return TRUE;
+}
+
diff --git a/hw/xwin/winshadow.h b/hw/xwin/winshadow.h
new file mode 100644
index 0000000..1f2a9a1
--- /dev/null
+++ b/hw/xwin/winshadow.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright © 2007 Jie Luo
+ *
+ */
+
+#ifndef _WINSHADOW_H_
+#define _WINSHADOW_H_
+
+typedef void (*winRefreshAreaProcPtr)(ScreenPtr, RegionPtr);
+
+Bool
+winShadowSetup (
+	ScreenPtr pScreen, 
+	winRefreshAreaProcPtr preRefresh, 
+	winRefreshAreaProcPtr postRefresh);
+
+#endif /* _SHADOW_H_ */
