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