diff options
Diffstat (limited to 'xorg-server/composite/compalloc.c')
-rw-r--r-- | xorg-server/composite/compalloc.c | 147 |
1 files changed, 96 insertions, 51 deletions
diff --git a/xorg-server/composite/compalloc.c b/xorg-server/composite/compalloc.c index 7164c0d3c..5c27631e1 100644 --- a/xorg-server/composite/compalloc.c +++ b/xorg-server/composite/compalloc.c @@ -104,6 +104,35 @@ compDestroyDamage (DamagePtr pDamage, void *closure) cw->damage = 0; } +static Bool +compMarkWindows(WindowPtr pWin, + WindowPtr *ppLayerWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pLayerWin = pWin; + + if (!pWin->viewable) + return FALSE; + + (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + (*pScreen->MarkWindow)(pLayerWin->parent); + + *ppLayerWin = pLayerWin; + + return TRUE; +} + +static void +compHandleMarkedWindows(WindowPtr pWin, WindowPtr pLayerWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther); + (*pScreen->HandleExposures)(pLayerWin->parent); + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTOther); +} + /* * Redirect one window for one client */ @@ -112,8 +141,9 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) { CompWindowPtr cw = GetCompWindow (pWin); CompClientWindowPtr ccw; - Bool wasMapped = pWin->mapped; CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); + WindowPtr pLayerWin; + Bool anyMarked = FALSE; if (pWin == cs->pOverlayWin) { return Success; @@ -163,16 +193,14 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) free(cw); return BadAlloc; } - if (wasMapped) - { - DisableMapUnmapEvents (pWin); - UnmapWindow (pWin, FALSE); - EnableMapUnmapEvents (pWin); - } + anyMarked = compMarkWindows (pWin, &pLayerWin); + + /* Make sure our borderClip is correct for ValidateTree */ RegionNull(&cw->borderClip); - cw->borderClipX = 0; - cw->borderClipY = 0; + RegionCopy(&cw->borderClip, &pWin->borderClip); + cw->borderClipX = pWin->drawable.x; + cw->borderClipY = pWin->drawable.y; cw->update = CompositeRedirectAutomatic; cw->clients = 0; cw->oldx = COMP_ORIGIN_INVALID; @@ -188,16 +216,9 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) return BadAlloc; if (ccw->update == CompositeRedirectManual) { - /* If the window was CompositeRedirectAutomatic, then - * unmap the window so that the parent clip list will - * be correctly recomputed. - */ - if (pWin->mapped) - { - DisableMapUnmapEvents (pWin); - UnmapWindow (pWin, FALSE); - EnableMapUnmapEvents (pWin); - } + if (!anyMarked) + anyMarked = compMarkWindows (pWin, &pLayerWin); + if (cw->damageRegistered) { DamageUnregister (&pWin->drawable, cw->damage); @@ -205,25 +226,51 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) } cw->update = CompositeRedirectManual; } + else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) { + if (!anyMarked) + anyMarked = compMarkWindows (pWin, &pLayerWin); + } if (!compCheckRedirect (pWin)) { FreeResource (ccw->id, RT_NONE); return BadAlloc; } - if (wasMapped && !pWin->mapped) - { - Bool overrideRedirect = pWin->overrideRedirect; - pWin->overrideRedirect = TRUE; - DisableMapUnmapEvents (pWin); - MapWindow (pWin, pClient); - EnableMapUnmapEvents (pWin); - pWin->overrideRedirect = overrideRedirect; - } + + if (anyMarked) + compHandleMarkedWindows (pWin, pLayerWin); 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 @@ -231,9 +278,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 wasMapped = pWin->mapped; + Bool anyMarked = FALSE; + WindowPtr pLayerWin; + PixmapPtr pPixmap = NULL; if (!cw) return; @@ -250,15 +300,12 @@ compFreeClientWindow (WindowPtr pWin, XID id) } if (!cw->clients) { - if (wasMapped) - { - DisableMapUnmapEvents (pWin); - UnmapWindow (pWin, FALSE); - EnableMapUnmapEvents (pWin); - } + 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); @@ -271,19 +318,20 @@ compFreeClientWindow (WindowPtr pWin, XID id) else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone) { + anyMarked = compMarkWindows (pWin, &pLayerWin); + DamageRegister (&pWin->drawable, cw->damage); cw->damageRegistered = TRUE; pWin->redirectDraw = RedirectDrawAutomatic; DamageDamageRegion(&pWin->drawable, &pWin->borderSize); } - if (wasMapped && !pWin->mapped) - { - Bool overrideRedirect = pWin->overrideRedirect; - pWin->overrideRedirect = TRUE; - DisableMapUnmapEvents (pWin); - MapWindow (pWin, clients[CLIENT_ID(id)]); - EnableMapUnmapEvents (pWin); - pWin->overrideRedirect = overrideRedirect; + + if (anyMarked) + compHandleMarkedWindows (pWin, pLayerWin); + + if (pPixmap) { + compRestoreWindow (pWin, pPixmap); + (*pScreen->DestroyPixmap) (pPixmap); } } @@ -536,9 +584,8 @@ compNewPixmap (WindowPtr pWin, int x, int y, int w, int h, Bool map) { ChangeGCVal val; val.val = IncludeInferiors; - + ChangeGC (NullClient, pGC, GCSubwindowMode, &val); ValidateGC(&pPixmap->drawable, pGC); - ChangeGC (serverClient, pGC, GCSubwindowMode, &val); (*pGC->ops->CopyArea) (&pParent->drawable, &pPixmap->drawable, pGC, @@ -617,10 +664,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) @@ -636,11 +683,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); } /* |