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