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