compalloc.c revision 9ace9065
105b261ecSmrg/*
29ace9065Smrg * Copyright (c) 2006, Oracle and/or its affiliates. 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
509ace9065Smrgstatic void
519ace9065SmrgcompScreenUpdate (ScreenPtr pScreen)
529ace9065Smrg{
539ace9065Smrg    compCheckTree (pScreen);
549ace9065Smrg    compPaintChildrenToWindow (pScreen->root);
559ace9065Smrg}
569ace9065Smrg
579ace9065Smrgstatic void
589ace9065SmrgcompBlockHandler (int	    i,
599ace9065Smrg		  pointer   blockData,
609ace9065Smrg		  pointer   pTimeout,
619ace9065Smrg		  pointer   pReadmask)
629ace9065Smrg{
639ace9065Smrg    ScreenPtr	    pScreen = screenInfo.screens[i];
649ace9065Smrg    CompScreenPtr   cs = GetCompScreen (pScreen);
659ace9065Smrg
669ace9065Smrg    pScreen->BlockHandler = cs->BlockHandler;
679ace9065Smrg    compScreenUpdate (pScreen);
689ace9065Smrg    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
699ace9065Smrg
709ace9065Smrg    /* Next damage will restore the block handler */
719ace9065Smrg    cs->BlockHandler = NULL;
729ace9065Smrg}
739ace9065Smrg
7405b261ecSmrgstatic void
7505b261ecSmrgcompReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
7605b261ecSmrg{
7705b261ecSmrg    WindowPtr	    pWin = (WindowPtr) closure;
7805b261ecSmrg    ScreenPtr	    pScreen = pWin->drawable.pScreen;
7905b261ecSmrg    CompScreenPtr   cs = GetCompScreen (pScreen);
8005b261ecSmrg    CompWindowPtr   cw = GetCompWindow (pWin);
8105b261ecSmrg
829ace9065Smrg    if (!cs->BlockHandler) {
839ace9065Smrg        cs->BlockHandler = pScreen->BlockHandler;
849ace9065Smrg        pScreen->BlockHandler = compBlockHandler;
859ace9065Smrg    }
8605b261ecSmrg    cw->damaged = TRUE;
879ace9065Smrg
889ace9065Smrg    /* Mark the ancestors */
899ace9065Smrg    pWin = pWin->parent;
909ace9065Smrg    while (pWin) {
919ace9065Smrg	if (pWin->damagedDescendants)
929ace9065Smrg	    break;
939ace9065Smrg	pWin->damagedDescendants = TRUE;
949ace9065Smrg	pWin = pWin->parent;
959ace9065Smrg    }
9605b261ecSmrg}
9705b261ecSmrg
9805b261ecSmrgstatic void
9905b261ecSmrgcompDestroyDamage (DamagePtr pDamage, void *closure)
10005b261ecSmrg{
10105b261ecSmrg    WindowPtr	    pWin = (WindowPtr) closure;
10205b261ecSmrg    CompWindowPtr   cw = GetCompWindow (pWin);
10305b261ecSmrg
10405b261ecSmrg    cw->damage = 0;
10505b261ecSmrg}
10605b261ecSmrg
10705b261ecSmrg/*
10805b261ecSmrg * Redirect one window for one client
10905b261ecSmrg */
11005b261ecSmrgint
11105b261ecSmrgcompRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
11205b261ecSmrg{
11305b261ecSmrg    CompWindowPtr	cw = GetCompWindow (pWin);
11405b261ecSmrg    CompClientWindowPtr	ccw;
11505b261ecSmrg    Bool		wasMapped = pWin->mapped;
11605b261ecSmrg    CompScreenPtr       cs = GetCompScreen(pWin->drawable.pScreen);
11705b261ecSmrg
11805b261ecSmrg    if (pWin == cs->pOverlayWin) {
11905b261ecSmrg	return Success;
12005b261ecSmrg    }
12105b261ecSmrg
1224642e01fSmrg    if (!pWin->parent)
1234642e01fSmrg	return BadMatch;
1244642e01fSmrg
12505b261ecSmrg    /*
12605b261ecSmrg     * Only one Manual update is allowed
12705b261ecSmrg     */
12805b261ecSmrg    if (cw && update == CompositeRedirectManual)
12905b261ecSmrg	for (ccw = cw->clients; ccw; ccw = ccw->next)
13005b261ecSmrg	    if (ccw->update == CompositeRedirectManual)
13105b261ecSmrg		return BadAccess;
13205b261ecSmrg
13305b261ecSmrg    /*
13405b261ecSmrg     * Allocate per-client per-window structure
13505b261ecSmrg     * The client *could* allocate multiple, but while supported,
13605b261ecSmrg     * it is not expected to be common
13705b261ecSmrg     */
1386747b715Smrg    ccw = malloc(sizeof (CompClientWindowRec));
13905b261ecSmrg    if (!ccw)
14005b261ecSmrg	return BadAlloc;
14105b261ecSmrg    ccw->id = FakeClientID (pClient->index);
14205b261ecSmrg    ccw->update = update;
14305b261ecSmrg    /*
14405b261ecSmrg     * Now make sure there's a per-window structure to hang this from
14505b261ecSmrg     */
14605b261ecSmrg    if (!cw)
14705b261ecSmrg    {
1486747b715Smrg	cw = malloc(sizeof (CompWindowRec));
14905b261ecSmrg	if (!cw)
15005b261ecSmrg	{
1516747b715Smrg	    free(ccw);
15205b261ecSmrg	    return BadAlloc;
15305b261ecSmrg	}
15405b261ecSmrg	cw->damage = DamageCreate (compReportDamage,
15505b261ecSmrg				   compDestroyDamage,
15605b261ecSmrg				   DamageReportNonEmpty,
15705b261ecSmrg				   FALSE,
15805b261ecSmrg				   pWin->drawable.pScreen,
15905b261ecSmrg				   pWin);
16005b261ecSmrg	if (!cw->damage)
16105b261ecSmrg	{
1626747b715Smrg	    free(ccw);
1636747b715Smrg	    free(cw);
16405b261ecSmrg	    return BadAlloc;
16505b261ecSmrg	}
16605b261ecSmrg	if (wasMapped)
16705b261ecSmrg	{
16805b261ecSmrg	    DisableMapUnmapEvents (pWin);
16905b261ecSmrg	    UnmapWindow (pWin, FALSE);
17005b261ecSmrg	    EnableMapUnmapEvents (pWin);
17105b261ecSmrg	}
17205b261ecSmrg
1736747b715Smrg	RegionNull(&cw->borderClip);
1746747b715Smrg	cw->borderClipX = 0;
1756747b715Smrg	cw->borderClipY = 0;
17605b261ecSmrg	cw->update = CompositeRedirectAutomatic;
17705b261ecSmrg	cw->clients = 0;
17805b261ecSmrg	cw->oldx = COMP_ORIGIN_INVALID;
17905b261ecSmrg	cw->oldy = COMP_ORIGIN_INVALID;
18005b261ecSmrg	cw->damageRegistered = FALSE;
18105b261ecSmrg	cw->damaged = FALSE;
1826747b715Smrg	cw->pOldPixmap = NullPixmap;
1834642e01fSmrg	dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw);
18405b261ecSmrg    }
18505b261ecSmrg    ccw->next = cw->clients;
18605b261ecSmrg    cw->clients = ccw;
18705b261ecSmrg    if (!AddResource (ccw->id, CompositeClientWindowType, pWin))
18805b261ecSmrg	return BadAlloc;
18905b261ecSmrg    if (ccw->update == CompositeRedirectManual)
19005b261ecSmrg    {
1914642e01fSmrg	/* If the window was CompositeRedirectAutomatic, then
1924642e01fSmrg	 * unmap the window so that the parent clip list will
1934642e01fSmrg	 * be correctly recomputed.
1944642e01fSmrg	 */
1954642e01fSmrg	if (pWin->mapped)
1964642e01fSmrg	{
1974642e01fSmrg	    DisableMapUnmapEvents (pWin);
1984642e01fSmrg	    UnmapWindow (pWin, FALSE);
1994642e01fSmrg	    EnableMapUnmapEvents (pWin);
2004642e01fSmrg	}
20105b261ecSmrg	if (cw->damageRegistered)
20205b261ecSmrg	{
20305b261ecSmrg	    DamageUnregister (&pWin->drawable, cw->damage);
20405b261ecSmrg	    cw->damageRegistered = FALSE;
20505b261ecSmrg	}
20605b261ecSmrg	cw->update = CompositeRedirectManual;
20705b261ecSmrg    }
20805b261ecSmrg
20905b261ecSmrg    if (!compCheckRedirect (pWin))
21005b261ecSmrg    {
21105b261ecSmrg	FreeResource (ccw->id, RT_NONE);
21205b261ecSmrg	return BadAlloc;
21305b261ecSmrg    }
21405b261ecSmrg    if (wasMapped && !pWin->mapped)
21505b261ecSmrg    {
21605b261ecSmrg	Bool	overrideRedirect = pWin->overrideRedirect;
21705b261ecSmrg	pWin->overrideRedirect = TRUE;
21805b261ecSmrg	DisableMapUnmapEvents (pWin);
21905b261ecSmrg	MapWindow (pWin, pClient);
22005b261ecSmrg	EnableMapUnmapEvents (pWin);
22105b261ecSmrg	pWin->overrideRedirect = overrideRedirect;
22205b261ecSmrg    }
22305b261ecSmrg
22405b261ecSmrg    return Success;
22505b261ecSmrg}
22605b261ecSmrg
22705b261ecSmrg/*
22805b261ecSmrg * Free one of the per-client per-window resources, clearing
22905b261ecSmrg * redirect and the per-window pointer as appropriate
23005b261ecSmrg */
23105b261ecSmrgvoid
23205b261ecSmrgcompFreeClientWindow (WindowPtr pWin, XID id)
23305b261ecSmrg{
23405b261ecSmrg    CompWindowPtr	cw = GetCompWindow (pWin);
23505b261ecSmrg    CompClientWindowPtr	ccw, *prev;
23605b261ecSmrg    Bool		wasMapped = pWin->mapped;
23705b261ecSmrg
23805b261ecSmrg    if (!cw)
23905b261ecSmrg	return;
24005b261ecSmrg    for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next)
24105b261ecSmrg    {
24205b261ecSmrg	if (ccw->id == id)
24305b261ecSmrg	{
24405b261ecSmrg	    *prev = ccw->next;
24505b261ecSmrg	    if (ccw->update == CompositeRedirectManual)
24605b261ecSmrg		cw->update = CompositeRedirectAutomatic;
2476747b715Smrg	    free(ccw);
24805b261ecSmrg	    break;
24905b261ecSmrg	}
25005b261ecSmrg    }
25105b261ecSmrg    if (!cw->clients)
25205b261ecSmrg    {
25305b261ecSmrg	if (wasMapped)
25405b261ecSmrg	{
25505b261ecSmrg	    DisableMapUnmapEvents (pWin);
25605b261ecSmrg	    UnmapWindow (pWin, FALSE);
25705b261ecSmrg	    EnableMapUnmapEvents (pWin);
25805b261ecSmrg	}
25905b261ecSmrg
26005b261ecSmrg	if (pWin->redirectDraw != RedirectDrawNone)
26105b261ecSmrg	    compFreePixmap (pWin);
26205b261ecSmrg
26305b261ecSmrg	if (cw->damage)
26405b261ecSmrg	    DamageDestroy (cw->damage);
26505b261ecSmrg
2666747b715Smrg	RegionUninit(&cw->borderClip);
26705b261ecSmrg
2684642e01fSmrg	dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL);
2696747b715Smrg	free(cw);
27005b261ecSmrg    }
27105b261ecSmrg    else if (cw->update == CompositeRedirectAutomatic &&
27205b261ecSmrg	     !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone)
27305b261ecSmrg    {
27405b261ecSmrg	DamageRegister (&pWin->drawable, cw->damage);
27505b261ecSmrg	cw->damageRegistered = TRUE;
27605b261ecSmrg	pWin->redirectDraw = RedirectDrawAutomatic;
2778223e2f2Smrg	DamageDamageRegion(&pWin->drawable, &pWin->borderSize);
27805b261ecSmrg    }
27905b261ecSmrg    if (wasMapped && !pWin->mapped)
28005b261ecSmrg    {
28105b261ecSmrg	Bool	overrideRedirect = pWin->overrideRedirect;
28205b261ecSmrg	pWin->overrideRedirect = TRUE;
28305b261ecSmrg	DisableMapUnmapEvents (pWin);
28405b261ecSmrg	MapWindow (pWin, clients[CLIENT_ID(id)]);
28505b261ecSmrg	EnableMapUnmapEvents (pWin);
28605b261ecSmrg	pWin->overrideRedirect = overrideRedirect;
28705b261ecSmrg    }
28805b261ecSmrg}
28905b261ecSmrg
29005b261ecSmrg/*
29105b261ecSmrg * This is easy, just free the appropriate resource.
29205b261ecSmrg */
29305b261ecSmrg
29405b261ecSmrgint
29505b261ecSmrgcompUnredirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
29605b261ecSmrg{
29705b261ecSmrg    CompWindowPtr	cw = GetCompWindow (pWin);
29805b261ecSmrg    CompClientWindowPtr	ccw;
29905b261ecSmrg
30005b261ecSmrg    if (!cw)
30105b261ecSmrg	return BadValue;
30205b261ecSmrg
30305b261ecSmrg    for (ccw = cw->clients; ccw; ccw = ccw->next)
30405b261ecSmrg	if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index)
30505b261ecSmrg	{
30605b261ecSmrg	    FreeResource (ccw->id, RT_NONE);
30705b261ecSmrg	    return Success;
30805b261ecSmrg	}
30905b261ecSmrg    return BadValue;
31005b261ecSmrg}
31105b261ecSmrg
31205b261ecSmrg/*
31305b261ecSmrg * Redirect all subwindows for one client
31405b261ecSmrg */
31505b261ecSmrg
31605b261ecSmrgint
31705b261ecSmrgcompRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update)
31805b261ecSmrg{
31905b261ecSmrg    CompSubwindowsPtr	csw = GetCompSubwindows (pWin);
32005b261ecSmrg    CompClientWindowPtr	ccw;
32105b261ecSmrg    WindowPtr		pChild;
32205b261ecSmrg
32305b261ecSmrg    /*
32405b261ecSmrg     * Only one Manual update is allowed
32505b261ecSmrg     */
32605b261ecSmrg    if (csw && update == CompositeRedirectManual)
32705b261ecSmrg	for (ccw = csw->clients; ccw; ccw = ccw->next)
32805b261ecSmrg	    if (ccw->update == CompositeRedirectManual)
32905b261ecSmrg		return BadAccess;
33005b261ecSmrg    /*
33105b261ecSmrg     * Allocate per-client per-window structure
33205b261ecSmrg     * The client *could* allocate multiple, but while supported,
33305b261ecSmrg     * it is not expected to be common
33405b261ecSmrg     */
3356747b715Smrg    ccw = malloc(sizeof (CompClientWindowRec));
33605b261ecSmrg    if (!ccw)
33705b261ecSmrg	return BadAlloc;
33805b261ecSmrg    ccw->id = FakeClientID (pClient->index);
33905b261ecSmrg    ccw->update = update;
34005b261ecSmrg    /*
34105b261ecSmrg     * Now make sure there's a per-window structure to hang this from
34205b261ecSmrg     */
34305b261ecSmrg    if (!csw)
34405b261ecSmrg    {
3456747b715Smrg	csw = malloc(sizeof (CompSubwindowsRec));
34605b261ecSmrg	if (!csw)
34705b261ecSmrg	{
3486747b715Smrg	    free(ccw);
34905b261ecSmrg	    return BadAlloc;
35005b261ecSmrg	}
35105b261ecSmrg	csw->update = CompositeRedirectAutomatic;
35205b261ecSmrg	csw->clients = 0;
3534642e01fSmrg	dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw);
35405b261ecSmrg    }
35505b261ecSmrg    /*
35605b261ecSmrg     * Redirect all existing windows
35705b261ecSmrg     */
35805b261ecSmrg    for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
35905b261ecSmrg    {
36005b261ecSmrg	int ret = compRedirectWindow (pClient, pChild, update);
36105b261ecSmrg	if (ret != Success)
36205b261ecSmrg	{
36305b261ecSmrg	    for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib)
36405b261ecSmrg		(void) compUnredirectWindow (pClient, pChild, update);
36505b261ecSmrg	    if (!csw->clients)
36605b261ecSmrg	    {
3676747b715Smrg		free(csw);
3684642e01fSmrg		dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0);
36905b261ecSmrg	    }
3706747b715Smrg	    free(ccw);
37105b261ecSmrg	    return ret;
37205b261ecSmrg	}
37305b261ecSmrg    }
37405b261ecSmrg    /*
37505b261ecSmrg     * Hook into subwindows list
37605b261ecSmrg     */
37705b261ecSmrg    ccw->next = csw->clients;
37805b261ecSmrg    csw->clients = ccw;
37905b261ecSmrg    if (!AddResource (ccw->id, CompositeClientSubwindowsType, pWin))
38005b261ecSmrg	return BadAlloc;
38105b261ecSmrg    if (ccw->update == CompositeRedirectManual)
38205b261ecSmrg    {
38305b261ecSmrg	csw->update = CompositeRedirectManual;
38405b261ecSmrg	/*
38505b261ecSmrg	 * tell damage extension that damage events for this client are
38605b261ecSmrg	 * critical output
38705b261ecSmrg	 */
38805b261ecSmrg	DamageExtSetCritical (pClient, TRUE);
38905b261ecSmrg    }
39005b261ecSmrg    return Success;
39105b261ecSmrg}
39205b261ecSmrg
39305b261ecSmrg/*
39405b261ecSmrg * Free one of the per-client per-subwindows resources,
39505b261ecSmrg * which frees one redirect per subwindow
39605b261ecSmrg */
39705b261ecSmrgvoid
39805b261ecSmrgcompFreeClientSubwindows (WindowPtr pWin, XID id)
39905b261ecSmrg{
40005b261ecSmrg    CompSubwindowsPtr	csw = GetCompSubwindows (pWin);
40105b261ecSmrg    CompClientWindowPtr	ccw, *prev;
40205b261ecSmrg    WindowPtr		pChild;
40305b261ecSmrg
40405b261ecSmrg    if (!csw)
40505b261ecSmrg	return;
40605b261ecSmrg    for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next)
40705b261ecSmrg    {
40805b261ecSmrg	if (ccw->id == id)
40905b261ecSmrg	{
41005b261ecSmrg	    ClientPtr	pClient = clients[CLIENT_ID(id)];
41105b261ecSmrg
41205b261ecSmrg	    *prev = ccw->next;
41305b261ecSmrg	    if (ccw->update == CompositeRedirectManual)
41405b261ecSmrg	    {
41505b261ecSmrg		/*
41605b261ecSmrg		 * tell damage extension that damage events for this client are
41705b261ecSmrg		 * critical output
41805b261ecSmrg		 */
41905b261ecSmrg		DamageExtSetCritical (pClient, FALSE);
42005b261ecSmrg		csw->update = CompositeRedirectAutomatic;
42105b261ecSmrg		if (pWin->mapped)
42205b261ecSmrg		    (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, TRUE);
42305b261ecSmrg	    }
42405b261ecSmrg
42505b261ecSmrg	    /*
42605b261ecSmrg	     * Unredirect all existing subwindows
42705b261ecSmrg	     */
42805b261ecSmrg	    for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
42905b261ecSmrg		(void) compUnredirectWindow (pClient, pChild, ccw->update);
43005b261ecSmrg
4316747b715Smrg	    free(ccw);
43205b261ecSmrg	    break;
43305b261ecSmrg	}
43405b261ecSmrg    }
43505b261ecSmrg
43605b261ecSmrg    /*
43705b261ecSmrg     * Check if all of the per-client records are gone
43805b261ecSmrg     */
43905b261ecSmrg    if (!csw->clients)
44005b261ecSmrg    {
4414642e01fSmrg	dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL);
4426747b715Smrg	free(csw);
44305b261ecSmrg    }
44405b261ecSmrg}
44505b261ecSmrg
44605b261ecSmrg/*
44705b261ecSmrg * This is easy, just free the appropriate resource.
44805b261ecSmrg */
44905b261ecSmrg
45005b261ecSmrgint
45105b261ecSmrgcompUnredirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update)
45205b261ecSmrg{
45305b261ecSmrg    CompSubwindowsPtr	csw = GetCompSubwindows (pWin);
45405b261ecSmrg    CompClientWindowPtr	ccw;
45505b261ecSmrg
45605b261ecSmrg    if (!csw)
45705b261ecSmrg	return BadValue;
45805b261ecSmrg    for (ccw = csw->clients; ccw; ccw = ccw->next)
45905b261ecSmrg	if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index)
46005b261ecSmrg	{
46105b261ecSmrg	    FreeResource (ccw->id, RT_NONE);
46205b261ecSmrg	    return Success;
46305b261ecSmrg	}
46405b261ecSmrg    return BadValue;
46505b261ecSmrg}
46605b261ecSmrg
46705b261ecSmrg/*
46805b261ecSmrg * Add redirection information for one subwindow (during reparent)
46905b261ecSmrg */
47005b261ecSmrg
47105b261ecSmrgint
47205b261ecSmrgcompRedirectOneSubwindow (WindowPtr pParent, WindowPtr pWin)
47305b261ecSmrg{
47405b261ecSmrg    CompSubwindowsPtr	csw = GetCompSubwindows (pParent);
47505b261ecSmrg    CompClientWindowPtr	ccw;
47605b261ecSmrg
47705b261ecSmrg    if (!csw)
47805b261ecSmrg	return Success;
47905b261ecSmrg    for (ccw = csw->clients; ccw; ccw = ccw->next)
48005b261ecSmrg    {
48105b261ecSmrg	int ret = compRedirectWindow (clients[CLIENT_ID(ccw->id)],
48205b261ecSmrg				      pWin, ccw->update);
48305b261ecSmrg	if (ret != Success)
48405b261ecSmrg	    return ret;
48505b261ecSmrg    }
48605b261ecSmrg    return Success;
48705b261ecSmrg}
48805b261ecSmrg
48905b261ecSmrg/*
49005b261ecSmrg * Remove redirection information for one subwindow (during reparent)
49105b261ecSmrg */
49205b261ecSmrg
49305b261ecSmrgint
49405b261ecSmrgcompUnredirectOneSubwindow (WindowPtr pParent, WindowPtr pWin)
49505b261ecSmrg{
49605b261ecSmrg    CompSubwindowsPtr	csw = GetCompSubwindows (pParent);
49705b261ecSmrg    CompClientWindowPtr	ccw;
49805b261ecSmrg
49905b261ecSmrg    if (!csw)
50005b261ecSmrg	return Success;
50105b261ecSmrg    for (ccw = csw->clients; ccw; ccw = ccw->next)
50205b261ecSmrg    {
50305b261ecSmrg	int ret = compUnredirectWindow (clients[CLIENT_ID(ccw->id)],
50405b261ecSmrg					pWin, ccw->update);
50505b261ecSmrg	if (ret != Success)
50605b261ecSmrg	    return ret;
50705b261ecSmrg    }
50805b261ecSmrg    return Success;
50905b261ecSmrg}
51005b261ecSmrg
5119ace9065Smrgstatic int
5129ace9065SmrgbgNoneVisitWindow(WindowPtr pWin, void *null)
5139ace9065Smrg{
5149ace9065Smrg    if (pWin->backgroundState != BackgroundPixmap)
5159ace9065Smrg	return WT_WALKCHILDREN;
5169ace9065Smrg    if (pWin->background.pixmap != None)
5179ace9065Smrg	return WT_WALKCHILDREN;
5189ace9065Smrg
5199ace9065Smrg    return WT_STOPWALKING;
5209ace9065Smrg}
5219ace9065Smrg
52205b261ecSmrgstatic PixmapPtr
5239ace9065SmrgcompNewPixmap (WindowPtr pWin, int x, int y, int w, int h, Bool map)
52405b261ecSmrg{
52505b261ecSmrg    ScreenPtr	    pScreen = pWin->drawable.pScreen;
52605b261ecSmrg    WindowPtr	    pParent = pWin->parent;
52705b261ecSmrg    PixmapPtr	    pPixmap;
52805b261ecSmrg
5294642e01fSmrg    pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth,
5304642e01fSmrg					CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
53105b261ecSmrg
53205b261ecSmrg    if (!pPixmap)
53305b261ecSmrg	return 0;
53405b261ecSmrg
53505b261ecSmrg    pPixmap->screen_x = x;
53605b261ecSmrg    pPixmap->screen_y = y;
5379ace9065Smrg
5389ace9065Smrg    /* resize allocations will update later in compCopyWindow, not here */
5399ace9065Smrg    if (!map)
5409ace9065Smrg	return pPixmap;
5419ace9065Smrg
5429ace9065Smrg    /*
5439ace9065Smrg     * If there's no bg=None in the tree, we're done.
5449ace9065Smrg     *
5459ace9065Smrg     * We could optimize this more by collection the regions of all the
5469ace9065Smrg     * bg=None subwindows and feeding that in as the clip for the
5479ace9065Smrg     * CopyArea below, but since window trees are shallow these days it
5489ace9065Smrg     * might not be worth the effort.
5499ace9065Smrg     */
5509ace9065Smrg    if (TraverseTree(pWin, bgNoneVisitWindow, NULL) == WT_NOMATCH)
5519ace9065Smrg	return pPixmap;
5529ace9065Smrg
5539ace9065Smrg    /*
5549ace9065Smrg     * Copy bits from the parent into the new pixmap so that it will
5559ace9065Smrg     * have "reasonable" contents in case for background None areas.
5569ace9065Smrg     */
55705b261ecSmrg    if (pParent->drawable.depth == pWin->drawable.depth)
55805b261ecSmrg    {
55905b261ecSmrg	GCPtr	pGC = GetScratchGC (pWin->drawable.depth, pScreen);
56005b261ecSmrg
56105b261ecSmrg	if (pGC)
56205b261ecSmrg	{
5636747b715Smrg	    ChangeGCVal val;
5646747b715Smrg	    val.val = IncludeInferiors;
56505b261ecSmrg
56605b261ecSmrg	    ValidateGC(&pPixmap->drawable, pGC);
5676747b715Smrg	    ChangeGC (serverClient, pGC, GCSubwindowMode, &val);
56805b261ecSmrg	    (*pGC->ops->CopyArea) (&pParent->drawable,
56905b261ecSmrg				   &pPixmap->drawable,
57005b261ecSmrg				   pGC,
57105b261ecSmrg				   x - pParent->drawable.x,
57205b261ecSmrg				   y - pParent->drawable.y,
57305b261ecSmrg				   w, h, 0, 0);
57405b261ecSmrg	    FreeScratchGC (pGC);
57505b261ecSmrg	}
57605b261ecSmrg    }
57705b261ecSmrg    else
57805b261ecSmrg    {
57905b261ecSmrg	PictFormatPtr	pSrcFormat = compWindowFormat (pParent);
58005b261ecSmrg	PictFormatPtr	pDstFormat = compWindowFormat (pWin);
58105b261ecSmrg	XID		inferiors = IncludeInferiors;
58205b261ecSmrg	int		error;
58305b261ecSmrg
58405b261ecSmrg	PicturePtr	pSrcPicture = CreatePicture (None,
58505b261ecSmrg						     &pParent->drawable,
58605b261ecSmrg						     pSrcFormat,
58705b261ecSmrg						     CPSubwindowMode,
58805b261ecSmrg						     &inferiors,
58905b261ecSmrg						     serverClient, &error);
59005b261ecSmrg
59105b261ecSmrg	PicturePtr	pDstPicture = CreatePicture (None,
59205b261ecSmrg						     &pPixmap->drawable,
59305b261ecSmrg						     pDstFormat,
59405b261ecSmrg						     0, 0,
59505b261ecSmrg						     serverClient, &error);
59605b261ecSmrg
59705b261ecSmrg	if (pSrcPicture && pDstPicture)
59805b261ecSmrg	{
59905b261ecSmrg	    CompositePicture (PictOpSrc,
60005b261ecSmrg			      pSrcPicture,
60105b261ecSmrg			      NULL,
60205b261ecSmrg			      pDstPicture,
60305b261ecSmrg			      x - pParent->drawable.x,
60405b261ecSmrg			      y - pParent->drawable.y,
60505b261ecSmrg			      0, 0, 0, 0, w, h);
60605b261ecSmrg	}
60705b261ecSmrg	if (pSrcPicture)
60805b261ecSmrg	    FreePicture (pSrcPicture, 0);
60905b261ecSmrg	if (pDstPicture)
61005b261ecSmrg	    FreePicture (pDstPicture, 0);
61105b261ecSmrg    }
61205b261ecSmrg    return pPixmap;
61305b261ecSmrg}
61405b261ecSmrg
61505b261ecSmrgBool
61605b261ecSmrgcompAllocPixmap (WindowPtr pWin)
61705b261ecSmrg{
61805b261ecSmrg    int		    bw = (int) pWin->borderWidth;
61905b261ecSmrg    int		    x = pWin->drawable.x - bw;
62005b261ecSmrg    int		    y = pWin->drawable.y - bw;
62105b261ecSmrg    int		    w = pWin->drawable.width + (bw << 1);
62205b261ecSmrg    int		    h = pWin->drawable.height + (bw << 1);
6239ace9065Smrg    PixmapPtr	    pPixmap = compNewPixmap (pWin, x, y, w, h, TRUE);
62405b261ecSmrg    CompWindowPtr   cw = GetCompWindow (pWin);
62505b261ecSmrg
62605b261ecSmrg    if (!pPixmap)
62705b261ecSmrg	return FALSE;
62805b261ecSmrg    if (cw->update == CompositeRedirectAutomatic)
62905b261ecSmrg	pWin->redirectDraw = RedirectDrawAutomatic;
63005b261ecSmrg    else
63105b261ecSmrg	pWin->redirectDraw = RedirectDrawManual;
63205b261ecSmrg
63305b261ecSmrg    compSetPixmap (pWin, pPixmap);
63405b261ecSmrg    cw->oldx = COMP_ORIGIN_INVALID;
63505b261ecSmrg    cw->oldy = COMP_ORIGIN_INVALID;
63605b261ecSmrg    cw->damageRegistered = FALSE;
63705b261ecSmrg    if (cw->update == CompositeRedirectAutomatic)
63805b261ecSmrg    {
63905b261ecSmrg	DamageRegister (&pWin->drawable, cw->damage);
64005b261ecSmrg	cw->damageRegistered = TRUE;
64105b261ecSmrg    }
64205b261ecSmrg    return TRUE;
64305b261ecSmrg}
64405b261ecSmrg
64505b261ecSmrgvoid
64605b261ecSmrgcompFreePixmap (WindowPtr pWin)
64705b261ecSmrg{
64805b261ecSmrg    ScreenPtr	    pScreen = pWin->drawable.pScreen;
64905b261ecSmrg    PixmapPtr	    pRedirectPixmap, pParentPixmap;
65005b261ecSmrg    CompWindowPtr   cw = GetCompWindow (pWin);
65105b261ecSmrg
65205b261ecSmrg    if (cw->damageRegistered)
65305b261ecSmrg    {
65405b261ecSmrg	DamageUnregister (&pWin->drawable, cw->damage);
65505b261ecSmrg	cw->damageRegistered = FALSE;
65605b261ecSmrg	DamageEmpty (cw->damage);
65705b261ecSmrg    }
65805b261ecSmrg    /*
65905b261ecSmrg     * Move the parent-constrained border clip region back into
66005b261ecSmrg     * the window so that ValidateTree will handle the unmap
66105b261ecSmrg     * case correctly.  Unmap adds the window borderClip to the
66205b261ecSmrg     * parent exposed area; regions beyond the parent cause crashes
66305b261ecSmrg     */
6646747b715Smrg    RegionCopy(&pWin->borderClip, &cw->borderClip);
66505b261ecSmrg    pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin);
66605b261ecSmrg    pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent);
66705b261ecSmrg    pWin->redirectDraw = RedirectDrawNone;
66805b261ecSmrg    compSetPixmap (pWin, pParentPixmap);
66905b261ecSmrg    (*pScreen->DestroyPixmap) (pRedirectPixmap);
67005b261ecSmrg}
67105b261ecSmrg
67205b261ecSmrg/*
67305b261ecSmrg * Make sure the pixmap is the right size and offset.  Allocate a new
67405b261ecSmrg * pixmap to change size, adjust origin to change offset, leaving the
67505b261ecSmrg * old pixmap in cw->pOldPixmap so bits can be recovered
67605b261ecSmrg */
67705b261ecSmrgBool
67805b261ecSmrgcompReallocPixmap (WindowPtr pWin, int draw_x, int draw_y,
67905b261ecSmrg		   unsigned int w, unsigned int h, int bw)
68005b261ecSmrg{
68105b261ecSmrg    ScreenPtr	    pScreen = pWin->drawable.pScreen;
68205b261ecSmrg    PixmapPtr	    pOld = (*pScreen->GetWindowPixmap) (pWin);
68305b261ecSmrg    PixmapPtr	    pNew;
68405b261ecSmrg    CompWindowPtr   cw = GetCompWindow (pWin);
68505b261ecSmrg    int		    pix_x, pix_y;
68605b261ecSmrg    int		    pix_w, pix_h;
68705b261ecSmrg
68805b261ecSmrg    assert (cw && pWin->redirectDraw != RedirectDrawNone);
68905b261ecSmrg    cw->oldx = pOld->screen_x;
69005b261ecSmrg    cw->oldy = pOld->screen_y;
69105b261ecSmrg    pix_x = draw_x - bw;
69205b261ecSmrg    pix_y = draw_y - bw;
69305b261ecSmrg    pix_w = w + (bw << 1);
69405b261ecSmrg    pix_h = h + (bw << 1);
69505b261ecSmrg    if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height)
69605b261ecSmrg    {
6979ace9065Smrg	pNew = compNewPixmap (pWin, pix_x, pix_y, pix_w, pix_h, FALSE);
69805b261ecSmrg	if (!pNew)
69905b261ecSmrg	    return FALSE;
70005b261ecSmrg	cw->pOldPixmap = pOld;
70105b261ecSmrg	compSetPixmap (pWin, pNew);
70205b261ecSmrg    }
70305b261ecSmrg    else
70405b261ecSmrg    {
70505b261ecSmrg	pNew = pOld;
70605b261ecSmrg	cw->pOldPixmap = 0;
70705b261ecSmrg    }
70805b261ecSmrg    pNew->screen_x = pix_x;
70905b261ecSmrg    pNew->screen_y = pix_y;
71005b261ecSmrg    return TRUE;
71105b261ecSmrg}
712