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 50static Bool 51compScreenUpdate(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 64void 65compMarkAncestors(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 76static void 77compReportDamage(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 93static void 94compDestroyDamage(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 104static Bool 105compMarkWindows(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 121static void 122compHandleMarkedWindows(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 */ 135int 136compRedirectWindow(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 int status = Success; 144 145 if (pWin == cs->pOverlayWin) { 146 return Success; 147 } 148 149 if (!pWin->parent) 150 return BadMatch; 151 152 /* 153 * Only one Manual update is allowed 154 */ 155 if (cw && update == CompositeRedirectManual) 156 for (ccw = cw->clients; ccw; ccw = ccw->next) 157 if (ccw->update == CompositeRedirectManual) 158 return BadAccess; 159 160 /* 161 * Allocate per-client per-window structure 162 * The client *could* allocate multiple, but while supported, 163 * it is not expected to be common 164 */ 165 ccw = malloc(sizeof(CompClientWindowRec)); 166 if (!ccw) 167 return BadAlloc; 168 ccw->id = FakeClientID(pClient->index); 169 ccw->update = update; 170 /* 171 * Now make sure there's a per-window structure to hang this from 172 */ 173 if (!cw) { 174 cw = malloc(sizeof(CompWindowRec)); 175 if (!cw) { 176 free(ccw); 177 return BadAlloc; 178 } 179 cw->damage = DamageCreate(compReportDamage, 180 compDestroyDamage, 181 DamageReportNonEmpty, 182 FALSE, pWin->drawable.pScreen, pWin); 183 if (!cw->damage) { 184 free(ccw); 185 free(cw); 186 return BadAlloc; 187 } 188 189 anyMarked = compMarkWindows(pWin, &pLayerWin); 190 191 RegionNull(&cw->borderClip); 192 cw->update = CompositeRedirectAutomatic; 193 cw->clients = 0; 194 cw->oldx = COMP_ORIGIN_INVALID; 195 cw->oldy = COMP_ORIGIN_INVALID; 196 cw->damageRegistered = FALSE; 197 cw->damaged = FALSE; 198 cw->pOldPixmap = NullPixmap; 199 dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw); 200 } 201 ccw->next = cw->clients; 202 cw->clients = ccw; 203 if (!AddResource(ccw->id, CompositeClientWindowType, pWin)) 204 return BadAlloc; 205 if (ccw->update == CompositeRedirectManual) { 206 if (!anyMarked) 207 anyMarked = compMarkWindows(pWin, &pLayerWin); 208 209 if (cw->damageRegistered) { 210 DamageUnregister(cw->damage); 211 cw->damageRegistered = FALSE; 212 } 213 cw->update = CompositeRedirectManual; 214 } 215 else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) { 216 if (!anyMarked) 217 anyMarked = compMarkWindows(pWin, &pLayerWin); 218 } 219 220 if (!compCheckRedirect(pWin)) { 221 FreeResource(ccw->id, RT_NONE); 222 status = BadAlloc; 223 } 224 225 if (anyMarked) 226 compHandleMarkedWindows(pWin, pLayerWin); 227 228 return status; 229} 230 231void 232compRestoreWindow(WindowPtr pWin, PixmapPtr pPixmap) 233{ 234 ScreenPtr pScreen = pWin->drawable.pScreen; 235 WindowPtr pParent = pWin->parent; 236 237 if (pParent->drawable.depth == pWin->drawable.depth) { 238 GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen); 239 int bw = (int) pWin->borderWidth; 240 int x = bw; 241 int y = bw; 242 int w = pWin->drawable.width; 243 int h = pWin->drawable.height; 244 245 if (pGC) { 246 ChangeGCVal val; 247 248 val.val = IncludeInferiors; 249 ChangeGC(NullClient, pGC, GCSubwindowMode, &val); 250 ValidateGC(&pWin->drawable, pGC); 251 (*pGC->ops->CopyArea) (&pPixmap->drawable, 252 &pWin->drawable, pGC, x, y, w, h, 0, 0); 253 FreeScratchGC(pGC); 254 } 255 } 256} 257 258/* 259 * Free one of the per-client per-window resources, clearing 260 * redirect and the per-window pointer as appropriate 261 */ 262void 263compFreeClientWindow(WindowPtr pWin, XID id) 264{ 265 ScreenPtr pScreen = pWin->drawable.pScreen; 266 CompWindowPtr cw = GetCompWindow(pWin); 267 CompClientWindowPtr ccw, *prev; 268 Bool anyMarked = FALSE; 269 WindowPtr pLayerWin; 270 PixmapPtr pPixmap = NULL; 271 272 if (!cw) 273 return; 274 for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next) { 275 if (ccw->id == id) { 276 *prev = ccw->next; 277 if (ccw->update == CompositeRedirectManual) 278 cw->update = CompositeRedirectAutomatic; 279 free(ccw); 280 break; 281 } 282 } 283 if (!cw->clients) { 284 anyMarked = compMarkWindows(pWin, &pLayerWin); 285 286 if (pWin->redirectDraw != RedirectDrawNone) { 287 pPixmap = (*pScreen->GetWindowPixmap) (pWin); 288 compSetParentPixmap(pWin); 289 } 290 291 if (cw->damage) 292 DamageDestroy(cw->damage); 293 294 RegionUninit(&cw->borderClip); 295 296 dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL); 297 free(cw); 298 } 299 else if (cw->update == CompositeRedirectAutomatic && 300 !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone) { 301 anyMarked = compMarkWindows(pWin, &pLayerWin); 302 303 DamageRegister(&pWin->drawable, cw->damage); 304 cw->damageRegistered = TRUE; 305 pWin->redirectDraw = RedirectDrawAutomatic; 306 DamageDamageRegion(&pWin->drawable, &pWin->borderSize); 307 } 308 309 if (anyMarked) 310 compHandleMarkedWindows(pWin, pLayerWin); 311 312 if (pPixmap) { 313 compRestoreWindow(pWin, pPixmap); 314 (*pScreen->DestroyPixmap) (pPixmap); 315 } 316} 317 318/* 319 * This is easy, just free the appropriate resource. 320 */ 321 322int 323compUnredirectWindow(ClientPtr pClient, WindowPtr pWin, int update) 324{ 325 CompWindowPtr cw = GetCompWindow(pWin); 326 CompClientWindowPtr ccw; 327 328 if (!cw) 329 return BadValue; 330 331 for (ccw = cw->clients; ccw; ccw = ccw->next) 332 if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) { 333 FreeResource(ccw->id, RT_NONE); 334 return Success; 335 } 336 return BadValue; 337} 338 339/* 340 * Redirect all subwindows for one client 341 */ 342 343int 344compRedirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update) 345{ 346 CompSubwindowsPtr csw = GetCompSubwindows(pWin); 347 CompClientWindowPtr ccw; 348 WindowPtr pChild; 349 350 /* 351 * Only one Manual update is allowed 352 */ 353 if (csw && update == CompositeRedirectManual) 354 for (ccw = csw->clients; ccw; ccw = ccw->next) 355 if (ccw->update == CompositeRedirectManual) 356 return BadAccess; 357 /* 358 * Allocate per-client per-window structure 359 * The client *could* allocate multiple, but while supported, 360 * it is not expected to be common 361 */ 362 ccw = malloc(sizeof(CompClientWindowRec)); 363 if (!ccw) 364 return BadAlloc; 365 ccw->id = FakeClientID(pClient->index); 366 ccw->update = update; 367 /* 368 * Now make sure there's a per-window structure to hang this from 369 */ 370 if (!csw) { 371 csw = malloc(sizeof(CompSubwindowsRec)); 372 if (!csw) { 373 free(ccw); 374 return BadAlloc; 375 } 376 csw->update = CompositeRedirectAutomatic; 377 csw->clients = 0; 378 dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw); 379 } 380 /* 381 * Redirect all existing windows 382 */ 383 for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) { 384 int ret = compRedirectWindow(pClient, pChild, update); 385 386 if (ret != Success) { 387 for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib) 388 (void) compUnredirectWindow(pClient, pChild, update); 389 if (!csw->clients) { 390 free(csw); 391 dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0); 392 } 393 free(ccw); 394 return ret; 395 } 396 } 397 /* 398 * Hook into subwindows list 399 */ 400 ccw->next = csw->clients; 401 csw->clients = ccw; 402 if (!AddResource(ccw->id, CompositeClientSubwindowsType, pWin)) 403 return BadAlloc; 404 if (ccw->update == CompositeRedirectManual) { 405 csw->update = CompositeRedirectManual; 406 /* 407 * tell damage extension that damage events for this client are 408 * critical output 409 */ 410 DamageExtSetCritical(pClient, TRUE); 411 pWin->inhibitBGPaint = TRUE; 412 } 413 return Success; 414} 415 416/* 417 * Free one of the per-client per-subwindows resources, 418 * which frees one redirect per subwindow 419 */ 420void 421compFreeClientSubwindows(WindowPtr pWin, XID id) 422{ 423 CompSubwindowsPtr csw = GetCompSubwindows(pWin); 424 CompClientWindowPtr ccw, *prev; 425 WindowPtr pChild; 426 427 if (!csw) 428 return; 429 for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next) { 430 if (ccw->id == id) { 431 ClientPtr pClient = clients[CLIENT_ID(id)]; 432 433 *prev = ccw->next; 434 if (ccw->update == CompositeRedirectManual) { 435 /* 436 * tell damage extension that damage events for this client are 437 * critical output 438 */ 439 DamageExtSetCritical(pClient, FALSE); 440 csw->update = CompositeRedirectAutomatic; 441 pWin->inhibitBGPaint = FALSE; 442 if (pWin->mapped) 443 (*pWin->drawable.pScreen->ClearToBackground) (pWin, 0, 0, 0, 444 0, TRUE); 445 } 446 447 /* 448 * Unredirect all existing subwindows 449 */ 450 for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) 451 (void) compUnredirectWindow(pClient, pChild, ccw->update); 452 453 free(ccw); 454 break; 455 } 456 } 457 458 /* 459 * Check if all of the per-client records are gone 460 */ 461 if (!csw->clients) { 462 dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL); 463 free(csw); 464 } 465} 466 467/* 468 * This is easy, just free the appropriate resource. 469 */ 470 471int 472compUnredirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update) 473{ 474 CompSubwindowsPtr csw = GetCompSubwindows(pWin); 475 CompClientWindowPtr ccw; 476 477 if (!csw) 478 return BadValue; 479 for (ccw = csw->clients; ccw; ccw = ccw->next) 480 if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) { 481 FreeResource(ccw->id, RT_NONE); 482 return Success; 483 } 484 return BadValue; 485} 486 487/* 488 * Add redirection information for one subwindow (during reparent) 489 */ 490 491int 492compRedirectOneSubwindow(WindowPtr pParent, WindowPtr pWin) 493{ 494 CompSubwindowsPtr csw = GetCompSubwindows(pParent); 495 CompClientWindowPtr ccw; 496 497 if (!csw) 498 return Success; 499 for (ccw = csw->clients; ccw; ccw = ccw->next) { 500 int ret = compRedirectWindow(clients[CLIENT_ID(ccw->id)], 501 pWin, ccw->update); 502 503 if (ret != Success) 504 return ret; 505 } 506 return Success; 507} 508 509/* 510 * Remove redirection information for one subwindow (during reparent) 511 */ 512 513int 514compUnredirectOneSubwindow(WindowPtr pParent, WindowPtr pWin) 515{ 516 CompSubwindowsPtr csw = GetCompSubwindows(pParent); 517 CompClientWindowPtr ccw; 518 519 if (!csw) 520 return Success; 521 for (ccw = csw->clients; ccw; ccw = ccw->next) { 522 int ret = compUnredirectWindow(clients[CLIENT_ID(ccw->id)], 523 pWin, ccw->update); 524 525 if (ret != Success) 526 return ret; 527 } 528 return Success; 529} 530 531static PixmapPtr 532compNewPixmap(WindowPtr pWin, int x, int y, int w, int h) 533{ 534 ScreenPtr pScreen = pWin->drawable.pScreen; 535 WindowPtr pParent = pWin->parent; 536 PixmapPtr pPixmap; 537 538 pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth, 539 CREATE_PIXMAP_USAGE_BACKING_PIXMAP); 540 541 if (!pPixmap) 542 return 0; 543 544 pPixmap->screen_x = x; 545 pPixmap->screen_y = y; 546 547 if (pParent->drawable.depth == pWin->drawable.depth) { 548 GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen); 549 550 if (pGC) { 551 ChangeGCVal val; 552 553 val.val = IncludeInferiors; 554 ChangeGC(NullClient, pGC, GCSubwindowMode, &val); 555 ValidateGC(&pPixmap->drawable, pGC); 556 (*pGC->ops->CopyArea) (&pParent->drawable, 557 &pPixmap->drawable, 558 pGC, 559 x - pParent->drawable.x, 560 y - pParent->drawable.y, w, h, 0, 0); 561 FreeScratchGC(pGC); 562 } 563 } 564 else { 565 PictFormatPtr pSrcFormat = PictureWindowFormat(pParent); 566 PictFormatPtr pDstFormat = PictureWindowFormat(pWin); 567 XID inferiors = IncludeInferiors; 568 int error; 569 570 PicturePtr pSrcPicture = CreatePicture(None, 571 &pParent->drawable, 572 pSrcFormat, 573 CPSubwindowMode, 574 &inferiors, 575 serverClient, &error); 576 577 PicturePtr pDstPicture = CreatePicture(None, 578 &pPixmap->drawable, 579 pDstFormat, 580 0, 0, 581 serverClient, &error); 582 583 if (pSrcPicture && pDstPicture) { 584 CompositePicture(PictOpSrc, 585 pSrcPicture, 586 NULL, 587 pDstPicture, 588 x - pParent->drawable.x, 589 y - pParent->drawable.y, 0, 0, 0, 0, w, h); 590 } 591 if (pSrcPicture) 592 FreePicture(pSrcPicture, 0); 593 if (pDstPicture) 594 FreePicture(pDstPicture, 0); 595 } 596 return pPixmap; 597} 598 599Bool 600compAllocPixmap(WindowPtr pWin) 601{ 602 int bw = (int) pWin->borderWidth; 603 int x = pWin->drawable.x - bw; 604 int y = pWin->drawable.y - bw; 605 int w = pWin->drawable.width + (bw << 1); 606 int h = pWin->drawable.height + (bw << 1); 607 PixmapPtr pPixmap = compNewPixmap(pWin, x, y, w, h); 608 CompWindowPtr cw = GetCompWindow(pWin); 609 Bool status; 610 611 if (!pPixmap) { 612 status = FALSE; 613 goto out; 614 } 615 if (cw->update == CompositeRedirectAutomatic) 616 pWin->redirectDraw = RedirectDrawAutomatic; 617 else 618 pWin->redirectDraw = RedirectDrawManual; 619 620 compSetPixmap(pWin, pPixmap, bw); 621 cw->oldx = COMP_ORIGIN_INVALID; 622 cw->oldy = COMP_ORIGIN_INVALID; 623 cw->damageRegistered = FALSE; 624 if (cw->update == CompositeRedirectAutomatic) { 625 DamageRegister(&pWin->drawable, cw->damage); 626 cw->damageRegistered = TRUE; 627 } 628 status = TRUE; 629 630out: 631 /* Make sure our borderClip is up to date */ 632 RegionUninit(&cw->borderClip); 633 RegionCopy(&cw->borderClip, &pWin->borderClip); 634 cw->borderClipX = pWin->drawable.x; 635 cw->borderClipY = pWin->drawable.y; 636 637 return status; 638} 639 640void 641compSetParentPixmap(WindowPtr pWin) 642{ 643 ScreenPtr pScreen = pWin->drawable.pScreen; 644 PixmapPtr pParentPixmap; 645 CompWindowPtr cw = GetCompWindow(pWin); 646 647 if (cw->damageRegistered) { 648 DamageUnregister(cw->damage); 649 cw->damageRegistered = FALSE; 650 DamageEmpty(cw->damage); 651 } 652 /* 653 * Move the parent-constrained border clip region back into 654 * the window so that ValidateTree will handle the unmap 655 * case correctly. Unmap adds the window borderClip to the 656 * parent exposed area; regions beyond the parent cause crashes 657 */ 658 RegionCopy(&pWin->borderClip, &cw->borderClip); 659 pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent); 660 pWin->redirectDraw = RedirectDrawNone; 661 compSetPixmap(pWin, pParentPixmap, pWin->borderWidth); 662} 663 664/* 665 * Make sure the pixmap is the right size and offset. Allocate a new 666 * pixmap to change size, adjust origin to change offset, leaving the 667 * old pixmap in cw->pOldPixmap so bits can be recovered 668 */ 669Bool 670compReallocPixmap(WindowPtr pWin, int draw_x, int draw_y, 671 unsigned int w, unsigned int h, int bw) 672{ 673 ScreenPtr pScreen = pWin->drawable.pScreen; 674 PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin); 675 PixmapPtr pNew; 676 CompWindowPtr cw = GetCompWindow(pWin); 677 int pix_x, pix_y; 678 int pix_w, pix_h; 679 680 assert(cw); 681 assert(pWin->redirectDraw != RedirectDrawNone); 682 cw->oldx = pOld->screen_x; 683 cw->oldy = pOld->screen_y; 684 pix_x = draw_x - bw; 685 pix_y = draw_y - bw; 686 pix_w = w + (bw << 1); 687 pix_h = h + (bw << 1); 688 if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height) { 689 pNew = compNewPixmap(pWin, pix_x, pix_y, pix_w, pix_h); 690 if (!pNew) 691 return FALSE; 692 cw->pOldPixmap = pOld; 693 compSetPixmap(pWin, pNew, bw); 694 } 695 else { 696 pNew = pOld; 697 cw->pOldPixmap = 0; 698 } 699 pNew->screen_x = pix_x; 700 pNew->screen_y = pix_y; 701 return TRUE; 702} 703