aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/composite/compalloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/composite/compalloc.c')
-rw-r--r--xorg-server/composite/compalloc.c147
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);
}
/*