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