From 74663e61528346aeea9c11908b6980b51dcaeb68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 20 Dec 2010 16:37:24 +0200 Subject: [PATCH] composite: Copy the window contents back from the pixmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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ä Reviewed-by: Daniel Stone --- 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 23654a7bdc..37d2245d45 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); + } } /* @@ -621,10 +658,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) @@ -640,11 +677,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 57e0b5dea7..bb5335d70a 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 2440f18977..bcbdf35729 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;