[PATCH v3 4/6] composite: Copy the window contents back from the pixmap

ville.syrjala at nokia.com ville.syrjala at nokia.com
Fri Apr 15 11:42:12 PDT 2011


From: Ville Syrjälä <ville.syrjala at nokia.com>

Since extra expose events are no longer generated during window
unredirection, the window contents must be preserved by the server.
So copy the window contents back from the pixmap. The copy can only
be done after the clips have been recomputed, so delay the copy and
the pixmap destruction until ValidateTree is done. Window borders are
restored by HandleExposures and thus don't need to be copied back.

Signed-off-by: Ville Syrjälä <ville.syrjala at nokia.com>
Reviewed-by: Daniel Stone <daniel at fooishbar.org>
---
v3: unchanged

 composite/compalloc.c  |   47 +++++++++++++++++++++++++++++++++++++++++------
 composite/compint.h    |    5 ++++-
 composite/compwindow.c |   16 ++++++++++++----
 3 files changed, 57 insertions(+), 11 deletions(-)

diff --git a/composite/compalloc.c b/composite/compalloc.c
index 8130948..e6f70e4 100644
--- a/composite/compalloc.c
+++ b/composite/compalloc.c
@@ -239,6 +239,34 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
     return Success;
 }
 
+void
+compRestoreWindow (WindowPtr pWin, PixmapPtr pPixmap)
+{
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+    WindowPtr pParent = pWin->parent;
+
+    if (pParent->drawable.depth == pWin->drawable.depth) {
+	GCPtr pGC = GetScratchGC (pWin->drawable.depth, pScreen);
+	int bw = (int) pWin->borderWidth;
+	int x = bw;
+	int y = bw;
+	int w = pWin->drawable.width;
+	int h = pWin->drawable.height;
+
+	if (pGC) {
+	    ChangeGCVal val;
+	    val.val = IncludeInferiors;
+	    ChangeGC (NullClient, pGC, GCSubwindowMode, &val);
+	    ValidateGC(&pWin->drawable, pGC);
+	    (*pGC->ops->CopyArea) (&pPixmap->drawable,
+				   &pWin->drawable,
+				   pGC,
+				   x, y, w, h, 0, 0);
+	    FreeScratchGC (pGC);
+	}
+    }
+}
+
 /*
  * Free one of the per-client per-window resources, clearing
  * redirect and the per-window pointer as appropriate
@@ -246,10 +274,12 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
 void
 compFreeClientWindow (WindowPtr pWin, XID id)
 {
+    ScreenPtr		pScreen = pWin->drawable.pScreen;
     CompWindowPtr	cw = GetCompWindow (pWin);
     CompClientWindowPtr	ccw, *prev;
     Bool		anyMarked = FALSE;
     WindowPtr		pLayerWin;
+    PixmapPtr           pPixmap = NULL;
 
     if (!cw)
 	return;
@@ -268,8 +298,10 @@ compFreeClientWindow (WindowPtr pWin, XID id)
     {
 	anyMarked = compMarkWindows (pWin, &pLayerWin);
     
-	if (pWin->redirectDraw != RedirectDrawNone)
-	    compFreePixmap (pWin);
+	if (pWin->redirectDraw != RedirectDrawNone) {
+	    pPixmap = (*pScreen->GetWindowPixmap) (pWin);
+	    compSetParentPixmap (pWin);
+	}
 
 	if (cw->damage)
 	    DamageDestroy (cw->damage);
@@ -290,6 +322,11 @@ compFreeClientWindow (WindowPtr pWin, XID id)
 
     if (anyMarked)
 	compHandleMarkedWindows (pWin, pLayerWin);
+
+    if (pPixmap) {
+	compRestoreWindow (pWin, pPixmap);
+	(*pScreen->DestroyPixmap) (pPixmap);
+    }
 }
 
 /*
@@ -647,10 +684,10 @@ compAllocPixmap (WindowPtr pWin)
 }
 
 void
-compFreePixmap (WindowPtr pWin)
+compSetParentPixmap (WindowPtr pWin)
 {
     ScreenPtr	    pScreen = pWin->drawable.pScreen;
-    PixmapPtr	    pRedirectPixmap, pParentPixmap;
+    PixmapPtr	    pParentPixmap;
     CompWindowPtr   cw = GetCompWindow (pWin);
 
     if (cw->damageRegistered)
@@ -666,11 +703,9 @@ compFreePixmap (WindowPtr pWin)
      * parent exposed area; regions beyond the parent cause crashes
      */
     RegionCopy(&pWin->borderClip, &cw->borderClip);
-    pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin);
     pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent);
     pWin->redirectDraw = RedirectDrawNone;
     compSetPixmap (pWin, pParentPixmap);
-    (*pScreen->DestroyPixmap) (pRedirectPixmap);
 }
 
 /*
diff --git a/composite/compint.h b/composite/compint.h
index 57e0b5d..bb5335d 100644
--- a/composite/compint.h
+++ b/composite/compint.h
@@ -215,7 +215,10 @@ Bool
 compAllocPixmap (WindowPtr pWin);
 
 void
-compFreePixmap (WindowPtr pWin);
+compSetParentPixmap (WindowPtr pWin);
+
+void
+compRestoreWindow (WindowPtr pWin, PixmapPtr pPixmap);
 
 Bool
 compReallocPixmap (WindowPtr pWin, int x, int y,
diff --git a/composite/compwindow.c b/composite/compwindow.c
index 2440f18..bcbdf35 100644
--- a/composite/compwindow.c
+++ b/composite/compwindow.c
@@ -164,8 +164,13 @@ compCheckRedirect (WindowPtr pWin)
     {
 	if (should)
 	    return compAllocPixmap (pWin);
-	else
-	    compFreePixmap (pWin);
+	else {
+	    ScreenPtr pScreen = pWin->drawable.pScreen;
+	    PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
+	    compSetParentPixmap (pWin);
+	    compRestoreWindow (pWin, pPixmap);
+	    (*pScreen->DestroyPixmap) (pPixmap);
+	}
     }
     return TRUE;
 }
@@ -583,8 +588,11 @@ compDestroyWindow (WindowPtr pWin)
     while ((csw = GetCompSubwindows (pWin)))
 	FreeResource (csw->clients->id, RT_NONE);
 
-    if (pWin->redirectDraw != RedirectDrawNone)
-	compFreePixmap (pWin);
+    if (pWin->redirectDraw != RedirectDrawNone) {
+	PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
+	compSetParentPixmap (pWin);
+	(*pScreen->DestroyPixmap) (pPixmap);
+    }
     ret = (*pScreen->DestroyWindow) (pWin);
     cs->DestroyWindow = pScreen->DestroyWindow;
     pScreen->DestroyWindow = compDestroyWindow;
-- 
1.7.3.4



More information about the xorg-devel mailing list