compalloc.c (21172B)
1 /* 2 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 * Copyright © 2003 Keith Packard 24 * 25 * Permission to use, copy, modify, distribute, and sell this software and its 26 * documentation for any purpose is hereby granted without fee, provided that 27 * the above copyright notice appear in all copies and that both that 28 * copyright notice and this permission notice appear in supporting 29 * documentation, and that the name of Keith Packard not be used in 30 * advertising or publicity pertaining to distribution of the software without 31 * specific, written prior permission. Keith Packard makes no 32 * representations about the suitability of this software for any purpose. It 33 * is provided "as is" without express or implied warranty. 34 * 35 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 36 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 37 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 38 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 39 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 40 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 41 * PERFORMANCE OF THIS SOFTWARE. 42 */ 43 44 #ifdef HAVE_DIX_CONFIG_H 45 #include <dix-config.h> 46 #endif 47 48 #include "compint.h" 49 50 static Bool 51 compScreenUpdate(ClientPtr pClient, void *closure) 52 { 53 ScreenPtr pScreen = closure; 54 CompScreenPtr cs = GetCompScreen(pScreen); 55 56 compCheckTree(pScreen); 57 compPaintChildrenToWindow(pScreen->root); 58 59 /* Next damage will restore the worker */ 60 cs->pendingScreenUpdate = FALSE; 61 return TRUE; 62 } 63 64 void 65 compMarkAncestors(WindowPtr pWin) 66 { 67 pWin = pWin->parent; 68 while (pWin) { 69 if (pWin->damagedDescendants) 70 return; 71 pWin->damagedDescendants = TRUE; 72 pWin = pWin->parent; 73 } 74 } 75 76 static void 77 compReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure) 78 { 79 WindowPtr pWin = (WindowPtr) closure; 80 ScreenPtr pScreen = pWin->drawable.pScreen; 81 CompScreenPtr cs = GetCompScreen(pScreen); 82 CompWindowPtr cw = GetCompWindow(pWin); 83 84 if (!cs->pendingScreenUpdate) { 85 QueueWorkProc(compScreenUpdate, serverClient, pScreen); 86 cs->pendingScreenUpdate = TRUE; 87 } 88 cw->damaged = TRUE; 89 90 compMarkAncestors(pWin); 91 } 92 93 static void 94 compDestroyDamage(DamagePtr pDamage, void *closure) 95 { 96 WindowPtr pWin = (WindowPtr) closure; 97 CompWindowPtr cw = GetCompWindow(pWin); 98 99 cw->damage = 0; 100 cw->damaged = 0; 101 cw->damageRegistered = 0; 102 } 103 104 static Bool 105 compMarkWindows(WindowPtr pWin, WindowPtr *ppLayerWin) 106 { 107 ScreenPtr pScreen = pWin->drawable.pScreen; 108 WindowPtr pLayerWin = pWin; 109 110 if (!pWin->viewable) 111 return FALSE; 112 113 (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin); 114 (*pScreen->MarkWindow) (pLayerWin->parent); 115 116 *ppLayerWin = pLayerWin; 117 118 return TRUE; 119 } 120 121 static void 122 compHandleMarkedWindows(WindowPtr pWin, WindowPtr pLayerWin) 123 { 124 ScreenPtr pScreen = pWin->drawable.pScreen; 125 126 (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTOther); 127 (*pScreen->HandleExposures) (pLayerWin->parent); 128 if (pScreen->PostValidateTree) 129 (*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin, VTOther); 130 } 131 132 /* 133 * Redirect one window for one client 134 */ 135 int 136 compRedirectWindow(ClientPtr pClient, WindowPtr pWin, int update) 137 { 138 CompWindowPtr cw = GetCompWindow(pWin); 139 CompClientWindowPtr ccw; 140 CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); 141 WindowPtr pLayerWin; 142 Bool anyMarked = FALSE; 143 144 if (pWin == cs->pOverlayWin) { 145 return Success; 146 } 147 148 if (!pWin->parent) 149 return BadMatch; 150 151 /* 152 * Only one Manual update is allowed 153 */ 154 if (cw && update == CompositeRedirectManual) 155 for (ccw = cw->clients; ccw; ccw = ccw->next) 156 if (ccw->update == CompositeRedirectManual) 157 return BadAccess; 158 159 /* 160 * Allocate per-client per-window structure 161 * The client *could* allocate multiple, but while supported, 162 * it is not expected to be common 163 */ 164 ccw = malloc(sizeof(CompClientWindowRec)); 165 if (!ccw) 166 return BadAlloc; 167 ccw->id = FakeClientID(pClient->index); 168 ccw->update = update; 169 /* 170 * Now make sure there's a per-window structure to hang this from 171 */ 172 if (!cw) { 173 cw = malloc(sizeof(CompWindowRec)); 174 if (!cw) { 175 free(ccw); 176 return BadAlloc; 177 } 178 cw->damage = DamageCreate(compReportDamage, 179 compDestroyDamage, 180 DamageReportNonEmpty, 181 FALSE, pWin->drawable.pScreen, pWin); 182 if (!cw->damage) { 183 free(ccw); 184 free(cw); 185 return BadAlloc; 186 } 187 188 anyMarked = compMarkWindows(pWin, &pLayerWin); 189 190 RegionNull(&cw->borderClip); 191 cw->update = CompositeRedirectAutomatic; 192 cw->clients = 0; 193 cw->oldx = COMP_ORIGIN_INVALID; 194 cw->oldy = COMP_ORIGIN_INVALID; 195 cw->damageRegistered = FALSE; 196 cw->damaged = FALSE; 197 cw->pOldPixmap = NullPixmap; 198 dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw); 199 } 200 ccw->next = cw->clients; 201 cw->clients = ccw; 202 if (!AddResource(ccw->id, CompositeClientWindowType, pWin)) 203 return BadAlloc; 204 if (ccw->update == CompositeRedirectManual) { 205 if (!anyMarked) 206 anyMarked = compMarkWindows(pWin, &pLayerWin); 207 208 if (cw->damageRegistered) { 209 DamageUnregister(cw->damage); 210 cw->damageRegistered = FALSE; 211 } 212 cw->update = CompositeRedirectManual; 213 } 214 else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) { 215 if (!anyMarked) 216 anyMarked = compMarkWindows(pWin, &pLayerWin); 217 } 218 219 if (!compCheckRedirect(pWin)) { 220 FreeResource(ccw->id, RT_NONE); 221 return BadAlloc; 222 } 223 224 if (anyMarked) 225 compHandleMarkedWindows(pWin, pLayerWin); 226 227 return Success; 228 } 229 230 void 231 compRestoreWindow(WindowPtr pWin, PixmapPtr pPixmap) 232 { 233 ScreenPtr pScreen = pWin->drawable.pScreen; 234 WindowPtr pParent = pWin->parent; 235 236 if (pParent->drawable.depth == pWin->drawable.depth) { 237 GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen); 238 int bw = (int) pWin->borderWidth; 239 int x = bw; 240 int y = bw; 241 int w = pWin->drawable.width; 242 int h = pWin->drawable.height; 243 244 if (pGC) { 245 ChangeGCVal val; 246 247 val.val = IncludeInferiors; 248 ChangeGC(NullClient, pGC, GCSubwindowMode, &val); 249 ValidateGC(&pWin->drawable, pGC); 250 (*pGC->ops->CopyArea) (&pPixmap->drawable, 251 &pWin->drawable, pGC, x, y, w, h, 0, 0); 252 FreeScratchGC(pGC); 253 } 254 } 255 } 256 257 /* 258 * Free one of the per-client per-window resources, clearing 259 * redirect and the per-window pointer as appropriate 260 */ 261 void 262 compFreeClientWindow(WindowPtr pWin, XID id) 263 { 264 ScreenPtr pScreen = pWin->drawable.pScreen; 265 CompWindowPtr cw = GetCompWindow(pWin); 266 CompClientWindowPtr ccw, *prev; 267 Bool anyMarked = FALSE; 268 WindowPtr pLayerWin; 269 PixmapPtr pPixmap = NULL; 270 271 if (!cw) 272 return; 273 for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next) { 274 if (ccw->id == id) { 275 *prev = ccw->next; 276 if (ccw->update == CompositeRedirectManual) 277 cw->update = CompositeRedirectAutomatic; 278 free(ccw); 279 break; 280 } 281 } 282 if (!cw->clients) { 283 anyMarked = compMarkWindows(pWin, &pLayerWin); 284 285 if (pWin->redirectDraw != RedirectDrawNone) { 286 pPixmap = (*pScreen->GetWindowPixmap) (pWin); 287 compSetParentPixmap(pWin); 288 } 289 290 if (cw->damage) 291 DamageDestroy(cw->damage); 292 293 RegionUninit(&cw->borderClip); 294 295 dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL); 296 free(cw); 297 } 298 else if (cw->update == CompositeRedirectAutomatic && 299 !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone) { 300 anyMarked = compMarkWindows(pWin, &pLayerWin); 301 302 DamageRegister(&pWin->drawable, cw->damage); 303 cw->damageRegistered = TRUE; 304 pWin->redirectDraw = RedirectDrawAutomatic; 305 DamageDamageRegion(&pWin->drawable, &pWin->borderSize); 306 } 307 308 if (anyMarked) 309 compHandleMarkedWindows(pWin, pLayerWin); 310 311 if (pPixmap) { 312 compRestoreWindow(pWin, pPixmap); 313 (*pScreen->DestroyPixmap) (pPixmap); 314 } 315 } 316 317 /* 318 * This is easy, just free the appropriate resource. 319 */ 320 321 int 322 compUnredirectWindow(ClientPtr pClient, WindowPtr pWin, int update) 323 { 324 CompWindowPtr cw = GetCompWindow(pWin); 325 CompClientWindowPtr ccw; 326 327 if (!cw) 328 return BadValue; 329 330 for (ccw = cw->clients; ccw; ccw = ccw->next) 331 if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) { 332 FreeResource(ccw->id, RT_NONE); 333 return Success; 334 } 335 return BadValue; 336 } 337 338 /* 339 * Redirect all subwindows for one client 340 */ 341 342 int 343 compRedirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update) 344 { 345 CompSubwindowsPtr csw = GetCompSubwindows(pWin); 346 CompClientWindowPtr ccw; 347 WindowPtr pChild; 348 349 /* 350 * Only one Manual update is allowed 351 */ 352 if (csw && update == CompositeRedirectManual) 353 for (ccw = csw->clients; ccw; ccw = ccw->next) 354 if (ccw->update == CompositeRedirectManual) 355 return BadAccess; 356 /* 357 * Allocate per-client per-window structure 358 * The client *could* allocate multiple, but while supported, 359 * it is not expected to be common 360 */ 361 ccw = malloc(sizeof(CompClientWindowRec)); 362 if (!ccw) 363 return BadAlloc; 364 ccw->id = FakeClientID(pClient->index); 365 ccw->update = update; 366 /* 367 * Now make sure there's a per-window structure to hang this from 368 */ 369 if (!csw) { 370 csw = malloc(sizeof(CompSubwindowsRec)); 371 if (!csw) { 372 free(ccw); 373 return BadAlloc; 374 } 375 csw->update = CompositeRedirectAutomatic; 376 csw->clients = 0; 377 dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw); 378 } 379 /* 380 * Redirect all existing windows 381 */ 382 for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) { 383 int ret = compRedirectWindow(pClient, pChild, update); 384 385 if (ret != Success) { 386 for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib) 387 (void) compUnredirectWindow(pClient, pChild, update); 388 if (!csw->clients) { 389 free(csw); 390 dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0); 391 } 392 free(ccw); 393 return ret; 394 } 395 } 396 /* 397 * Hook into subwindows list 398 */ 399 ccw->next = csw->clients; 400 csw->clients = ccw; 401 if (!AddResource(ccw->id, CompositeClientSubwindowsType, pWin)) 402 return BadAlloc; 403 if (ccw->update == CompositeRedirectManual) { 404 csw->update = CompositeRedirectManual; 405 /* 406 * tell damage extension that damage events for this client are 407 * critical output 408 */ 409 DamageExtSetCritical(pClient, TRUE); 410 pWin->inhibitBGPaint = TRUE; 411 } 412 return Success; 413 } 414 415 /* 416 * Free one of the per-client per-subwindows resources, 417 * which frees one redirect per subwindow 418 */ 419 void 420 compFreeClientSubwindows(WindowPtr pWin, XID id) 421 { 422 CompSubwindowsPtr csw = GetCompSubwindows(pWin); 423 CompClientWindowPtr ccw, *prev; 424 WindowPtr pChild; 425 426 if (!csw) 427 return; 428 for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next) { 429 if (ccw->id == id) { 430 ClientPtr pClient = clients[CLIENT_ID(id)]; 431 432 *prev = ccw->next; 433 if (ccw->update == CompositeRedirectManual) { 434 /* 435 * tell damage extension that damage events for this client are 436 * critical output 437 */ 438 DamageExtSetCritical(pClient, FALSE); 439 csw->update = CompositeRedirectAutomatic; 440 pWin->inhibitBGPaint = FALSE; 441 if (pWin->mapped) 442 (*pWin->drawable.pScreen->ClearToBackground) (pWin, 0, 0, 0, 443 0, TRUE); 444 } 445 446 /* 447 * Unredirect all existing subwindows 448 */ 449 for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) 450 (void) compUnredirectWindow(pClient, pChild, ccw->update); 451 452 free(ccw); 453 break; 454 } 455 } 456 457 /* 458 * Check if all of the per-client records are gone 459 */ 460 if (!csw->clients) { 461 dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL); 462 free(csw); 463 } 464 } 465 466 /* 467 * This is easy, just free the appropriate resource. 468 */ 469 470 int 471 compUnredirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update) 472 { 473 CompSubwindowsPtr csw = GetCompSubwindows(pWin); 474 CompClientWindowPtr ccw; 475 476 if (!csw) 477 return BadValue; 478 for (ccw = csw->clients; ccw; ccw = ccw->next) 479 if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) { 480 FreeResource(ccw->id, RT_NONE); 481 return Success; 482 } 483 return BadValue; 484 } 485 486 /* 487 * Add redirection information for one subwindow (during reparent) 488 */ 489 490 int 491 compRedirectOneSubwindow(WindowPtr pParent, WindowPtr pWin) 492 { 493 CompSubwindowsPtr csw = GetCompSubwindows(pParent); 494 CompClientWindowPtr ccw; 495 496 if (!csw) 497 return Success; 498 for (ccw = csw->clients; ccw; ccw = ccw->next) { 499 int ret = compRedirectWindow(clients[CLIENT_ID(ccw->id)], 500 pWin, ccw->update); 501 502 if (ret != Success) 503 return ret; 504 } 505 return Success; 506 } 507 508 /* 509 * Remove redirection information for one subwindow (during reparent) 510 */ 511 512 int 513 compUnredirectOneSubwindow(WindowPtr pParent, WindowPtr pWin) 514 { 515 CompSubwindowsPtr csw = GetCompSubwindows(pParent); 516 CompClientWindowPtr ccw; 517 518 if (!csw) 519 return Success; 520 for (ccw = csw->clients; ccw; ccw = ccw->next) { 521 int ret = compUnredirectWindow(clients[CLIENT_ID(ccw->id)], 522 pWin, ccw->update); 523 524 if (ret != Success) 525 return ret; 526 } 527 return Success; 528 } 529 530 static PixmapPtr 531 compNewPixmap(WindowPtr pWin, int x, int y, int w, int h) 532 { 533 ScreenPtr pScreen = pWin->drawable.pScreen; 534 WindowPtr pParent = pWin->parent; 535 PixmapPtr pPixmap; 536 537 pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth, 538 CREATE_PIXMAP_USAGE_BACKING_PIXMAP); 539 540 if (!pPixmap) 541 return 0; 542 543 pPixmap->screen_x = x; 544 pPixmap->screen_y = y; 545 546 if (pParent->drawable.depth == pWin->drawable.depth) { 547 GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen); 548 549 if (pGC) { 550 ChangeGCVal val; 551 552 val.val = IncludeInferiors; 553 ChangeGC(NullClient, pGC, GCSubwindowMode, &val); 554 ValidateGC(&pPixmap->drawable, pGC); 555 (*pGC->ops->CopyArea) (&pParent->drawable, 556 &pPixmap->drawable, 557 pGC, 558 x - pParent->drawable.x, 559 y - pParent->drawable.y, w, h, 0, 0); 560 FreeScratchGC(pGC); 561 } 562 } 563 else { 564 PictFormatPtr pSrcFormat = PictureWindowFormat(pParent); 565 PictFormatPtr pDstFormat = PictureWindowFormat(pWin); 566 XID inferiors = IncludeInferiors; 567 int error; 568 569 PicturePtr pSrcPicture = CreatePicture(None, 570 &pParent->drawable, 571 pSrcFormat, 572 CPSubwindowMode, 573 &inferiors, 574 serverClient, &error); 575 576 PicturePtr pDstPicture = CreatePicture(None, 577 &pPixmap->drawable, 578 pDstFormat, 579 0, 0, 580 serverClient, &error); 581 582 if (pSrcPicture && pDstPicture) { 583 CompositePicture(PictOpSrc, 584 pSrcPicture, 585 NULL, 586 pDstPicture, 587 x - pParent->drawable.x, 588 y - pParent->drawable.y, 0, 0, 0, 0, w, h); 589 } 590 if (pSrcPicture) 591 FreePicture(pSrcPicture, 0); 592 if (pDstPicture) 593 FreePicture(pDstPicture, 0); 594 } 595 return pPixmap; 596 } 597 598 Bool 599 compAllocPixmap(WindowPtr pWin) 600 { 601 int bw = (int) pWin->borderWidth; 602 int x = pWin->drawable.x - bw; 603 int y = pWin->drawable.y - bw; 604 int w = pWin->drawable.width + (bw << 1); 605 int h = pWin->drawable.height + (bw << 1); 606 PixmapPtr pPixmap = compNewPixmap(pWin, x, y, w, h); 607 CompWindowPtr cw = GetCompWindow(pWin); 608 609 if (!pPixmap) 610 return FALSE; 611 if (cw->update == CompositeRedirectAutomatic) 612 pWin->redirectDraw = RedirectDrawAutomatic; 613 else 614 pWin->redirectDraw = RedirectDrawManual; 615 616 compSetPixmap(pWin, pPixmap, bw); 617 cw->oldx = COMP_ORIGIN_INVALID; 618 cw->oldy = COMP_ORIGIN_INVALID; 619 cw->damageRegistered = FALSE; 620 if (cw->update == CompositeRedirectAutomatic) { 621 DamageRegister(&pWin->drawable, cw->damage); 622 cw->damageRegistered = TRUE; 623 } 624 625 /* Make sure our borderClip is up to date */ 626 RegionUninit(&cw->borderClip); 627 RegionCopy(&cw->borderClip, &pWin->borderClip); 628 cw->borderClipX = pWin->drawable.x; 629 cw->borderClipY = pWin->drawable.y; 630 631 return TRUE; 632 } 633 634 void 635 compSetParentPixmap(WindowPtr pWin) 636 { 637 ScreenPtr pScreen = pWin->drawable.pScreen; 638 PixmapPtr pParentPixmap; 639 CompWindowPtr cw = GetCompWindow(pWin); 640 641 if (cw->damageRegistered) { 642 DamageUnregister(cw->damage); 643 cw->damageRegistered = FALSE; 644 DamageEmpty(cw->damage); 645 } 646 /* 647 * Move the parent-constrained border clip region back into 648 * the window so that ValidateTree will handle the unmap 649 * case correctly. Unmap adds the window borderClip to the 650 * parent exposed area; regions beyond the parent cause crashes 651 */ 652 RegionCopy(&pWin->borderClip, &cw->borderClip); 653 pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent); 654 pWin->redirectDraw = RedirectDrawNone; 655 compSetPixmap(pWin, pParentPixmap, pWin->borderWidth); 656 } 657 658 /* 659 * Make sure the pixmap is the right size and offset. Allocate a new 660 * pixmap to change size, adjust origin to change offset, leaving the 661 * old pixmap in cw->pOldPixmap so bits can be recovered 662 */ 663 Bool 664 compReallocPixmap(WindowPtr pWin, int draw_x, int draw_y, 665 unsigned int w, unsigned int h, int bw) 666 { 667 ScreenPtr pScreen = pWin->drawable.pScreen; 668 PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin); 669 PixmapPtr pNew; 670 CompWindowPtr cw = GetCompWindow(pWin); 671 int pix_x, pix_y; 672 int pix_w, pix_h; 673 674 assert(cw); 675 assert(pWin->redirectDraw != RedirectDrawNone); 676 cw->oldx = pOld->screen_x; 677 cw->oldy = pOld->screen_y; 678 pix_x = draw_x - bw; 679 pix_y = draw_y - bw; 680 pix_w = w + (bw << 1); 681 pix_h = h + (bw << 1); 682 if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height) { 683 pNew = compNewPixmap(pWin, pix_x, pix_y, pix_w, pix_h); 684 if (!pNew) 685 return FALSE; 686 cw->pOldPixmap = pOld; 687 compSetPixmap(pWin, pNew, bw); 688 } 689 else { 690 pNew = pOld; 691 cw->pOldPixmap = 0; 692 } 693 pNew->screen_x = pix_x; 694 pNew->screen_y = pix_y; 695 return TRUE; 696 }