compwindow.c (25197B)
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 #ifdef PANORAMIX 51 #include "panoramiXsrv.h" 52 #endif 53 54 #ifdef COMPOSITE_DEBUG 55 static int 56 compCheckWindow(WindowPtr pWin, void *data) 57 { 58 ScreenPtr pScreen = pWin->drawable.pScreen; 59 PixmapPtr pWinPixmap = (*pScreen->GetWindowPixmap) (pWin); 60 PixmapPtr pParentPixmap = 61 pWin->parent ? (*pScreen->GetWindowPixmap) (pWin->parent) : 0; 62 PixmapPtr pScreenPixmap = (*pScreen->GetScreenPixmap) (pScreen); 63 64 if (!pWin->parent) { 65 assert(pWin->redirectDraw == RedirectDrawNone); 66 assert(pWinPixmap == pScreenPixmap); 67 } 68 else if (pWin->redirectDraw != RedirectDrawNone) { 69 assert(pWinPixmap != pParentPixmap); 70 assert(pWinPixmap != pScreenPixmap); 71 } 72 else { 73 assert(pWinPixmap == pParentPixmap); 74 } 75 76 assert(0 < pWinPixmap->refcnt) 77 assert(pWinPixmap->refcnt < 3); 78 79 assert(0 < pScreenPixmap->refcnt); 80 assert(pScreenPixmap->refcnt < 3); 81 82 if (pParentPixmap) { 83 assert(0 <= pParentPixmap->refcnt); 84 assert(pParentPixmap->refcnt < 3); 85 } 86 return WT_WALKCHILDREN; 87 } 88 89 void 90 compCheckTree(ScreenPtr pScreen) 91 { 92 WalkTree(pScreen, compCheckWindow, 0); 93 } 94 #endif 95 96 typedef struct _compPixmapVisit { 97 WindowPtr pWindow; 98 PixmapPtr pPixmap; 99 int bw; 100 } CompPixmapVisitRec, *CompPixmapVisitPtr; 101 102 static Bool 103 compRepaintBorder(ClientPtr pClient, void *closure) 104 { 105 WindowPtr pWindow; 106 int rc = 107 dixLookupWindow(&pWindow, (XID) (intptr_t) closure, pClient, 108 DixWriteAccess); 109 110 if (rc == Success) { 111 RegionRec exposed; 112 113 RegionNull(&exposed); 114 RegionSubtract(&exposed, &pWindow->borderClip, &pWindow->winSize); 115 pWindow->drawable.pScreen->PaintWindow(pWindow, &exposed, PW_BORDER); 116 RegionUninit(&exposed); 117 } 118 return TRUE; 119 } 120 121 static int 122 compSetPixmapVisitWindow(WindowPtr pWindow, void *data) 123 { 124 CompPixmapVisitPtr pVisit = (CompPixmapVisitPtr) data; 125 ScreenPtr pScreen = pWindow->drawable.pScreen; 126 127 if (pWindow != pVisit->pWindow && pWindow->redirectDraw != RedirectDrawNone) 128 return WT_DONTWALKCHILDREN; 129 (*pScreen->SetWindowPixmap) (pWindow, pVisit->pPixmap); 130 /* 131 * Recompute winSize and borderSize. This is duplicate effort 132 * when resizing pixmaps, but necessary when changing redirection. 133 * Might be nice to fix this. 134 */ 135 SetWinSize(pWindow); 136 SetBorderSize(pWindow); 137 if (pVisit->bw) 138 QueueWorkProc(compRepaintBorder, serverClient, 139 (void *) (intptr_t) pWindow->drawable.id); 140 return WT_WALKCHILDREN; 141 } 142 143 void 144 compSetPixmap(WindowPtr pWindow, PixmapPtr pPixmap, int bw) 145 { 146 CompPixmapVisitRec visitRec; 147 148 visitRec.pWindow = pWindow; 149 visitRec.pPixmap = pPixmap; 150 visitRec.bw = bw; 151 TraverseTree(pWindow, compSetPixmapVisitWindow, (void *) &visitRec); 152 compCheckTree(pWindow->drawable.pScreen); 153 } 154 155 Bool 156 compCheckRedirect(WindowPtr pWin) 157 { 158 CompWindowPtr cw = GetCompWindow(pWin); 159 CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); 160 Bool should; 161 162 should = pWin->realized && (pWin->drawable.class != InputOnly) && 163 (cw != NULL) && (pWin->parent != NULL); 164 165 /* Never redirect the overlay window */ 166 if (cs->pOverlayWin != NULL) { 167 if (pWin == cs->pOverlayWin) { 168 should = FALSE; 169 } 170 } 171 172 if (should != (pWin->redirectDraw != RedirectDrawNone)) { 173 if (should) 174 return compAllocPixmap(pWin); 175 else { 176 ScreenPtr pScreen = pWin->drawable.pScreen; 177 PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); 178 179 compSetParentPixmap(pWin); 180 compRestoreWindow(pWin, pPixmap); 181 (*pScreen->DestroyPixmap) (pPixmap); 182 } 183 } 184 else if (should) { 185 if (cw->update == CompositeRedirectAutomatic) 186 pWin->redirectDraw = RedirectDrawAutomatic; 187 else 188 pWin->redirectDraw = RedirectDrawManual; 189 } 190 return TRUE; 191 } 192 193 static int 194 updateOverlayWindow(ScreenPtr pScreen) 195 { 196 CompScreenPtr cs; 197 WindowPtr pWin; /* overlay window */ 198 XID vlist[2]; 199 int w = pScreen->width; 200 int h = pScreen->height; 201 202 #ifdef PANORAMIX 203 if (!noPanoramiXExtension) { 204 w = PanoramiXPixWidth; 205 h = PanoramiXPixHeight; 206 } 207 #endif 208 209 cs = GetCompScreen(pScreen); 210 if ((pWin = cs->pOverlayWin) != NULL) { 211 if ((pWin->drawable.width == w) && (pWin->drawable.height == h)) 212 return Success; 213 214 /* Let's resize the overlay window. */ 215 vlist[0] = w; 216 vlist[1] = h; 217 return ConfigureWindow(pWin, CWWidth | CWHeight, vlist, wClient(pWin)); 218 } 219 220 /* Let's be on the safe side and not assume an overlay window is 221 always allocated. */ 222 return Success; 223 } 224 225 Bool 226 compPositionWindow(WindowPtr pWin, int x, int y) 227 { 228 ScreenPtr pScreen = pWin->drawable.pScreen; 229 CompScreenPtr cs = GetCompScreen(pScreen); 230 Bool ret = TRUE; 231 232 pScreen->PositionWindow = cs->PositionWindow; 233 /* 234 * "Shouldn't need this as all possible places should be wrapped 235 * 236 compCheckRedirect (pWin); 237 */ 238 #ifdef COMPOSITE_DEBUG 239 if ((pWin->redirectDraw != RedirectDrawNone) != 240 (pWin->viewable && (GetCompWindow(pWin) != NULL))) 241 OsAbort(); 242 #endif 243 if (pWin->redirectDraw != RedirectDrawNone) { 244 PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); 245 int bw = wBorderWidth(pWin); 246 int nx = pWin->drawable.x - bw; 247 int ny = pWin->drawable.y - bw; 248 249 if (pPixmap->screen_x != nx || pPixmap->screen_y != ny) { 250 pPixmap->screen_x = nx; 251 pPixmap->screen_y = ny; 252 pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 253 } 254 } 255 256 if (!(*pScreen->PositionWindow) (pWin, x, y)) 257 ret = FALSE; 258 cs->PositionWindow = pScreen->PositionWindow; 259 pScreen->PositionWindow = compPositionWindow; 260 compCheckTree(pWin->drawable.pScreen); 261 if (updateOverlayWindow(pScreen) != Success) 262 ret = FALSE; 263 return ret; 264 } 265 266 Bool 267 compRealizeWindow(WindowPtr pWin) 268 { 269 ScreenPtr pScreen = pWin->drawable.pScreen; 270 CompScreenPtr cs = GetCompScreen(pScreen); 271 Bool ret = TRUE; 272 273 pScreen->RealizeWindow = cs->RealizeWindow; 274 compCheckRedirect(pWin); 275 if (!(*pScreen->RealizeWindow) (pWin)) 276 ret = FALSE; 277 cs->RealizeWindow = pScreen->RealizeWindow; 278 pScreen->RealizeWindow = compRealizeWindow; 279 compCheckTree(pWin->drawable.pScreen); 280 return ret; 281 } 282 283 Bool 284 compUnrealizeWindow(WindowPtr pWin) 285 { 286 ScreenPtr pScreen = pWin->drawable.pScreen; 287 CompScreenPtr cs = GetCompScreen(pScreen); 288 Bool ret = TRUE; 289 290 pScreen->UnrealizeWindow = cs->UnrealizeWindow; 291 compCheckRedirect(pWin); 292 if (!(*pScreen->UnrealizeWindow) (pWin)) 293 ret = FALSE; 294 cs->UnrealizeWindow = pScreen->UnrealizeWindow; 295 pScreen->UnrealizeWindow = compUnrealizeWindow; 296 compCheckTree(pWin->drawable.pScreen); 297 return ret; 298 } 299 300 /* 301 * Called after the borderClip for the window has settled down 302 * We use this to make sure our extra borderClip has the right origin 303 */ 304 305 void 306 compClipNotify(WindowPtr pWin, int dx, int dy) 307 { 308 ScreenPtr pScreen = pWin->drawable.pScreen; 309 CompScreenPtr cs = GetCompScreen(pScreen); 310 CompWindowPtr cw = GetCompWindow(pWin); 311 312 if (cw) { 313 if (cw->borderClipX != pWin->drawable.x || 314 cw->borderClipY != pWin->drawable.y) { 315 RegionTranslate(&cw->borderClip, 316 pWin->drawable.x - cw->borderClipX, 317 pWin->drawable.y - cw->borderClipY); 318 cw->borderClipX = pWin->drawable.x; 319 cw->borderClipY = pWin->drawable.y; 320 } 321 } 322 if (cs->ClipNotify) { 323 pScreen->ClipNotify = cs->ClipNotify; 324 (*pScreen->ClipNotify) (pWin, dx, dy); 325 cs->ClipNotify = pScreen->ClipNotify; 326 pScreen->ClipNotify = compClipNotify; 327 } 328 } 329 330 Bool 331 compIsAlternateVisual(ScreenPtr pScreen, XID visual) 332 { 333 CompScreenPtr cs = GetCompScreen(pScreen); 334 int i; 335 336 for (i = 0; cs && i < cs->numAlternateVisuals; i++) 337 if (cs->alternateVisuals[i] == visual) 338 return TRUE; 339 return FALSE; 340 } 341 342 static Bool 343 compIsImplicitRedirectException(ScreenPtr pScreen, 344 XID parentVisual, XID winVisual) 345 { 346 CompScreenPtr cs = GetCompScreen(pScreen); 347 int i; 348 349 for (i = 0; i < cs->numImplicitRedirectExceptions; i++) 350 if (cs->implicitRedirectExceptions[i].parentVisual == parentVisual && 351 cs->implicitRedirectExceptions[i].winVisual == winVisual) 352 return TRUE; 353 354 return FALSE; 355 } 356 357 static Bool 358 compImplicitRedirect(WindowPtr pWin, WindowPtr pParent) 359 { 360 if (pParent) { 361 ScreenPtr pScreen = pWin->drawable.pScreen; 362 XID winVisual = wVisual(pWin); 363 XID parentVisual = wVisual(pParent); 364 365 if (compIsImplicitRedirectException(pScreen, parentVisual, winVisual)) 366 return FALSE; 367 368 if (winVisual != parentVisual && 369 (compIsAlternateVisual(pScreen, winVisual) || 370 compIsAlternateVisual(pScreen, parentVisual))) 371 return TRUE; 372 } 373 return FALSE; 374 } 375 376 static void 377 compFreeOldPixmap(WindowPtr pWin) 378 { 379 ScreenPtr pScreen = pWin->drawable.pScreen; 380 381 if (pWin->redirectDraw != RedirectDrawNone) { 382 CompWindowPtr cw = GetCompWindow(pWin); 383 384 if (cw->pOldPixmap) { 385 (*pScreen->DestroyPixmap) (cw->pOldPixmap); 386 cw->pOldPixmap = NullPixmap; 387 } 388 } 389 } 390 391 void 392 compMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) 393 { 394 ScreenPtr pScreen = pWin->drawable.pScreen; 395 CompScreenPtr cs = GetCompScreen(pScreen); 396 397 pScreen->MoveWindow = cs->MoveWindow; 398 (*pScreen->MoveWindow) (pWin, x, y, pSib, kind); 399 cs->MoveWindow = pScreen->MoveWindow; 400 pScreen->MoveWindow = compMoveWindow; 401 402 compFreeOldPixmap(pWin); 403 compCheckTree(pScreen); 404 } 405 406 void 407 compResizeWindow(WindowPtr pWin, int x, int y, 408 unsigned int w, unsigned int h, WindowPtr pSib) 409 { 410 ScreenPtr pScreen = pWin->drawable.pScreen; 411 CompScreenPtr cs = GetCompScreen(pScreen); 412 413 pScreen->ResizeWindow = cs->ResizeWindow; 414 (*pScreen->ResizeWindow) (pWin, x, y, w, h, pSib); 415 cs->ResizeWindow = pScreen->ResizeWindow; 416 pScreen->ResizeWindow = compResizeWindow; 417 418 compFreeOldPixmap(pWin); 419 compCheckTree(pWin->drawable.pScreen); 420 } 421 422 void 423 compChangeBorderWidth(WindowPtr pWin, unsigned int bw) 424 { 425 ScreenPtr pScreen = pWin->drawable.pScreen; 426 CompScreenPtr cs = GetCompScreen(pScreen); 427 428 pScreen->ChangeBorderWidth = cs->ChangeBorderWidth; 429 (*pScreen->ChangeBorderWidth) (pWin, bw); 430 cs->ChangeBorderWidth = pScreen->ChangeBorderWidth; 431 pScreen->ChangeBorderWidth = compChangeBorderWidth; 432 433 compFreeOldPixmap(pWin); 434 compCheckTree(pWin->drawable.pScreen); 435 } 436 437 void 438 compReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) 439 { 440 ScreenPtr pScreen = pWin->drawable.pScreen; 441 CompScreenPtr cs = GetCompScreen(pScreen); 442 CompWindowPtr cw; 443 444 pScreen->ReparentWindow = cs->ReparentWindow; 445 /* 446 * Remove any implicit redirect due to synthesized visual 447 */ 448 if (compImplicitRedirect(pWin, pPriorParent)) 449 compUnredirectWindow(serverClient, pWin, CompositeRedirectAutomatic); 450 /* 451 * Handle subwindows redirection 452 */ 453 compUnredirectOneSubwindow(pPriorParent, pWin); 454 compRedirectOneSubwindow(pWin->parent, pWin); 455 /* 456 * Add any implicit redirect due to synthesized visual 457 */ 458 if (compImplicitRedirect(pWin, pWin->parent)) 459 compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic); 460 461 /* 462 * Allocate any necessary redirect pixmap 463 * (this actually should never be true; pWin is always unmapped) 464 */ 465 compCheckRedirect(pWin); 466 467 /* 468 * Reset pixmap pointers as appropriate 469 */ 470 if (pWin->parent && pWin->redirectDraw == RedirectDrawNone) 471 compSetPixmap(pWin, (*pScreen->GetWindowPixmap) (pWin->parent), 472 pWin->borderWidth); 473 /* 474 * Call down to next function 475 */ 476 if (pScreen->ReparentWindow) 477 (*pScreen->ReparentWindow) (pWin, pPriorParent); 478 cs->ReparentWindow = pScreen->ReparentWindow; 479 pScreen->ReparentWindow = compReparentWindow; 480 481 cw = GetCompWindow(pWin); 482 if (pWin->damagedDescendants || (cw && cw->damaged)) 483 compMarkAncestors(pWin); 484 485 compCheckTree(pWin->drawable.pScreen); 486 } 487 488 void 489 compCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 490 { 491 ScreenPtr pScreen = pWin->drawable.pScreen; 492 CompScreenPtr cs = GetCompScreen(pScreen); 493 int dx = 0, dy = 0; 494 495 if (pWin->redirectDraw != RedirectDrawNone) { 496 PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); 497 CompWindowPtr cw = GetCompWindow(pWin); 498 499 assert(cw->oldx != COMP_ORIGIN_INVALID); 500 assert(cw->oldy != COMP_ORIGIN_INVALID); 501 if (cw->pOldPixmap) { 502 /* 503 * Ok, the old bits are available in pOldPixmap and 504 * need to be copied to pNewPixmap. 505 */ 506 RegionRec rgnDst; 507 GCPtr pGC; 508 509 dx = ptOldOrg.x - pWin->drawable.x; 510 dy = ptOldOrg.y - pWin->drawable.y; 511 RegionTranslate(prgnSrc, -dx, -dy); 512 513 RegionNull(&rgnDst); 514 515 RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); 516 517 RegionTranslate(&rgnDst, -pPixmap->screen_x, -pPixmap->screen_y); 518 519 dx = dx + pPixmap->screen_x - cw->oldx; 520 dy = dy + pPixmap->screen_y - cw->oldy; 521 pGC = GetScratchGC(pPixmap->drawable.depth, pScreen); 522 if (pGC) { 523 BoxPtr pBox = RegionRects(&rgnDst); 524 int nBox = RegionNumRects(&rgnDst); 525 526 ValidateGC(&pPixmap->drawable, pGC); 527 while (nBox--) { 528 (void) (*pGC->ops->CopyArea) (&cw->pOldPixmap->drawable, 529 &pPixmap->drawable, 530 pGC, 531 pBox->x1 + dx, pBox->y1 + dy, 532 pBox->x2 - pBox->x1, 533 pBox->y2 - pBox->y1, 534 pBox->x1, pBox->y1); 535 pBox++; 536 } 537 FreeScratchGC(pGC); 538 } 539 RegionUninit(&rgnDst); 540 return; 541 } 542 dx = pPixmap->screen_x - cw->oldx; 543 dy = pPixmap->screen_y - cw->oldy; 544 ptOldOrg.x += dx; 545 ptOldOrg.y += dy; 546 } 547 548 pScreen->CopyWindow = cs->CopyWindow; 549 if (ptOldOrg.x != pWin->drawable.x || ptOldOrg.y != pWin->drawable.y) { 550 if (dx || dy) 551 RegionTranslate(prgnSrc, dx, dy); 552 (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); 553 if (dx || dy) 554 RegionTranslate(prgnSrc, -dx, -dy); 555 } 556 else { 557 ptOldOrg.x -= dx; 558 ptOldOrg.y -= dy; 559 RegionTranslate(prgnSrc, 560 pWin->drawable.x - ptOldOrg.x, 561 pWin->drawable.y - ptOldOrg.y); 562 DamageDamageRegion(&pWin->drawable, prgnSrc); 563 } 564 cs->CopyWindow = pScreen->CopyWindow; 565 pScreen->CopyWindow = compCopyWindow; 566 compCheckTree(pWin->drawable.pScreen); 567 } 568 569 Bool 570 compCreateWindow(WindowPtr pWin) 571 { 572 ScreenPtr pScreen = pWin->drawable.pScreen; 573 CompScreenPtr cs = GetCompScreen(pScreen); 574 Bool ret; 575 576 pScreen->CreateWindow = cs->CreateWindow; 577 ret = (*pScreen->CreateWindow) (pWin); 578 if (pWin->parent && ret) { 579 CompSubwindowsPtr csw = GetCompSubwindows(pWin->parent); 580 CompClientWindowPtr ccw; 581 PixmapPtr parent_pixmap = (*pScreen->GetWindowPixmap)(pWin->parent); 582 PixmapPtr window_pixmap = (*pScreen->GetWindowPixmap)(pWin); 583 584 if (window_pixmap != parent_pixmap) 585 (*pScreen->SetWindowPixmap) (pWin, parent_pixmap); 586 if (csw) 587 for (ccw = csw->clients; ccw; ccw = ccw->next) 588 compRedirectWindow(clients[CLIENT_ID(ccw->id)], 589 pWin, ccw->update); 590 if (compImplicitRedirect(pWin, pWin->parent)) 591 compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic); 592 } 593 cs->CreateWindow = pScreen->CreateWindow; 594 pScreen->CreateWindow = compCreateWindow; 595 compCheckTree(pWin->drawable.pScreen); 596 return ret; 597 } 598 599 Bool 600 compDestroyWindow(WindowPtr pWin) 601 { 602 ScreenPtr pScreen = pWin->drawable.pScreen; 603 CompScreenPtr cs = GetCompScreen(pScreen); 604 CompWindowPtr cw; 605 CompSubwindowsPtr csw; 606 Bool ret; 607 608 pScreen->DestroyWindow = cs->DestroyWindow; 609 while ((cw = GetCompWindow(pWin))) 610 FreeResource(cw->clients->id, RT_NONE); 611 while ((csw = GetCompSubwindows(pWin))) 612 FreeResource(csw->clients->id, RT_NONE); 613 614 if (pWin->redirectDraw != RedirectDrawNone) { 615 PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); 616 617 compSetParentPixmap(pWin); 618 (*pScreen->DestroyPixmap) (pPixmap); 619 } 620 ret = (*pScreen->DestroyWindow) (pWin); 621 cs->DestroyWindow = pScreen->DestroyWindow; 622 pScreen->DestroyWindow = compDestroyWindow; 623 /* compCheckTree (pWin->drawable.pScreen); can't check -- tree isn't good*/ 624 return ret; 625 } 626 627 void 628 compSetRedirectBorderClip(WindowPtr pWin, RegionPtr pRegion) 629 { 630 CompWindowPtr cw = GetCompWindow(pWin); 631 RegionRec damage; 632 633 RegionNull(&damage); 634 /* 635 * Align old border clip with new border clip 636 */ 637 RegionTranslate(&cw->borderClip, 638 pWin->drawable.x - cw->borderClipX, 639 pWin->drawable.y - cw->borderClipY); 640 /* 641 * Compute newly visible portion of window for repaint 642 */ 643 RegionSubtract(&damage, pRegion, &cw->borderClip); 644 /* 645 * Report that as damaged so it will be redrawn 646 */ 647 DamageDamageRegion(&pWin->drawable, &damage); 648 RegionUninit(&damage); 649 /* 650 * Save the new border clip region 651 */ 652 RegionCopy(&cw->borderClip, pRegion); 653 cw->borderClipX = pWin->drawable.x; 654 cw->borderClipY = pWin->drawable.y; 655 } 656 657 RegionPtr 658 compGetRedirectBorderClip(WindowPtr pWin) 659 { 660 CompWindowPtr cw = GetCompWindow(pWin); 661 662 return &cw->borderClip; 663 } 664 665 static void 666 compWindowUpdateAutomatic(WindowPtr pWin) 667 { 668 CompWindowPtr cw = GetCompWindow(pWin); 669 ScreenPtr pScreen = pWin->drawable.pScreen; 670 WindowPtr pParent = pWin->parent; 671 PixmapPtr pSrcPixmap = (*pScreen->GetWindowPixmap) (pWin); 672 PictFormatPtr pSrcFormat = PictureWindowFormat(pWin); 673 PictFormatPtr pDstFormat = PictureWindowFormat(pWin->parent); 674 int error; 675 RegionPtr pRegion = DamageRegion(cw->damage); 676 PicturePtr pSrcPicture = CreatePicture(0, &pSrcPixmap->drawable, 677 pSrcFormat, 678 0, 0, 679 serverClient, 680 &error); 681 XID subwindowMode = IncludeInferiors; 682 PicturePtr pDstPicture = CreatePicture(0, &pParent->drawable, 683 pDstFormat, 684 CPSubwindowMode, 685 &subwindowMode, 686 serverClient, 687 &error); 688 689 /* 690 * First move the region from window to screen coordinates 691 */ 692 RegionTranslate(pRegion, pWin->drawable.x, pWin->drawable.y); 693 694 /* 695 * Clip against the "real" border clip 696 */ 697 RegionIntersect(pRegion, pRegion, &cw->borderClip); 698 699 /* 700 * Now translate from screen to dest coordinates 701 */ 702 RegionTranslate(pRegion, -pParent->drawable.x, -pParent->drawable.y); 703 704 /* 705 * Clip the picture 706 */ 707 SetPictureClipRegion(pDstPicture, 0, 0, pRegion); 708 709 /* 710 * And paint 711 */ 712 CompositePicture(PictOpSrc, pSrcPicture, 0, pDstPicture, 713 0, 0, /* src_x, src_y */ 714 0, 0, /* msk_x, msk_y */ 715 pSrcPixmap->screen_x - pParent->drawable.x, 716 pSrcPixmap->screen_y - pParent->drawable.y, 717 pSrcPixmap->drawable.width, pSrcPixmap->drawable.height); 718 FreePicture(pSrcPicture, 0); 719 FreePicture(pDstPicture, 0); 720 /* 721 * Empty the damage region. This has the nice effect of 722 * rendering the translations above harmless 723 */ 724 DamageEmpty(cw->damage); 725 } 726 727 static void 728 compPaintWindowToParent(WindowPtr pWin) 729 { 730 compPaintChildrenToWindow(pWin); 731 732 if (pWin->redirectDraw != RedirectDrawNone) { 733 CompWindowPtr cw = GetCompWindow(pWin); 734 735 if (cw->damaged) { 736 compWindowUpdateAutomatic(pWin); 737 cw->damaged = FALSE; 738 } 739 } 740 } 741 742 void 743 compPaintChildrenToWindow(WindowPtr pWin) 744 { 745 WindowPtr pChild; 746 747 if (!pWin->damagedDescendants) 748 return; 749 750 for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) 751 compPaintWindowToParent(pChild); 752 753 pWin->damagedDescendants = FALSE; 754 } 755 756 WindowPtr 757 CompositeRealChildHead(WindowPtr pWin) 758 { 759 WindowPtr pChild, pChildBefore; 760 CompScreenPtr cs; 761 762 if (!pWin->parent && 763 (screenIsSaved == SCREEN_SAVER_ON) && 764 (HasSaverWindow(pWin->drawable.pScreen))) { 765 766 /* First child is the screen saver; see if next child is the overlay */ 767 pChildBefore = pWin->firstChild; 768 pChild = pChildBefore->nextSib; 769 770 } 771 else { 772 pChildBefore = NullWindow; 773 pChild = pWin->firstChild; 774 } 775 776 if (!pChild) { 777 return NullWindow; 778 } 779 780 cs = GetCompScreen(pWin->drawable.pScreen); 781 if (pChild == cs->pOverlayWin) { 782 return pChild; 783 } 784 else { 785 return pChildBefore; 786 } 787 } 788 789 int 790 compConfigNotify(WindowPtr pWin, int x, int y, int w, int h, 791 int bw, WindowPtr pSib) 792 { 793 ScreenPtr pScreen = pWin->drawable.pScreen; 794 CompScreenPtr cs = GetCompScreen(pScreen); 795 Bool ret = 0; 796 WindowPtr pParent = pWin->parent; 797 int draw_x, draw_y; 798 Bool alloc_ret; 799 800 if (cs->ConfigNotify) { 801 pScreen->ConfigNotify = cs->ConfigNotify; 802 ret = (*pScreen->ConfigNotify) (pWin, x, y, w, h, bw, pSib); 803 cs->ConfigNotify = pScreen->ConfigNotify; 804 pScreen->ConfigNotify = compConfigNotify; 805 806 if (ret) 807 return ret; 808 } 809 810 if (pWin->redirectDraw == RedirectDrawNone) 811 return Success; 812 813 compCheckTree(pScreen); 814 815 draw_x = pParent->drawable.x + x + bw; 816 draw_y = pParent->drawable.y + y + bw; 817 alloc_ret = compReallocPixmap(pWin, draw_x, draw_y, w, h, bw); 818 819 if (alloc_ret == FALSE) 820 return BadAlloc; 821 return Success; 822 }