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