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