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