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