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