1706f2543Smrg/* 2706f2543Smrg * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. 3706f2543Smrg * 4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5706f2543Smrg * copy of this software and associated documentation files (the "Software"), 6706f2543Smrg * to deal in the Software without restriction, including without limitation 7706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 9706f2543Smrg * Software is furnished to do so, subject to the following conditions: 10706f2543Smrg * 11706f2543Smrg * The above copyright notice and this permission notice (including the next 12706f2543Smrg * paragraph) shall be included in all copies or substantial portions of the 13706f2543Smrg * Software. 14706f2543Smrg * 15706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18706f2543Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19706f2543Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20706f2543Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21706f2543Smrg * DEALINGS IN THE SOFTWARE. 22706f2543Smrg * 23706f2543Smrg * Copyright © 2003 Keith Packard 24706f2543Smrg * 25706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 26706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 27706f2543Smrg * the above copyright notice appear in all copies and that both that 28706f2543Smrg * copyright notice and this permission notice appear in supporting 29706f2543Smrg * documentation, and that the name of Keith Packard not be used in 30706f2543Smrg * advertising or publicity pertaining to distribution of the software without 31706f2543Smrg * specific, written prior permission. Keith Packard makes no 32706f2543Smrg * representations about the suitability of this software for any purpose. It 33706f2543Smrg * is provided "as is" without express or implied warranty. 34706f2543Smrg * 35706f2543Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 36706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 37706f2543Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 38706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 39706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 40706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 41706f2543Smrg * PERFORMANCE OF THIS SOFTWARE. 42706f2543Smrg */ 43706f2543Smrg 44706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 45706f2543Smrg#include <dix-config.h> 46706f2543Smrg#endif 47706f2543Smrg 48706f2543Smrg#include "compint.h" 49706f2543Smrg 50706f2543Smrgstatic void 51706f2543SmrgcompScreenUpdate (ScreenPtr pScreen) 52706f2543Smrg{ 53706f2543Smrg compCheckTree (pScreen); 54706f2543Smrg compPaintChildrenToWindow (pScreen->root); 55706f2543Smrg} 56706f2543Smrg 57706f2543Smrgstatic void 58706f2543SmrgcompBlockHandler (int i, 59706f2543Smrg pointer blockData, 60706f2543Smrg pointer pTimeout, 61706f2543Smrg pointer pReadmask) 62706f2543Smrg{ 63706f2543Smrg ScreenPtr pScreen = screenInfo.screens[i]; 64706f2543Smrg CompScreenPtr cs = GetCompScreen (pScreen); 65706f2543Smrg 66706f2543Smrg pScreen->BlockHandler = cs->BlockHandler; 67706f2543Smrg compScreenUpdate (pScreen); 68706f2543Smrg (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); 69706f2543Smrg 70706f2543Smrg /* Next damage will restore the block handler */ 71706f2543Smrg cs->BlockHandler = NULL; 72706f2543Smrg} 73706f2543Smrg 74706f2543Smrgstatic void 75706f2543SmrgcompReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) 76706f2543Smrg{ 77706f2543Smrg WindowPtr pWin = (WindowPtr) closure; 78706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 79706f2543Smrg CompScreenPtr cs = GetCompScreen (pScreen); 80706f2543Smrg CompWindowPtr cw = GetCompWindow (pWin); 81706f2543Smrg 82706f2543Smrg if (!cs->BlockHandler) { 83706f2543Smrg cs->BlockHandler = pScreen->BlockHandler; 84706f2543Smrg pScreen->BlockHandler = compBlockHandler; 85706f2543Smrg } 86706f2543Smrg cw->damaged = TRUE; 87706f2543Smrg 88706f2543Smrg /* Mark the ancestors */ 89706f2543Smrg pWin = pWin->parent; 90706f2543Smrg while (pWin) { 91706f2543Smrg if (pWin->damagedDescendants) 92706f2543Smrg break; 93706f2543Smrg pWin->damagedDescendants = TRUE; 94706f2543Smrg pWin = pWin->parent; 95706f2543Smrg } 96706f2543Smrg} 97706f2543Smrg 98706f2543Smrgstatic void 99706f2543SmrgcompDestroyDamage (DamagePtr pDamage, void *closure) 100706f2543Smrg{ 101706f2543Smrg WindowPtr pWin = (WindowPtr) closure; 102706f2543Smrg CompWindowPtr cw = GetCompWindow (pWin); 103706f2543Smrg 104706f2543Smrg cw->damage = 0; 105706f2543Smrg} 106706f2543Smrg 107706f2543Smrg/* 108706f2543Smrg * Redirect one window for one client 109706f2543Smrg */ 110706f2543Smrgint 111706f2543SmrgcompRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) 112706f2543Smrg{ 113706f2543Smrg CompWindowPtr cw = GetCompWindow (pWin); 114706f2543Smrg CompClientWindowPtr ccw; 115706f2543Smrg Bool wasMapped = pWin->mapped; 116706f2543Smrg CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); 117706f2543Smrg 118706f2543Smrg if (pWin == cs->pOverlayWin) { 119706f2543Smrg return Success; 120706f2543Smrg } 121706f2543Smrg 122706f2543Smrg if (!pWin->parent) 123706f2543Smrg return BadMatch; 124706f2543Smrg 125706f2543Smrg /* 126706f2543Smrg * Only one Manual update is allowed 127706f2543Smrg */ 128706f2543Smrg if (cw && update == CompositeRedirectManual) 129706f2543Smrg for (ccw = cw->clients; ccw; ccw = ccw->next) 130706f2543Smrg if (ccw->update == CompositeRedirectManual) 131706f2543Smrg return BadAccess; 132706f2543Smrg 133706f2543Smrg /* 134706f2543Smrg * Allocate per-client per-window structure 135706f2543Smrg * The client *could* allocate multiple, but while supported, 136706f2543Smrg * it is not expected to be common 137706f2543Smrg */ 138706f2543Smrg ccw = malloc(sizeof (CompClientWindowRec)); 139706f2543Smrg if (!ccw) 140706f2543Smrg return BadAlloc; 141706f2543Smrg ccw->id = FakeClientID (pClient->index); 142706f2543Smrg ccw->update = update; 143706f2543Smrg /* 144706f2543Smrg * Now make sure there's a per-window structure to hang this from 145706f2543Smrg */ 146706f2543Smrg if (!cw) 147706f2543Smrg { 148706f2543Smrg cw = malloc(sizeof (CompWindowRec)); 149706f2543Smrg if (!cw) 150706f2543Smrg { 151706f2543Smrg free(ccw); 152706f2543Smrg return BadAlloc; 153706f2543Smrg } 154706f2543Smrg cw->damage = DamageCreate (compReportDamage, 155706f2543Smrg compDestroyDamage, 156706f2543Smrg DamageReportNonEmpty, 157706f2543Smrg FALSE, 158706f2543Smrg pWin->drawable.pScreen, 159706f2543Smrg pWin); 160706f2543Smrg if (!cw->damage) 161706f2543Smrg { 162706f2543Smrg free(ccw); 163706f2543Smrg free(cw); 164706f2543Smrg return BadAlloc; 165706f2543Smrg } 166706f2543Smrg if (wasMapped) 167706f2543Smrg { 168706f2543Smrg DisableMapUnmapEvents (pWin); 169706f2543Smrg UnmapWindow (pWin, FALSE); 170706f2543Smrg EnableMapUnmapEvents (pWin); 171706f2543Smrg } 172706f2543Smrg 173706f2543Smrg RegionNull(&cw->borderClip); 174706f2543Smrg cw->borderClipX = 0; 175706f2543Smrg cw->borderClipY = 0; 176706f2543Smrg cw->update = CompositeRedirectAutomatic; 177706f2543Smrg cw->clients = 0; 178706f2543Smrg cw->oldx = COMP_ORIGIN_INVALID; 179706f2543Smrg cw->oldy = COMP_ORIGIN_INVALID; 180706f2543Smrg cw->damageRegistered = FALSE; 181706f2543Smrg cw->damaged = FALSE; 182706f2543Smrg cw->pOldPixmap = NullPixmap; 183706f2543Smrg dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw); 184706f2543Smrg } 185706f2543Smrg ccw->next = cw->clients; 186706f2543Smrg cw->clients = ccw; 187706f2543Smrg if (!AddResource (ccw->id, CompositeClientWindowType, pWin)) 188706f2543Smrg return BadAlloc; 189706f2543Smrg if (ccw->update == CompositeRedirectManual) 190706f2543Smrg { 191706f2543Smrg /* If the window was CompositeRedirectAutomatic, then 192706f2543Smrg * unmap the window so that the parent clip list will 193706f2543Smrg * be correctly recomputed. 194706f2543Smrg */ 195706f2543Smrg if (pWin->mapped) 196706f2543Smrg { 197706f2543Smrg DisableMapUnmapEvents (pWin); 198706f2543Smrg UnmapWindow (pWin, FALSE); 199706f2543Smrg EnableMapUnmapEvents (pWin); 200706f2543Smrg } 201706f2543Smrg if (cw->damageRegistered) 202706f2543Smrg { 203706f2543Smrg DamageUnregister (&pWin->drawable, cw->damage); 204706f2543Smrg cw->damageRegistered = FALSE; 205706f2543Smrg } 206706f2543Smrg cw->update = CompositeRedirectManual; 207706f2543Smrg } 208706f2543Smrg 209706f2543Smrg if (!compCheckRedirect (pWin)) 210706f2543Smrg { 211706f2543Smrg FreeResource (ccw->id, RT_NONE); 212706f2543Smrg return BadAlloc; 213706f2543Smrg } 214706f2543Smrg if (wasMapped && !pWin->mapped) 215706f2543Smrg { 216706f2543Smrg Bool overrideRedirect = pWin->overrideRedirect; 217706f2543Smrg pWin->overrideRedirect = TRUE; 218706f2543Smrg DisableMapUnmapEvents (pWin); 219706f2543Smrg MapWindow (pWin, pClient); 220706f2543Smrg EnableMapUnmapEvents (pWin); 221706f2543Smrg pWin->overrideRedirect = overrideRedirect; 222706f2543Smrg } 223706f2543Smrg 224706f2543Smrg return Success; 225706f2543Smrg} 226706f2543Smrg 227706f2543Smrg/* 228706f2543Smrg * Free one of the per-client per-window resources, clearing 229706f2543Smrg * redirect and the per-window pointer as appropriate 230706f2543Smrg */ 231706f2543Smrgvoid 232706f2543SmrgcompFreeClientWindow (WindowPtr pWin, XID id) 233706f2543Smrg{ 234706f2543Smrg CompWindowPtr cw = GetCompWindow (pWin); 235706f2543Smrg CompClientWindowPtr ccw, *prev; 236706f2543Smrg Bool wasMapped = pWin->mapped; 237706f2543Smrg 238706f2543Smrg if (!cw) 239706f2543Smrg return; 240706f2543Smrg for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next) 241706f2543Smrg { 242706f2543Smrg if (ccw->id == id) 243706f2543Smrg { 244706f2543Smrg *prev = ccw->next; 245706f2543Smrg if (ccw->update == CompositeRedirectManual) 246706f2543Smrg cw->update = CompositeRedirectAutomatic; 247706f2543Smrg free(ccw); 248706f2543Smrg break; 249706f2543Smrg } 250706f2543Smrg } 251706f2543Smrg if (!cw->clients) 252706f2543Smrg { 253706f2543Smrg if (wasMapped) 254706f2543Smrg { 255706f2543Smrg DisableMapUnmapEvents (pWin); 256706f2543Smrg UnmapWindow (pWin, FALSE); 257706f2543Smrg EnableMapUnmapEvents (pWin); 258706f2543Smrg } 259706f2543Smrg 260706f2543Smrg if (pWin->redirectDraw != RedirectDrawNone) 261706f2543Smrg compFreePixmap (pWin); 262706f2543Smrg 263706f2543Smrg if (cw->damage) 264706f2543Smrg DamageDestroy (cw->damage); 265706f2543Smrg 266706f2543Smrg RegionUninit(&cw->borderClip); 267706f2543Smrg 268706f2543Smrg dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL); 269706f2543Smrg free(cw); 270706f2543Smrg } 271706f2543Smrg else if (cw->update == CompositeRedirectAutomatic && 272706f2543Smrg !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone) 273706f2543Smrg { 274706f2543Smrg DamageRegister (&pWin->drawable, cw->damage); 275706f2543Smrg cw->damageRegistered = TRUE; 276706f2543Smrg pWin->redirectDraw = RedirectDrawAutomatic; 277706f2543Smrg DamageDamageRegion(&pWin->drawable, &pWin->borderSize); 278706f2543Smrg } 279706f2543Smrg if (wasMapped && !pWin->mapped) 280706f2543Smrg { 281706f2543Smrg Bool overrideRedirect = pWin->overrideRedirect; 282706f2543Smrg pWin->overrideRedirect = TRUE; 283706f2543Smrg DisableMapUnmapEvents (pWin); 284706f2543Smrg MapWindow (pWin, clients[CLIENT_ID(id)]); 285706f2543Smrg EnableMapUnmapEvents (pWin); 286706f2543Smrg pWin->overrideRedirect = overrideRedirect; 287706f2543Smrg } 288706f2543Smrg} 289706f2543Smrg 290706f2543Smrg/* 291706f2543Smrg * This is easy, just free the appropriate resource. 292706f2543Smrg */ 293706f2543Smrg 294706f2543Smrgint 295706f2543SmrgcompUnredirectWindow (ClientPtr pClient, WindowPtr pWin, int update) 296706f2543Smrg{ 297706f2543Smrg CompWindowPtr cw = GetCompWindow (pWin); 298706f2543Smrg CompClientWindowPtr ccw; 299706f2543Smrg 300706f2543Smrg if (!cw) 301706f2543Smrg return BadValue; 302706f2543Smrg 303706f2543Smrg for (ccw = cw->clients; ccw; ccw = ccw->next) 304706f2543Smrg if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) 305706f2543Smrg { 306706f2543Smrg FreeResource (ccw->id, RT_NONE); 307706f2543Smrg return Success; 308706f2543Smrg } 309706f2543Smrg return BadValue; 310706f2543Smrg} 311706f2543Smrg 312706f2543Smrg/* 313706f2543Smrg * Redirect all subwindows for one client 314706f2543Smrg */ 315706f2543Smrg 316706f2543Smrgint 317706f2543SmrgcompRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update) 318706f2543Smrg{ 319706f2543Smrg CompSubwindowsPtr csw = GetCompSubwindows (pWin); 320706f2543Smrg CompClientWindowPtr ccw; 321706f2543Smrg WindowPtr pChild; 322706f2543Smrg 323706f2543Smrg /* 324706f2543Smrg * Only one Manual update is allowed 325706f2543Smrg */ 326706f2543Smrg if (csw && update == CompositeRedirectManual) 327706f2543Smrg for (ccw = csw->clients; ccw; ccw = ccw->next) 328706f2543Smrg if (ccw->update == CompositeRedirectManual) 329706f2543Smrg return BadAccess; 330706f2543Smrg /* 331706f2543Smrg * Allocate per-client per-window structure 332706f2543Smrg * The client *could* allocate multiple, but while supported, 333706f2543Smrg * it is not expected to be common 334706f2543Smrg */ 335706f2543Smrg ccw = malloc(sizeof (CompClientWindowRec)); 336706f2543Smrg if (!ccw) 337706f2543Smrg return BadAlloc; 338706f2543Smrg ccw->id = FakeClientID (pClient->index); 339706f2543Smrg ccw->update = update; 340706f2543Smrg /* 341706f2543Smrg * Now make sure there's a per-window structure to hang this from 342706f2543Smrg */ 343706f2543Smrg if (!csw) 344706f2543Smrg { 345706f2543Smrg csw = malloc(sizeof (CompSubwindowsRec)); 346706f2543Smrg if (!csw) 347706f2543Smrg { 348706f2543Smrg free(ccw); 349706f2543Smrg return BadAlloc; 350706f2543Smrg } 351706f2543Smrg csw->update = CompositeRedirectAutomatic; 352706f2543Smrg csw->clients = 0; 353706f2543Smrg dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw); 354706f2543Smrg } 355706f2543Smrg /* 356706f2543Smrg * Redirect all existing windows 357706f2543Smrg */ 358706f2543Smrg for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) 359706f2543Smrg { 360706f2543Smrg int ret = compRedirectWindow (pClient, pChild, update); 361706f2543Smrg if (ret != Success) 362706f2543Smrg { 363706f2543Smrg for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib) 364706f2543Smrg (void) compUnredirectWindow (pClient, pChild, update); 365706f2543Smrg if (!csw->clients) 366706f2543Smrg { 367706f2543Smrg free(csw); 368706f2543Smrg dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0); 369706f2543Smrg } 370706f2543Smrg free(ccw); 371706f2543Smrg return ret; 372706f2543Smrg } 373706f2543Smrg } 374706f2543Smrg /* 375706f2543Smrg * Hook into subwindows list 376706f2543Smrg */ 377706f2543Smrg ccw->next = csw->clients; 378706f2543Smrg csw->clients = ccw; 379706f2543Smrg if (!AddResource (ccw->id, CompositeClientSubwindowsType, pWin)) 380706f2543Smrg return BadAlloc; 381706f2543Smrg if (ccw->update == CompositeRedirectManual) 382706f2543Smrg { 383706f2543Smrg csw->update = CompositeRedirectManual; 384706f2543Smrg /* 385706f2543Smrg * tell damage extension that damage events for this client are 386706f2543Smrg * critical output 387706f2543Smrg */ 388706f2543Smrg DamageExtSetCritical (pClient, TRUE); 389706f2543Smrg } 390706f2543Smrg return Success; 391706f2543Smrg} 392706f2543Smrg 393706f2543Smrg/* 394706f2543Smrg * Free one of the per-client per-subwindows resources, 395706f2543Smrg * which frees one redirect per subwindow 396706f2543Smrg */ 397706f2543Smrgvoid 398706f2543SmrgcompFreeClientSubwindows (WindowPtr pWin, XID id) 399706f2543Smrg{ 400706f2543Smrg CompSubwindowsPtr csw = GetCompSubwindows (pWin); 401706f2543Smrg CompClientWindowPtr ccw, *prev; 402706f2543Smrg WindowPtr pChild; 403706f2543Smrg 404706f2543Smrg if (!csw) 405706f2543Smrg return; 406706f2543Smrg for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next) 407706f2543Smrg { 408706f2543Smrg if (ccw->id == id) 409706f2543Smrg { 410706f2543Smrg ClientPtr pClient = clients[CLIENT_ID(id)]; 411706f2543Smrg 412706f2543Smrg *prev = ccw->next; 413706f2543Smrg if (ccw->update == CompositeRedirectManual) 414706f2543Smrg { 415706f2543Smrg /* 416706f2543Smrg * tell damage extension that damage events for this client are 417706f2543Smrg * critical output 418706f2543Smrg */ 419706f2543Smrg DamageExtSetCritical (pClient, FALSE); 420706f2543Smrg csw->update = CompositeRedirectAutomatic; 421706f2543Smrg if (pWin->mapped) 422706f2543Smrg (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, TRUE); 423706f2543Smrg } 424706f2543Smrg 425706f2543Smrg /* 426706f2543Smrg * Unredirect all existing subwindows 427706f2543Smrg */ 428706f2543Smrg for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) 429706f2543Smrg (void) compUnredirectWindow (pClient, pChild, ccw->update); 430706f2543Smrg 431706f2543Smrg free(ccw); 432706f2543Smrg break; 433706f2543Smrg } 434706f2543Smrg } 435706f2543Smrg 436706f2543Smrg /* 437706f2543Smrg * Check if all of the per-client records are gone 438706f2543Smrg */ 439706f2543Smrg if (!csw->clients) 440706f2543Smrg { 441706f2543Smrg dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL); 442706f2543Smrg free(csw); 443706f2543Smrg } 444706f2543Smrg} 445706f2543Smrg 446706f2543Smrg/* 447706f2543Smrg * This is easy, just free the appropriate resource. 448706f2543Smrg */ 449706f2543Smrg 450706f2543Smrgint 451706f2543SmrgcompUnredirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update) 452706f2543Smrg{ 453706f2543Smrg CompSubwindowsPtr csw = GetCompSubwindows (pWin); 454706f2543Smrg CompClientWindowPtr ccw; 455706f2543Smrg 456706f2543Smrg if (!csw) 457706f2543Smrg return BadValue; 458706f2543Smrg for (ccw = csw->clients; ccw; ccw = ccw->next) 459706f2543Smrg if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) 460706f2543Smrg { 461706f2543Smrg FreeResource (ccw->id, RT_NONE); 462706f2543Smrg return Success; 463706f2543Smrg } 464706f2543Smrg return BadValue; 465706f2543Smrg} 466706f2543Smrg 467706f2543Smrg/* 468706f2543Smrg * Add redirection information for one subwindow (during reparent) 469706f2543Smrg */ 470706f2543Smrg 471706f2543Smrgint 472706f2543SmrgcompRedirectOneSubwindow (WindowPtr pParent, WindowPtr pWin) 473706f2543Smrg{ 474706f2543Smrg CompSubwindowsPtr csw = GetCompSubwindows (pParent); 475706f2543Smrg CompClientWindowPtr ccw; 476706f2543Smrg 477706f2543Smrg if (!csw) 478706f2543Smrg return Success; 479706f2543Smrg for (ccw = csw->clients; ccw; ccw = ccw->next) 480706f2543Smrg { 481706f2543Smrg int ret = compRedirectWindow (clients[CLIENT_ID(ccw->id)], 482706f2543Smrg pWin, ccw->update); 483706f2543Smrg if (ret != Success) 484706f2543Smrg return ret; 485706f2543Smrg } 486706f2543Smrg return Success; 487706f2543Smrg} 488706f2543Smrg 489706f2543Smrg/* 490706f2543Smrg * Remove redirection information for one subwindow (during reparent) 491706f2543Smrg */ 492706f2543Smrg 493706f2543Smrgint 494706f2543SmrgcompUnredirectOneSubwindow (WindowPtr pParent, WindowPtr pWin) 495706f2543Smrg{ 496706f2543Smrg CompSubwindowsPtr csw = GetCompSubwindows (pParent); 497706f2543Smrg CompClientWindowPtr ccw; 498706f2543Smrg 499706f2543Smrg if (!csw) 500706f2543Smrg return Success; 501706f2543Smrg for (ccw = csw->clients; ccw; ccw = ccw->next) 502706f2543Smrg { 503706f2543Smrg int ret = compUnredirectWindow (clients[CLIENT_ID(ccw->id)], 504706f2543Smrg pWin, ccw->update); 505706f2543Smrg if (ret != Success) 506706f2543Smrg return ret; 507706f2543Smrg } 508706f2543Smrg return Success; 509706f2543Smrg} 510706f2543Smrg 511706f2543Smrgstatic int 512706f2543SmrgbgNoneVisitWindow(WindowPtr pWin, void *null) 513706f2543Smrg{ 514706f2543Smrg if (pWin->backgroundState != BackgroundPixmap) 515706f2543Smrg return WT_WALKCHILDREN; 516706f2543Smrg if (pWin->background.pixmap != None) 517706f2543Smrg return WT_WALKCHILDREN; 518706f2543Smrg 519706f2543Smrg return WT_STOPWALKING; 520706f2543Smrg} 521706f2543Smrg 522706f2543Smrgstatic PixmapPtr 523706f2543SmrgcompNewPixmap (WindowPtr pWin, int x, int y, int w, int h, Bool map) 524706f2543Smrg{ 525706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 526706f2543Smrg WindowPtr pParent = pWin->parent; 527706f2543Smrg PixmapPtr pPixmap; 528706f2543Smrg 529706f2543Smrg pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth, 530706f2543Smrg CREATE_PIXMAP_USAGE_BACKING_PIXMAP); 531706f2543Smrg 532706f2543Smrg if (!pPixmap) 533706f2543Smrg return 0; 534706f2543Smrg 535706f2543Smrg pPixmap->screen_x = x; 536706f2543Smrg pPixmap->screen_y = y; 537706f2543Smrg 538706f2543Smrg /* resize allocations will update later in compCopyWindow, not here */ 539706f2543Smrg if (!map) 540706f2543Smrg return pPixmap; 541706f2543Smrg 542706f2543Smrg /* 543706f2543Smrg * If there's no bg=None in the tree, we're done. 544706f2543Smrg * 545706f2543Smrg * We could optimize this more by collection the regions of all the 546706f2543Smrg * bg=None subwindows and feeding that in as the clip for the 547706f2543Smrg * CopyArea below, but since window trees are shallow these days it 548706f2543Smrg * might not be worth the effort. 549706f2543Smrg */ 550706f2543Smrg if (TraverseTree(pWin, bgNoneVisitWindow, NULL) == WT_NOMATCH) 551706f2543Smrg return pPixmap; 552706f2543Smrg 553706f2543Smrg /* 554706f2543Smrg * Copy bits from the parent into the new pixmap so that it will 555706f2543Smrg * have "reasonable" contents in case for background None areas. 556706f2543Smrg */ 557706f2543Smrg if (pParent->drawable.depth == pWin->drawable.depth) 558706f2543Smrg { 559706f2543Smrg GCPtr pGC = GetScratchGC (pWin->drawable.depth, pScreen); 560706f2543Smrg 561706f2543Smrg if (pGC) 562706f2543Smrg { 563706f2543Smrg ChangeGCVal val; 564706f2543Smrg val.val = IncludeInferiors; 565706f2543Smrg 566706f2543Smrg ValidateGC(&pPixmap->drawable, pGC); 567706f2543Smrg ChangeGC (serverClient, pGC, GCSubwindowMode, &val); 568706f2543Smrg (*pGC->ops->CopyArea) (&pParent->drawable, 569706f2543Smrg &pPixmap->drawable, 570706f2543Smrg pGC, 571706f2543Smrg x - pParent->drawable.x, 572706f2543Smrg y - pParent->drawable.y, 573706f2543Smrg w, h, 0, 0); 574706f2543Smrg FreeScratchGC (pGC); 575706f2543Smrg } 576706f2543Smrg } 577706f2543Smrg else 578706f2543Smrg { 579706f2543Smrg PictFormatPtr pSrcFormat = compWindowFormat (pParent); 580706f2543Smrg PictFormatPtr pDstFormat = compWindowFormat (pWin); 581706f2543Smrg XID inferiors = IncludeInferiors; 582706f2543Smrg int error; 583706f2543Smrg 584706f2543Smrg PicturePtr pSrcPicture = CreatePicture (None, 585706f2543Smrg &pParent->drawable, 586706f2543Smrg pSrcFormat, 587706f2543Smrg CPSubwindowMode, 588706f2543Smrg &inferiors, 589706f2543Smrg serverClient, &error); 590706f2543Smrg 591706f2543Smrg PicturePtr pDstPicture = CreatePicture (None, 592706f2543Smrg &pPixmap->drawable, 593706f2543Smrg pDstFormat, 594706f2543Smrg 0, 0, 595706f2543Smrg serverClient, &error); 596706f2543Smrg 597706f2543Smrg if (pSrcPicture && pDstPicture) 598706f2543Smrg { 599706f2543Smrg CompositePicture (PictOpSrc, 600706f2543Smrg pSrcPicture, 601706f2543Smrg NULL, 602706f2543Smrg pDstPicture, 603706f2543Smrg x - pParent->drawable.x, 604706f2543Smrg y - pParent->drawable.y, 605706f2543Smrg 0, 0, 0, 0, w, h); 606706f2543Smrg } 607706f2543Smrg if (pSrcPicture) 608706f2543Smrg FreePicture (pSrcPicture, 0); 609706f2543Smrg if (pDstPicture) 610706f2543Smrg FreePicture (pDstPicture, 0); 611706f2543Smrg } 612706f2543Smrg return pPixmap; 613706f2543Smrg} 614706f2543Smrg 615706f2543SmrgBool 616706f2543SmrgcompAllocPixmap (WindowPtr pWin) 617706f2543Smrg{ 618706f2543Smrg int bw = (int) pWin->borderWidth; 619706f2543Smrg int x = pWin->drawable.x - bw; 620706f2543Smrg int y = pWin->drawable.y - bw; 621706f2543Smrg int w = pWin->drawable.width + (bw << 1); 622706f2543Smrg int h = pWin->drawable.height + (bw << 1); 623706f2543Smrg PixmapPtr pPixmap = compNewPixmap (pWin, x, y, w, h, TRUE); 624706f2543Smrg CompWindowPtr cw = GetCompWindow (pWin); 625706f2543Smrg 626706f2543Smrg if (!pPixmap) 627706f2543Smrg return FALSE; 628706f2543Smrg if (cw->update == CompositeRedirectAutomatic) 629706f2543Smrg pWin->redirectDraw = RedirectDrawAutomatic; 630706f2543Smrg else 631706f2543Smrg pWin->redirectDraw = RedirectDrawManual; 632706f2543Smrg 633706f2543Smrg compSetPixmap (pWin, pPixmap); 634706f2543Smrg cw->oldx = COMP_ORIGIN_INVALID; 635706f2543Smrg cw->oldy = COMP_ORIGIN_INVALID; 636706f2543Smrg cw->damageRegistered = FALSE; 637706f2543Smrg if (cw->update == CompositeRedirectAutomatic) 638706f2543Smrg { 639706f2543Smrg DamageRegister (&pWin->drawable, cw->damage); 640706f2543Smrg cw->damageRegistered = TRUE; 641706f2543Smrg } 642706f2543Smrg return TRUE; 643706f2543Smrg} 644706f2543Smrg 645706f2543Smrgvoid 646706f2543SmrgcompFreePixmap (WindowPtr pWin) 647706f2543Smrg{ 648706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 649706f2543Smrg PixmapPtr pRedirectPixmap, pParentPixmap; 650706f2543Smrg CompWindowPtr cw = GetCompWindow (pWin); 651706f2543Smrg 652706f2543Smrg if (cw->damageRegistered) 653706f2543Smrg { 654706f2543Smrg DamageUnregister (&pWin->drawable, cw->damage); 655706f2543Smrg cw->damageRegistered = FALSE; 656706f2543Smrg DamageEmpty (cw->damage); 657706f2543Smrg } 658706f2543Smrg /* 659706f2543Smrg * Move the parent-constrained border clip region back into 660706f2543Smrg * the window so that ValidateTree will handle the unmap 661706f2543Smrg * case correctly. Unmap adds the window borderClip to the 662706f2543Smrg * parent exposed area; regions beyond the parent cause crashes 663706f2543Smrg */ 664706f2543Smrg RegionCopy(&pWin->borderClip, &cw->borderClip); 665706f2543Smrg pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin); 666706f2543Smrg pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent); 667706f2543Smrg pWin->redirectDraw = RedirectDrawNone; 668706f2543Smrg compSetPixmap (pWin, pParentPixmap); 669706f2543Smrg (*pScreen->DestroyPixmap) (pRedirectPixmap); 670706f2543Smrg} 671706f2543Smrg 672706f2543Smrg/* 673706f2543Smrg * Make sure the pixmap is the right size and offset. Allocate a new 674706f2543Smrg * pixmap to change size, adjust origin to change offset, leaving the 675706f2543Smrg * old pixmap in cw->pOldPixmap so bits can be recovered 676706f2543Smrg */ 677706f2543SmrgBool 678706f2543SmrgcompReallocPixmap (WindowPtr pWin, int draw_x, int draw_y, 679706f2543Smrg unsigned int w, unsigned int h, int bw) 680706f2543Smrg{ 681706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 682706f2543Smrg PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin); 683706f2543Smrg PixmapPtr pNew; 684706f2543Smrg CompWindowPtr cw = GetCompWindow (pWin); 685706f2543Smrg int pix_x, pix_y; 686706f2543Smrg int pix_w, pix_h; 687706f2543Smrg 688706f2543Smrg assert (cw && pWin->redirectDraw != RedirectDrawNone); 689706f2543Smrg cw->oldx = pOld->screen_x; 690706f2543Smrg cw->oldy = pOld->screen_y; 691706f2543Smrg pix_x = draw_x - bw; 692706f2543Smrg pix_y = draw_y - bw; 693706f2543Smrg pix_w = w + (bw << 1); 694706f2543Smrg pix_h = h + (bw << 1); 695706f2543Smrg if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height) 696706f2543Smrg { 697706f2543Smrg pNew = compNewPixmap (pWin, pix_x, pix_y, pix_w, pix_h, FALSE); 698706f2543Smrg if (!pNew) 699706f2543Smrg return FALSE; 700706f2543Smrg cw->pOldPixmap = pOld; 701706f2543Smrg compSetPixmap (pWin, pNew); 702706f2543Smrg } 703706f2543Smrg else 704706f2543Smrg { 705706f2543Smrg pNew = pOld; 706706f2543Smrg cw->pOldPixmap = 0; 707706f2543Smrg } 708706f2543Smrg pNew->screen_x = pix_x; 709706f2543Smrg pNew->screen_y = pix_y; 710706f2543Smrg return TRUE; 711706f2543Smrg} 712