compalloc.c revision 6747b715
105b261ecSmrg/*
26747b715Smrg * Copyright © 2006 Sun Microsystems, Inc.  All rights reserved.
305b261ecSmrg *
46747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a
56747b715Smrg * copy of this software and associated documentation files (the "Software"),
66747b715Smrg * to deal in the Software without restriction, including without limitation
76747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
86747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the
96747b715Smrg * Software is furnished to do so, subject to the following conditions:
1005b261ecSmrg *
116747b715Smrg * The above copyright notice and this permission notice (including the next
126747b715Smrg * paragraph) shall be included in all copies or substantial portions of the
136747b715Smrg * Software.
146747b715Smrg *
156747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
166747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
176747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
186747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
196747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
206747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
216747b715Smrg * DEALINGS IN THE SOFTWARE.
2205b261ecSmrg *
2305b261ecSmrg * Copyright © 2003 Keith Packard
2405b261ecSmrg *
2505b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
2605b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
2705b261ecSmrg * the above copyright notice appear in all copies and that both that
2805b261ecSmrg * copyright notice and this permission notice appear in supporting
2905b261ecSmrg * documentation, and that the name of Keith Packard not be used in
3005b261ecSmrg * advertising or publicity pertaining to distribution of the software without
3105b261ecSmrg * specific, written prior permission.  Keith Packard makes no
3205b261ecSmrg * representations about the suitability of this software for any purpose.  It
3305b261ecSmrg * is provided "as is" without express or implied warranty.
3405b261ecSmrg *
3505b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
3605b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
3705b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
3805b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
3905b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
4005b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
4105b261ecSmrg * PERFORMANCE OF THIS SOFTWARE.
4205b261ecSmrg */
4305b261ecSmrg
4405b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
4505b261ecSmrg#include <dix-config.h>
4605b261ecSmrg#endif
4705b261ecSmrg
4805b261ecSmrg#include "compint.h"
4905b261ecSmrg
5005b261ecSmrgstatic void
5105b261ecSmrgcompReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
5205b261ecSmrg{
5305b261ecSmrg    WindowPtr	    pWin = (WindowPtr) closure;
5405b261ecSmrg    ScreenPtr	    pScreen = pWin->drawable.pScreen;
5505b261ecSmrg    CompScreenPtr   cs = GetCompScreen (pScreen);
5605b261ecSmrg    CompWindowPtr   cw = GetCompWindow (pWin);
5705b261ecSmrg
5805b261ecSmrg    cs->damaged = TRUE;
5905b261ecSmrg    cw->damaged = TRUE;
6005b261ecSmrg}
6105b261ecSmrg
6205b261ecSmrgstatic void
6305b261ecSmrgcompDestroyDamage (DamagePtr pDamage, void *closure)
6405b261ecSmrg{
6505b261ecSmrg    WindowPtr	    pWin = (WindowPtr) closure;
6605b261ecSmrg    CompWindowPtr   cw = GetCompWindow (pWin);
6705b261ecSmrg
6805b261ecSmrg    cw->damage = 0;
6905b261ecSmrg}
7005b261ecSmrg
7105b261ecSmrg/*
7205b261ecSmrg * Redirect one window for one client
7305b261ecSmrg */
7405b261ecSmrgint
7505b261ecSmrgcompRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
7605b261ecSmrg{
7705b261ecSmrg    CompWindowPtr	cw = GetCompWindow (pWin);
7805b261ecSmrg    CompClientWindowPtr	ccw;
7905b261ecSmrg    Bool		wasMapped = pWin->mapped;
8005b261ecSmrg    CompScreenPtr       cs = GetCompScreen(pWin->drawable.pScreen);
8105b261ecSmrg
8205b261ecSmrg    if (pWin == cs->pOverlayWin) {
8305b261ecSmrg	return Success;
8405b261ecSmrg    }
8505b261ecSmrg
864642e01fSmrg    if (!pWin->parent)
874642e01fSmrg	return BadMatch;
884642e01fSmrg
8905b261ecSmrg    /*
9005b261ecSmrg     * Only one Manual update is allowed
9105b261ecSmrg     */
9205b261ecSmrg    if (cw && update == CompositeRedirectManual)
9305b261ecSmrg	for (ccw = cw->clients; ccw; ccw = ccw->next)
9405b261ecSmrg	    if (ccw->update == CompositeRedirectManual)
9505b261ecSmrg		return BadAccess;
9605b261ecSmrg
9705b261ecSmrg    /*
9805b261ecSmrg     * Allocate per-client per-window structure
9905b261ecSmrg     * The client *could* allocate multiple, but while supported,
10005b261ecSmrg     * it is not expected to be common
10105b261ecSmrg     */
1026747b715Smrg    ccw = malloc(sizeof (CompClientWindowRec));
10305b261ecSmrg    if (!ccw)
10405b261ecSmrg	return BadAlloc;
10505b261ecSmrg    ccw->id = FakeClientID (pClient->index);
10605b261ecSmrg    ccw->update = update;
10705b261ecSmrg    /*
10805b261ecSmrg     * Now make sure there's a per-window structure to hang this from
10905b261ecSmrg     */
11005b261ecSmrg    if (!cw)
11105b261ecSmrg    {
1126747b715Smrg	cw = malloc(sizeof (CompWindowRec));
11305b261ecSmrg	if (!cw)
11405b261ecSmrg	{
1156747b715Smrg	    free(ccw);
11605b261ecSmrg	    return BadAlloc;
11705b261ecSmrg	}
11805b261ecSmrg	cw->damage = DamageCreate (compReportDamage,
11905b261ecSmrg				   compDestroyDamage,
12005b261ecSmrg				   DamageReportNonEmpty,
12105b261ecSmrg				   FALSE,
12205b261ecSmrg				   pWin->drawable.pScreen,
12305b261ecSmrg				   pWin);
12405b261ecSmrg	if (!cw->damage)
12505b261ecSmrg	{
1266747b715Smrg	    free(ccw);
1276747b715Smrg	    free(cw);
12805b261ecSmrg	    return BadAlloc;
12905b261ecSmrg	}
13005b261ecSmrg	if (wasMapped)
13105b261ecSmrg	{
13205b261ecSmrg	    DisableMapUnmapEvents (pWin);
13305b261ecSmrg	    UnmapWindow (pWin, FALSE);
13405b261ecSmrg	    EnableMapUnmapEvents (pWin);
13505b261ecSmrg	}
13605b261ecSmrg
1376747b715Smrg	RegionNull(&cw->borderClip);
1386747b715Smrg	cw->borderClipX = 0;
1396747b715Smrg	cw->borderClipY = 0;
14005b261ecSmrg	cw->update = CompositeRedirectAutomatic;
14105b261ecSmrg	cw->clients = 0;
14205b261ecSmrg	cw->oldx = COMP_ORIGIN_INVALID;
14305b261ecSmrg	cw->oldy = COMP_ORIGIN_INVALID;
14405b261ecSmrg	cw->damageRegistered = FALSE;
14505b261ecSmrg	cw->damaged = FALSE;
1466747b715Smrg	cw->pOldPixmap = NullPixmap;
1474642e01fSmrg	dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw);
14805b261ecSmrg    }
14905b261ecSmrg    ccw->next = cw->clients;
15005b261ecSmrg    cw->clients = ccw;
15105b261ecSmrg    if (!AddResource (ccw->id, CompositeClientWindowType, pWin))
15205b261ecSmrg	return BadAlloc;
15305b261ecSmrg    if (ccw->update == CompositeRedirectManual)
15405b261ecSmrg    {
1554642e01fSmrg	/* If the window was CompositeRedirectAutomatic, then
1564642e01fSmrg	 * unmap the window so that the parent clip list will
1574642e01fSmrg	 * be correctly recomputed.
1584642e01fSmrg	 */
1594642e01fSmrg	if (pWin->mapped)
1604642e01fSmrg	{
1614642e01fSmrg	    DisableMapUnmapEvents (pWin);
1624642e01fSmrg	    UnmapWindow (pWin, FALSE);
1634642e01fSmrg	    EnableMapUnmapEvents (pWin);
1644642e01fSmrg	}
16505b261ecSmrg	if (cw->damageRegistered)
16605b261ecSmrg	{
16705b261ecSmrg	    DamageUnregister (&pWin->drawable, cw->damage);
16805b261ecSmrg	    cw->damageRegistered = FALSE;
16905b261ecSmrg	}
17005b261ecSmrg	cw->update = CompositeRedirectManual;
17105b261ecSmrg    }
17205b261ecSmrg
17305b261ecSmrg    if (!compCheckRedirect (pWin))
17405b261ecSmrg    {
17505b261ecSmrg	FreeResource (ccw->id, RT_NONE);
17605b261ecSmrg	return BadAlloc;
17705b261ecSmrg    }
17805b261ecSmrg    if (wasMapped && !pWin->mapped)
17905b261ecSmrg    {
18005b261ecSmrg	Bool	overrideRedirect = pWin->overrideRedirect;
18105b261ecSmrg	pWin->overrideRedirect = TRUE;
18205b261ecSmrg	DisableMapUnmapEvents (pWin);
18305b261ecSmrg	MapWindow (pWin, pClient);
18405b261ecSmrg	EnableMapUnmapEvents (pWin);
18505b261ecSmrg	pWin->overrideRedirect = overrideRedirect;
18605b261ecSmrg    }
18705b261ecSmrg
18805b261ecSmrg    return Success;
18905b261ecSmrg}
19005b261ecSmrg
19105b261ecSmrg/*
19205b261ecSmrg * Free one of the per-client per-window resources, clearing
19305b261ecSmrg * redirect and the per-window pointer as appropriate
19405b261ecSmrg */
19505b261ecSmrgvoid
19605b261ecSmrgcompFreeClientWindow (WindowPtr pWin, XID id)
19705b261ecSmrg{
19805b261ecSmrg    CompWindowPtr	cw = GetCompWindow (pWin);
19905b261ecSmrg    CompClientWindowPtr	ccw, *prev;
20005b261ecSmrg    Bool		wasMapped = pWin->mapped;
20105b261ecSmrg
20205b261ecSmrg    if (!cw)
20305b261ecSmrg	return;
20405b261ecSmrg    for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next)
20505b261ecSmrg    {
20605b261ecSmrg	if (ccw->id == id)
20705b261ecSmrg	{
20805b261ecSmrg	    *prev = ccw->next;
20905b261ecSmrg	    if (ccw->update == CompositeRedirectManual)
21005b261ecSmrg		cw->update = CompositeRedirectAutomatic;
2116747b715Smrg	    free(ccw);
21205b261ecSmrg	    break;
21305b261ecSmrg	}
21405b261ecSmrg    }
21505b261ecSmrg    if (!cw->clients)
21605b261ecSmrg    {
21705b261ecSmrg	if (wasMapped)
21805b261ecSmrg	{
21905b261ecSmrg	    DisableMapUnmapEvents (pWin);
22005b261ecSmrg	    UnmapWindow (pWin, FALSE);
22105b261ecSmrg	    EnableMapUnmapEvents (pWin);
22205b261ecSmrg	}
22305b261ecSmrg
22405b261ecSmrg	if (pWin->redirectDraw != RedirectDrawNone)
22505b261ecSmrg	    compFreePixmap (pWin);
22605b261ecSmrg
22705b261ecSmrg	if (cw->damage)
22805b261ecSmrg	    DamageDestroy (cw->damage);
22905b261ecSmrg
2306747b715Smrg	RegionUninit(&cw->borderClip);
23105b261ecSmrg
2324642e01fSmrg	dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL);
2336747b715Smrg	free(cw);
23405b261ecSmrg    }
23505b261ecSmrg    else if (cw->update == CompositeRedirectAutomatic &&
23605b261ecSmrg	     !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone)
23705b261ecSmrg    {
23805b261ecSmrg	DamageRegister (&pWin->drawable, cw->damage);
23905b261ecSmrg	cw->damageRegistered = TRUE;
24005b261ecSmrg	pWin->redirectDraw = RedirectDrawAutomatic;
2414642e01fSmrg	DamageRegionAppend(&pWin->drawable, &pWin->borderSize);
24205b261ecSmrg    }
24305b261ecSmrg    if (wasMapped && !pWin->mapped)
24405b261ecSmrg    {
24505b261ecSmrg	Bool	overrideRedirect = pWin->overrideRedirect;
24605b261ecSmrg	pWin->overrideRedirect = TRUE;
24705b261ecSmrg	DisableMapUnmapEvents (pWin);
24805b261ecSmrg	MapWindow (pWin, clients[CLIENT_ID(id)]);
24905b261ecSmrg	EnableMapUnmapEvents (pWin);
25005b261ecSmrg	pWin->overrideRedirect = overrideRedirect;
25105b261ecSmrg    }
25205b261ecSmrg}
25305b261ecSmrg
25405b261ecSmrg/*
25505b261ecSmrg * This is easy, just free the appropriate resource.
25605b261ecSmrg */
25705b261ecSmrg
25805b261ecSmrgint
25905b261ecSmrgcompUnredirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
26005b261ecSmrg{
26105b261ecSmrg    CompWindowPtr	cw = GetCompWindow (pWin);
26205b261ecSmrg    CompClientWindowPtr	ccw;
26305b261ecSmrg
26405b261ecSmrg    if (!cw)
26505b261ecSmrg	return BadValue;
26605b261ecSmrg
26705b261ecSmrg    for (ccw = cw->clients; ccw; ccw = ccw->next)
26805b261ecSmrg	if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index)
26905b261ecSmrg	{
27005b261ecSmrg	    FreeResource (ccw->id, RT_NONE);
27105b261ecSmrg	    return Success;
27205b261ecSmrg	}
27305b261ecSmrg    return BadValue;
27405b261ecSmrg}
27505b261ecSmrg
27605b261ecSmrg/*
27705b261ecSmrg * Redirect all subwindows for one client
27805b261ecSmrg */
27905b261ecSmrg
28005b261ecSmrgint
28105b261ecSmrgcompRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update)
28205b261ecSmrg{
28305b261ecSmrg    CompSubwindowsPtr	csw = GetCompSubwindows (pWin);
28405b261ecSmrg    CompClientWindowPtr	ccw;
28505b261ecSmrg    WindowPtr		pChild;
28605b261ecSmrg
28705b261ecSmrg    /*
28805b261ecSmrg     * Only one Manual update is allowed
28905b261ecSmrg     */
29005b261ecSmrg    if (csw && update == CompositeRedirectManual)
29105b261ecSmrg	for (ccw = csw->clients; ccw; ccw = ccw->next)
29205b261ecSmrg	    if (ccw->update == CompositeRedirectManual)
29305b261ecSmrg		return BadAccess;
29405b261ecSmrg    /*
29505b261ecSmrg     * Allocate per-client per-window structure
29605b261ecSmrg     * The client *could* allocate multiple, but while supported,
29705b261ecSmrg     * it is not expected to be common
29805b261ecSmrg     */
2996747b715Smrg    ccw = malloc(sizeof (CompClientWindowRec));
30005b261ecSmrg    if (!ccw)
30105b261ecSmrg	return BadAlloc;
30205b261ecSmrg    ccw->id = FakeClientID (pClient->index);
30305b261ecSmrg    ccw->update = update;
30405b261ecSmrg    /*
30505b261ecSmrg     * Now make sure there's a per-window structure to hang this from
30605b261ecSmrg     */
30705b261ecSmrg    if (!csw)
30805b261ecSmrg    {
3096747b715Smrg	csw = malloc(sizeof (CompSubwindowsRec));
31005b261ecSmrg	if (!csw)
31105b261ecSmrg	{
3126747b715Smrg	    free(ccw);
31305b261ecSmrg	    return BadAlloc;
31405b261ecSmrg	}
31505b261ecSmrg	csw->update = CompositeRedirectAutomatic;
31605b261ecSmrg	csw->clients = 0;
3174642e01fSmrg	dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw);
31805b261ecSmrg    }
31905b261ecSmrg    /*
32005b261ecSmrg     * Redirect all existing windows
32105b261ecSmrg     */
32205b261ecSmrg    for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
32305b261ecSmrg    {
32405b261ecSmrg	int ret = compRedirectWindow (pClient, pChild, update);
32505b261ecSmrg	if (ret != Success)
32605b261ecSmrg	{
32705b261ecSmrg	    for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib)
32805b261ecSmrg		(void) compUnredirectWindow (pClient, pChild, update);
32905b261ecSmrg	    if (!csw->clients)
33005b261ecSmrg	    {
3316747b715Smrg		free(csw);
3324642e01fSmrg		dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0);
33305b261ecSmrg	    }
3346747b715Smrg	    free(ccw);
33505b261ecSmrg	    return ret;
33605b261ecSmrg	}
33705b261ecSmrg    }
33805b261ecSmrg    /*
33905b261ecSmrg     * Hook into subwindows list
34005b261ecSmrg     */
34105b261ecSmrg    ccw->next = csw->clients;
34205b261ecSmrg    csw->clients = ccw;
34305b261ecSmrg    if (!AddResource (ccw->id, CompositeClientSubwindowsType, pWin))
34405b261ecSmrg	return BadAlloc;
34505b261ecSmrg    if (ccw->update == CompositeRedirectManual)
34605b261ecSmrg    {
34705b261ecSmrg	csw->update = CompositeRedirectManual;
34805b261ecSmrg	/*
34905b261ecSmrg	 * tell damage extension that damage events for this client are
35005b261ecSmrg	 * critical output
35105b261ecSmrg	 */
35205b261ecSmrg	DamageExtSetCritical (pClient, TRUE);
35305b261ecSmrg    }
35405b261ecSmrg    return Success;
35505b261ecSmrg}
35605b261ecSmrg
35705b261ecSmrg/*
35805b261ecSmrg * Free one of the per-client per-subwindows resources,
35905b261ecSmrg * which frees one redirect per subwindow
36005b261ecSmrg */
36105b261ecSmrgvoid
36205b261ecSmrgcompFreeClientSubwindows (WindowPtr pWin, XID id)
36305b261ecSmrg{
36405b261ecSmrg    CompSubwindowsPtr	csw = GetCompSubwindows (pWin);
36505b261ecSmrg    CompClientWindowPtr	ccw, *prev;
36605b261ecSmrg    WindowPtr		pChild;
36705b261ecSmrg
36805b261ecSmrg    if (!csw)
36905b261ecSmrg	return;
37005b261ecSmrg    for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next)
37105b261ecSmrg    {
37205b261ecSmrg	if (ccw->id == id)
37305b261ecSmrg	{
37405b261ecSmrg	    ClientPtr	pClient = clients[CLIENT_ID(id)];
37505b261ecSmrg
37605b261ecSmrg	    *prev = ccw->next;
37705b261ecSmrg	    if (ccw->update == CompositeRedirectManual)
37805b261ecSmrg	    {
37905b261ecSmrg		/*
38005b261ecSmrg		 * tell damage extension that damage events for this client are
38105b261ecSmrg		 * critical output
38205b261ecSmrg		 */
38305b261ecSmrg		DamageExtSetCritical (pClient, FALSE);
38405b261ecSmrg		csw->update = CompositeRedirectAutomatic;
38505b261ecSmrg		if (pWin->mapped)
38605b261ecSmrg		    (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, TRUE);
38705b261ecSmrg	    }
38805b261ecSmrg
38905b261ecSmrg	    /*
39005b261ecSmrg	     * Unredirect all existing subwindows
39105b261ecSmrg	     */
39205b261ecSmrg	    for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
39305b261ecSmrg		(void) compUnredirectWindow (pClient, pChild, ccw->update);
39405b261ecSmrg
3956747b715Smrg	    free(ccw);
39605b261ecSmrg	    break;
39705b261ecSmrg	}
39805b261ecSmrg    }
39905b261ecSmrg
40005b261ecSmrg    /*
40105b261ecSmrg     * Check if all of the per-client records are gone
40205b261ecSmrg     */
40305b261ecSmrg    if (!csw->clients)
40405b261ecSmrg    {
4054642e01fSmrg	dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL);
4066747b715Smrg	free(csw);
40705b261ecSmrg    }
40805b261ecSmrg}
40905b261ecSmrg
41005b261ecSmrg/*
41105b261ecSmrg * This is easy, just free the appropriate resource.
41205b261ecSmrg */
41305b261ecSmrg
41405b261ecSmrgint
41505b261ecSmrgcompUnredirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update)
41605b261ecSmrg{
41705b261ecSmrg    CompSubwindowsPtr	csw = GetCompSubwindows (pWin);
41805b261ecSmrg    CompClientWindowPtr	ccw;
41905b261ecSmrg
42005b261ecSmrg    if (!csw)
42105b261ecSmrg	return BadValue;
42205b261ecSmrg    for (ccw = csw->clients; ccw; ccw = ccw->next)
42305b261ecSmrg	if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index)
42405b261ecSmrg	{
42505b261ecSmrg	    FreeResource (ccw->id, RT_NONE);
42605b261ecSmrg	    return Success;
42705b261ecSmrg	}
42805b261ecSmrg    return BadValue;
42905b261ecSmrg}
43005b261ecSmrg
43105b261ecSmrg/*
43205b261ecSmrg * Add redirection information for one subwindow (during reparent)
43305b261ecSmrg */
43405b261ecSmrg
43505b261ecSmrgint
43605b261ecSmrgcompRedirectOneSubwindow (WindowPtr pParent, WindowPtr pWin)
43705b261ecSmrg{
43805b261ecSmrg    CompSubwindowsPtr	csw = GetCompSubwindows (pParent);
43905b261ecSmrg    CompClientWindowPtr	ccw;
44005b261ecSmrg
44105b261ecSmrg    if (!csw)
44205b261ecSmrg	return Success;
44305b261ecSmrg    for (ccw = csw->clients; ccw; ccw = ccw->next)
44405b261ecSmrg    {
44505b261ecSmrg	int ret = compRedirectWindow (clients[CLIENT_ID(ccw->id)],
44605b261ecSmrg				      pWin, ccw->update);
44705b261ecSmrg	if (ret != Success)
44805b261ecSmrg	    return ret;
44905b261ecSmrg    }
45005b261ecSmrg    return Success;
45105b261ecSmrg}
45205b261ecSmrg
45305b261ecSmrg/*
45405b261ecSmrg * Remove redirection information for one subwindow (during reparent)
45505b261ecSmrg */
45605b261ecSmrg
45705b261ecSmrgint
45805b261ecSmrgcompUnredirectOneSubwindow (WindowPtr pParent, WindowPtr pWin)
45905b261ecSmrg{
46005b261ecSmrg    CompSubwindowsPtr	csw = GetCompSubwindows (pParent);
46105b261ecSmrg    CompClientWindowPtr	ccw;
46205b261ecSmrg
46305b261ecSmrg    if (!csw)
46405b261ecSmrg	return Success;
46505b261ecSmrg    for (ccw = csw->clients; ccw; ccw = ccw->next)
46605b261ecSmrg    {
46705b261ecSmrg	int ret = compUnredirectWindow (clients[CLIENT_ID(ccw->id)],
46805b261ecSmrg					pWin, ccw->update);
46905b261ecSmrg	if (ret != Success)
47005b261ecSmrg	    return ret;
47105b261ecSmrg    }
47205b261ecSmrg    return Success;
47305b261ecSmrg}
47405b261ecSmrg
47505b261ecSmrgstatic PixmapPtr
47605b261ecSmrgcompNewPixmap (WindowPtr pWin, int x, int y, int w, int h)
47705b261ecSmrg{
47805b261ecSmrg    ScreenPtr	    pScreen = pWin->drawable.pScreen;
47905b261ecSmrg    WindowPtr	    pParent = pWin->parent;
48005b261ecSmrg    PixmapPtr	    pPixmap;
48105b261ecSmrg
4824642e01fSmrg    pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth,
4834642e01fSmrg					CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
48405b261ecSmrg
48505b261ecSmrg    if (!pPixmap)
48605b261ecSmrg	return 0;
48705b261ecSmrg
48805b261ecSmrg    pPixmap->screen_x = x;
48905b261ecSmrg    pPixmap->screen_y = y;
49005b261ecSmrg
49105b261ecSmrg    if (pParent->drawable.depth == pWin->drawable.depth)
49205b261ecSmrg    {
49305b261ecSmrg	GCPtr	pGC = GetScratchGC (pWin->drawable.depth, pScreen);
49405b261ecSmrg
49505b261ecSmrg	/*
49605b261ecSmrg	 * Copy bits from the parent into the new pixmap so that it will
49705b261ecSmrg	 * have "reasonable" contents in case for background None areas.
49805b261ecSmrg	 */
49905b261ecSmrg	if (pGC)
50005b261ecSmrg	{
5016747b715Smrg	    ChangeGCVal val;
5026747b715Smrg	    val.val = IncludeInferiors;
50305b261ecSmrg
50405b261ecSmrg	    ValidateGC(&pPixmap->drawable, pGC);
5056747b715Smrg	    ChangeGC (serverClient, pGC, GCSubwindowMode, &val);
50605b261ecSmrg	    (*pGC->ops->CopyArea) (&pParent->drawable,
50705b261ecSmrg				   &pPixmap->drawable,
50805b261ecSmrg				   pGC,
50905b261ecSmrg				   x - pParent->drawable.x,
51005b261ecSmrg				   y - pParent->drawable.y,
51105b261ecSmrg				   w, h, 0, 0);
51205b261ecSmrg	    FreeScratchGC (pGC);
51305b261ecSmrg	}
51405b261ecSmrg    }
51505b261ecSmrg    else
51605b261ecSmrg    {
51705b261ecSmrg	PictFormatPtr	pSrcFormat = compWindowFormat (pParent);
51805b261ecSmrg	PictFormatPtr	pDstFormat = compWindowFormat (pWin);
51905b261ecSmrg	XID		inferiors = IncludeInferiors;
52005b261ecSmrg	int		error;
52105b261ecSmrg
52205b261ecSmrg	PicturePtr	pSrcPicture = CreatePicture (None,
52305b261ecSmrg						     &pParent->drawable,
52405b261ecSmrg						     pSrcFormat,
52505b261ecSmrg						     CPSubwindowMode,
52605b261ecSmrg						     &inferiors,
52705b261ecSmrg						     serverClient, &error);
52805b261ecSmrg
52905b261ecSmrg	PicturePtr	pDstPicture = CreatePicture (None,
53005b261ecSmrg						     &pPixmap->drawable,
53105b261ecSmrg						     pDstFormat,
53205b261ecSmrg						     0, 0,
53305b261ecSmrg						     serverClient, &error);
53405b261ecSmrg
53505b261ecSmrg	if (pSrcPicture && pDstPicture)
53605b261ecSmrg	{
53705b261ecSmrg	    CompositePicture (PictOpSrc,
53805b261ecSmrg			      pSrcPicture,
53905b261ecSmrg			      NULL,
54005b261ecSmrg			      pDstPicture,
54105b261ecSmrg			      x - pParent->drawable.x,
54205b261ecSmrg			      y - pParent->drawable.y,
54305b261ecSmrg			      0, 0, 0, 0, w, h);
54405b261ecSmrg	}
54505b261ecSmrg	if (pSrcPicture)
54605b261ecSmrg	    FreePicture (pSrcPicture, 0);
54705b261ecSmrg	if (pDstPicture)
54805b261ecSmrg	    FreePicture (pDstPicture, 0);
54905b261ecSmrg    }
55005b261ecSmrg    return pPixmap;
55105b261ecSmrg}
55205b261ecSmrg
55305b261ecSmrgBool
55405b261ecSmrgcompAllocPixmap (WindowPtr pWin)
55505b261ecSmrg{
55605b261ecSmrg    int		    bw = (int) pWin->borderWidth;
55705b261ecSmrg    int		    x = pWin->drawable.x - bw;
55805b261ecSmrg    int		    y = pWin->drawable.y - bw;
55905b261ecSmrg    int		    w = pWin->drawable.width + (bw << 1);
56005b261ecSmrg    int		    h = pWin->drawable.height + (bw << 1);
56105b261ecSmrg    PixmapPtr	    pPixmap = compNewPixmap (pWin, x, y, w, h);
56205b261ecSmrg    CompWindowPtr   cw = GetCompWindow (pWin);
56305b261ecSmrg
56405b261ecSmrg    if (!pPixmap)
56505b261ecSmrg	return FALSE;
56605b261ecSmrg    if (cw->update == CompositeRedirectAutomatic)
56705b261ecSmrg	pWin->redirectDraw = RedirectDrawAutomatic;
56805b261ecSmrg    else
56905b261ecSmrg	pWin->redirectDraw = RedirectDrawManual;
57005b261ecSmrg
57105b261ecSmrg    compSetPixmap (pWin, pPixmap);
57205b261ecSmrg    cw->oldx = COMP_ORIGIN_INVALID;
57305b261ecSmrg    cw->oldy = COMP_ORIGIN_INVALID;
57405b261ecSmrg    cw->damageRegistered = FALSE;
57505b261ecSmrg    if (cw->update == CompositeRedirectAutomatic)
57605b261ecSmrg    {
57705b261ecSmrg	DamageRegister (&pWin->drawable, cw->damage);
57805b261ecSmrg	cw->damageRegistered = TRUE;
57905b261ecSmrg    }
58005b261ecSmrg    return TRUE;
58105b261ecSmrg}
58205b261ecSmrg
58305b261ecSmrgvoid
58405b261ecSmrgcompFreePixmap (WindowPtr pWin)
58505b261ecSmrg{
58605b261ecSmrg    ScreenPtr	    pScreen = pWin->drawable.pScreen;
58705b261ecSmrg    PixmapPtr	    pRedirectPixmap, pParentPixmap;
58805b261ecSmrg    CompWindowPtr   cw = GetCompWindow (pWin);
58905b261ecSmrg
59005b261ecSmrg    if (cw->damageRegistered)
59105b261ecSmrg    {
59205b261ecSmrg	DamageUnregister (&pWin->drawable, cw->damage);
59305b261ecSmrg	cw->damageRegistered = FALSE;
59405b261ecSmrg	DamageEmpty (cw->damage);
59505b261ecSmrg    }
59605b261ecSmrg    /*
59705b261ecSmrg     * Move the parent-constrained border clip region back into
59805b261ecSmrg     * the window so that ValidateTree will handle the unmap
59905b261ecSmrg     * case correctly.  Unmap adds the window borderClip to the
60005b261ecSmrg     * parent exposed area; regions beyond the parent cause crashes
60105b261ecSmrg     */
6026747b715Smrg    RegionCopy(&pWin->borderClip, &cw->borderClip);
60305b261ecSmrg    pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin);
60405b261ecSmrg    pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent);
60505b261ecSmrg    pWin->redirectDraw = RedirectDrawNone;
60605b261ecSmrg    compSetPixmap (pWin, pParentPixmap);
60705b261ecSmrg    (*pScreen->DestroyPixmap) (pRedirectPixmap);
60805b261ecSmrg}
60905b261ecSmrg
61005b261ecSmrg/*
61105b261ecSmrg * Make sure the pixmap is the right size and offset.  Allocate a new
61205b261ecSmrg * pixmap to change size, adjust origin to change offset, leaving the
61305b261ecSmrg * old pixmap in cw->pOldPixmap so bits can be recovered
61405b261ecSmrg */
61505b261ecSmrgBool
61605b261ecSmrgcompReallocPixmap (WindowPtr pWin, int draw_x, int draw_y,
61705b261ecSmrg		   unsigned int w, unsigned int h, int bw)
61805b261ecSmrg{
61905b261ecSmrg    ScreenPtr	    pScreen = pWin->drawable.pScreen;
62005b261ecSmrg    PixmapPtr	    pOld = (*pScreen->GetWindowPixmap) (pWin);
62105b261ecSmrg    PixmapPtr	    pNew;
62205b261ecSmrg    CompWindowPtr   cw = GetCompWindow (pWin);
62305b261ecSmrg    int		    pix_x, pix_y;
62405b261ecSmrg    int		    pix_w, pix_h;
62505b261ecSmrg
62605b261ecSmrg    assert (cw && pWin->redirectDraw != RedirectDrawNone);
62705b261ecSmrg    cw->oldx = pOld->screen_x;
62805b261ecSmrg    cw->oldy = pOld->screen_y;
62905b261ecSmrg    pix_x = draw_x - bw;
63005b261ecSmrg    pix_y = draw_y - bw;
63105b261ecSmrg    pix_w = w + (bw << 1);
63205b261ecSmrg    pix_h = h + (bw << 1);
63305b261ecSmrg    if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height)
63405b261ecSmrg    {
63505b261ecSmrg	pNew = compNewPixmap (pWin, pix_x, pix_y, pix_w, pix_h);
63605b261ecSmrg	if (!pNew)
63705b261ecSmrg	    return FALSE;
63805b261ecSmrg	cw->pOldPixmap = pOld;
63905b261ecSmrg	compSetPixmap (pWin, pNew);
64005b261ecSmrg    }
64105b261ecSmrg    else
64205b261ecSmrg    {
64305b261ecSmrg	pNew = pOld;
64405b261ecSmrg	cw->pOldPixmap = 0;
64505b261ecSmrg    }
64605b261ecSmrg    pNew->screen_x = pix_x;
64705b261ecSmrg    pNew->screen_y = pix_y;
64805b261ecSmrg    return TRUE;
64905b261ecSmrg}
650