1 2#ifdef HAVE_DIX_CONFIG_H 3#include <dix-config.h> 4#endif 5 6#include <X11/X.h> 7#include "scrnintstr.h" 8#include <X11/extensions/shapeproto.h> 9#include "validate.h" 10#include "windowstr.h" 11#include "mi.h" 12#include "gcstruct.h" 13#include "regionstr.h" 14#include "privates.h" 15#include "mivalidate.h" 16#include "mioverlay.h" 17#include "migc.h" 18 19#include "globals.h" 20 21typedef struct { 22 RegionRec exposed; 23 RegionRec borderExposed; 24 RegionPtr borderVisible; 25 DDXPointRec oldAbsCorner; 26} miOverlayValDataRec, *miOverlayValDataPtr; 27 28typedef struct _TreeRec { 29 WindowPtr pWin; 30 struct _TreeRec *parent; 31 struct _TreeRec *firstChild; 32 struct _TreeRec *lastChild; 33 struct _TreeRec *prevSib; 34 struct _TreeRec *nextSib; 35 RegionRec borderClip; 36 RegionRec clipList; 37 unsigned visibility; 38 miOverlayValDataPtr valdata; 39} miOverlayTreeRec, *miOverlayTreePtr; 40 41typedef struct { 42 miOverlayTreePtr tree; 43} miOverlayWindowRec, *miOverlayWindowPtr; 44 45typedef struct { 46 CloseScreenProcPtr CloseScreen; 47 CreateWindowProcPtr CreateWindow; 48 DestroyWindowProcPtr DestroyWindow; 49 UnrealizeWindowProcPtr UnrealizeWindow; 50 RealizeWindowProcPtr RealizeWindow; 51 miOverlayTransFunc MakeTransparent; 52 miOverlayInOverlayFunc InOverlay; 53 Bool underlayMarked; 54 Bool copyUnderlay; 55} miOverlayScreenRec, *miOverlayScreenPtr; 56 57static DevPrivateKeyRec miOverlayWindowKeyRec; 58 59#define miOverlayWindowKey (&miOverlayWindowKeyRec) 60static DevPrivateKeyRec miOverlayScreenKeyRec; 61 62#define miOverlayScreenKey (&miOverlayScreenKeyRec) 63 64static void RebuildTree(WindowPtr); 65static Bool HasUnderlayChildren(WindowPtr); 66static void MarkUnderlayWindow(WindowPtr); 67static Bool CollectUnderlayChildrenRegions(WindowPtr, RegionPtr); 68 69static Bool miOverlayCloseScreen(ScreenPtr); 70static Bool miOverlayCreateWindow(WindowPtr); 71static Bool miOverlayDestroyWindow(WindowPtr); 72static Bool miOverlayUnrealizeWindow(WindowPtr); 73static Bool miOverlayRealizeWindow(WindowPtr); 74static void miOverlayMarkWindow(WindowPtr); 75static void miOverlayReparentWindow(WindowPtr, WindowPtr); 76static void miOverlayRestackWindow(WindowPtr, WindowPtr); 77static Bool miOverlayMarkOverlappedWindows(WindowPtr, WindowPtr, WindowPtr *); 78static void miOverlayMarkUnrealizedWindow(WindowPtr, WindowPtr, Bool); 79static int miOverlayValidateTree(WindowPtr, WindowPtr, VTKind); 80static void miOverlayHandleExposures(WindowPtr); 81static void miOverlayMoveWindow(WindowPtr, int, int, WindowPtr, VTKind); 82static void miOverlayWindowExposures(WindowPtr, RegionPtr); 83static void miOverlayResizeWindow(WindowPtr, int, int, unsigned int, 84 unsigned int, WindowPtr); 85static void miOverlayClearToBackground(WindowPtr, int, int, int, int, Bool); 86 87static void miOverlaySetShape(WindowPtr, int); 88static void miOverlayChangeBorderWidth(WindowPtr, unsigned int); 89 90#define MIOVERLAY_GET_SCREEN_PRIVATE(pScreen) ((miOverlayScreenPtr) \ 91 dixLookupPrivate(&(pScreen)->devPrivates, miOverlayScreenKey)) 92#define MIOVERLAY_GET_WINDOW_PRIVATE(pWin) ((miOverlayWindowPtr) \ 93 dixLookupPrivate(&(pWin)->devPrivates, miOverlayWindowKey)) 94#define MIOVERLAY_GET_WINDOW_TREE(pWin) \ 95 (MIOVERLAY_GET_WINDOW_PRIVATE(pWin)->tree) 96 97#define IN_UNDERLAY(w) MIOVERLAY_GET_WINDOW_TREE(w) 98#define IN_OVERLAY(w) !MIOVERLAY_GET_WINDOW_TREE(w) 99 100#define MARK_OVERLAY(w) miMarkWindow(w) 101#define MARK_UNDERLAY(w) MarkUnderlayWindow(w) 102 103#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \ 104 HasBorder(w) && \ 105 (w)->backgroundState == ParentRelative) 106 107Bool 108miInitOverlay(ScreenPtr pScreen, 109 miOverlayInOverlayFunc inOverlayFunc, 110 miOverlayTransFunc transFunc) 111{ 112 miOverlayScreenPtr pScreenPriv; 113 114 if (!inOverlayFunc || !transFunc) 115 return FALSE; 116 117 if (!dixRegisterPrivateKey 118 (&miOverlayWindowKeyRec, PRIVATE_WINDOW, sizeof(miOverlayWindowRec))) 119 return FALSE; 120 121 if (!dixRegisterPrivateKey(&miOverlayScreenKeyRec, PRIVATE_SCREEN, 0)) 122 return FALSE; 123 124 if (!(pScreenPriv = malloc(sizeof(miOverlayScreenRec)))) 125 return FALSE; 126 127 dixSetPrivate(&pScreen->devPrivates, miOverlayScreenKey, pScreenPriv); 128 129 pScreenPriv->InOverlay = inOverlayFunc; 130 pScreenPriv->MakeTransparent = transFunc; 131 pScreenPriv->underlayMarked = FALSE; 132 133 pScreenPriv->CloseScreen = pScreen->CloseScreen; 134 pScreenPriv->CreateWindow = pScreen->CreateWindow; 135 pScreenPriv->DestroyWindow = pScreen->DestroyWindow; 136 pScreenPriv->UnrealizeWindow = pScreen->UnrealizeWindow; 137 pScreenPriv->RealizeWindow = pScreen->RealizeWindow; 138 139 pScreen->CloseScreen = miOverlayCloseScreen; 140 pScreen->CreateWindow = miOverlayCreateWindow; 141 pScreen->DestroyWindow = miOverlayDestroyWindow; 142 pScreen->UnrealizeWindow = miOverlayUnrealizeWindow; 143 pScreen->RealizeWindow = miOverlayRealizeWindow; 144 145 pScreen->ReparentWindow = miOverlayReparentWindow; 146 pScreen->RestackWindow = miOverlayRestackWindow; 147 pScreen->MarkOverlappedWindows = miOverlayMarkOverlappedWindows; 148 pScreen->MarkUnrealizedWindow = miOverlayMarkUnrealizedWindow; 149 pScreen->ValidateTree = miOverlayValidateTree; 150 pScreen->HandleExposures = miOverlayHandleExposures; 151 pScreen->MoveWindow = miOverlayMoveWindow; 152 pScreen->WindowExposures = miOverlayWindowExposures; 153 pScreen->ResizeWindow = miOverlayResizeWindow; 154 pScreen->MarkWindow = miOverlayMarkWindow; 155 pScreen->ClearToBackground = miOverlayClearToBackground; 156 pScreen->SetShape = miOverlaySetShape; 157 pScreen->ChangeBorderWidth = miOverlayChangeBorderWidth; 158 159 return TRUE; 160} 161 162static Bool 163miOverlayCloseScreen(ScreenPtr pScreen) 164{ 165 miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); 166 167 pScreen->CloseScreen = pScreenPriv->CloseScreen; 168 pScreen->CreateWindow = pScreenPriv->CreateWindow; 169 pScreen->DestroyWindow = pScreenPriv->DestroyWindow; 170 pScreen->UnrealizeWindow = pScreenPriv->UnrealizeWindow; 171 pScreen->RealizeWindow = pScreenPriv->RealizeWindow; 172 173 free(pScreenPriv); 174 175 return (*pScreen->CloseScreen) (pScreen); 176} 177 178static Bool 179miOverlayCreateWindow(WindowPtr pWin) 180{ 181 ScreenPtr pScreen = pWin->drawable.pScreen; 182 miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); 183 miOverlayWindowPtr pWinPriv = MIOVERLAY_GET_WINDOW_PRIVATE(pWin); 184 miOverlayTreePtr pTree = NULL; 185 Bool result = TRUE; 186 187 pWinPriv->tree = NULL; 188 189 if (!pWin->parent || !((*pScreenPriv->InOverlay) (pWin))) { 190 if (!(pTree = (miOverlayTreePtr) calloc(1, sizeof(miOverlayTreeRec)))) 191 return FALSE; 192 } 193 194 if (pScreenPriv->CreateWindow) { 195 pScreen->CreateWindow = pScreenPriv->CreateWindow; 196 result = (*pScreen->CreateWindow) (pWin); 197 pScreen->CreateWindow = miOverlayCreateWindow; 198 } 199 200 if (pTree) { 201 if (result) { 202 pTree->pWin = pWin; 203 pTree->visibility = VisibilityNotViewable; 204 pWinPriv->tree = pTree; 205 if (pWin->parent) { 206 RegionNull(&(pTree->borderClip)); 207 RegionNull(&(pTree->clipList)); 208 RebuildTree(pWin); 209 } 210 else { 211 BoxRec fullBox; 212 213 fullBox.x1 = 0; 214 fullBox.y1 = 0; 215 fullBox.x2 = pScreen->width; 216 fullBox.y2 = pScreen->height; 217 RegionInit(&(pTree->borderClip), &fullBox, 1); 218 RegionInit(&(pTree->clipList), &fullBox, 1); 219 } 220 } 221 else 222 free(pTree); 223 } 224 225 return TRUE; 226} 227 228static Bool 229miOverlayDestroyWindow(WindowPtr pWin) 230{ 231 ScreenPtr pScreen = pWin->drawable.pScreen; 232 miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); 233 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); 234 Bool result = TRUE; 235 236 if (pTree) { 237 if (pTree->prevSib) 238 pTree->prevSib->nextSib = pTree->nextSib; 239 else if (pTree->parent) 240 pTree->parent->firstChild = pTree->nextSib; 241 242 if (pTree->nextSib) 243 pTree->nextSib->prevSib = pTree->prevSib; 244 else if (pTree->parent) 245 pTree->parent->lastChild = pTree->prevSib; 246 247 RegionUninit(&(pTree->borderClip)); 248 RegionUninit(&(pTree->clipList)); 249 free(pTree); 250 } 251 252 if (pScreenPriv->DestroyWindow) { 253 pScreen->DestroyWindow = pScreenPriv->DestroyWindow; 254 result = (*pScreen->DestroyWindow) (pWin); 255 pScreen->DestroyWindow = miOverlayDestroyWindow; 256 } 257 258 return result; 259} 260 261static Bool 262miOverlayUnrealizeWindow(WindowPtr pWin) 263{ 264 ScreenPtr pScreen = pWin->drawable.pScreen; 265 miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); 266 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); 267 Bool result = TRUE; 268 269 if (pTree) 270 pTree->visibility = VisibilityNotViewable; 271 272 if (pScreenPriv->UnrealizeWindow) { 273 pScreen->UnrealizeWindow = pScreenPriv->UnrealizeWindow; 274 result = (*pScreen->UnrealizeWindow) (pWin); 275 pScreen->UnrealizeWindow = miOverlayUnrealizeWindow; 276 } 277 278 return result; 279} 280 281static Bool 282miOverlayRealizeWindow(WindowPtr pWin) 283{ 284 ScreenPtr pScreen = pWin->drawable.pScreen; 285 miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); 286 Bool result = TRUE; 287 288 if (pScreenPriv->RealizeWindow) { 289 pScreen->RealizeWindow = pScreenPriv->RealizeWindow; 290 result = (*pScreen->RealizeWindow) (pWin); 291 pScreen->RealizeWindow = miOverlayRealizeWindow; 292 } 293 294 /* we only need to catch the root window realization */ 295 296 if (result && !pWin->parent && !((*pScreenPriv->InOverlay) (pWin))) { 297 BoxRec box; 298 299 box.x1 = box.y1 = 0; 300 box.x2 = pWin->drawable.width; 301 box.y2 = pWin->drawable.height; 302 (*pScreenPriv->MakeTransparent) (pScreen, 1, &box); 303 } 304 305 return result; 306} 307 308static void 309miOverlayReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) 310{ 311 if (IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)) { 312 /* This could probably be more optimal */ 313 RebuildTree(pWin->drawable.pScreen->root->firstChild); 314 } 315} 316 317static void 318miOverlayRestackWindow(WindowPtr pWin, WindowPtr oldNextSib) 319{ 320 if (IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)) { 321 /* This could probably be more optimal */ 322 RebuildTree(pWin); 323 } 324} 325 326static Bool 327miOverlayMarkOverlappedWindows(WindowPtr pWin, 328 WindowPtr pFirst, WindowPtr *pLayerWin) 329{ 330 WindowPtr pChild, pLast; 331 Bool overMarked, underMarked, doUnderlay, markAll; 332 miOverlayTreePtr pTree = NULL, tLast, tChild; 333 BoxPtr box; 334 335 overMarked = underMarked = markAll = FALSE; 336 337 if (pLayerWin) 338 *pLayerWin = pWin; /* hah! */ 339 340 doUnderlay = (IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)); 341 342 box = RegionExtents(&pWin->borderSize); 343 344 if ((pChild = pFirst)) { 345 pLast = pChild->parent->lastChild; 346 while (1) { 347 if (pChild == pWin) 348 markAll = TRUE; 349 350 if (doUnderlay && IN_UNDERLAY(pChild)) 351 pTree = MIOVERLAY_GET_WINDOW_TREE(pChild); 352 353 if (pChild->viewable) { 354 if (RegionBroken(&pChild->winSize)) 355 SetWinSize(pChild); 356 if (RegionBroken(&pChild->borderSize)) 357 SetBorderSize(pChild); 358 359 if (markAll || RegionContainsRect(&pChild->borderSize, box)) { 360 MARK_OVERLAY(pChild); 361 overMarked = TRUE; 362 if (doUnderlay && IN_UNDERLAY(pChild)) { 363 MARK_UNDERLAY(pChild); 364 underMarked = TRUE; 365 } 366 if (pChild->firstChild) { 367 pChild = pChild->firstChild; 368 continue; 369 } 370 } 371 } 372 while (!pChild->nextSib && (pChild != pLast)) { 373 pChild = pChild->parent; 374 if (doUnderlay && IN_UNDERLAY(pChild)) 375 pTree = MIOVERLAY_GET_WINDOW_TREE(pChild); 376 } 377 378 if (pChild == pWin) 379 markAll = FALSE; 380 381 if (pChild == pLast) 382 break; 383 384 pChild = pChild->nextSib; 385 } 386 if (overMarked) 387 MARK_OVERLAY(pWin->parent); 388 } 389 390 if (doUnderlay && !pTree) { 391 if (!(pTree = MIOVERLAY_GET_WINDOW_TREE(pWin))) { 392 pChild = pWin->lastChild; 393 while (1) { 394 if ((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) 395 break; 396 397 if (pChild->lastChild) { 398 pChild = pChild->lastChild; 399 continue; 400 } 401 402 while (!pChild->prevSib) 403 pChild = pChild->parent; 404 405 pChild = pChild->prevSib; 406 } 407 } 408 } 409 410 if (pTree && pTree->nextSib) { 411 tChild = pTree->parent->lastChild; 412 tLast = pTree->nextSib; 413 414 while (1) { 415 if (tChild->pWin->viewable) { 416 if (RegionBroken(&tChild->pWin->winSize)) 417 SetWinSize(tChild->pWin); 418 if (RegionBroken(&tChild->pWin->borderSize)) 419 SetBorderSize(tChild->pWin); 420 421 if (RegionContainsRect(&(tChild->pWin->borderSize), box)) { 422 MARK_UNDERLAY(tChild->pWin); 423 underMarked = TRUE; 424 } 425 } 426 427 if (tChild->lastChild) { 428 tChild = tChild->lastChild; 429 continue; 430 } 431 432 while (!tChild->prevSib && (tChild != tLast)) 433 tChild = tChild->parent; 434 435 if (tChild == tLast) 436 break; 437 438 tChild = tChild->prevSib; 439 } 440 } 441 442 if (underMarked) { 443 ScreenPtr pScreen = pWin->drawable.pScreen; 444 445 MARK_UNDERLAY(pTree->parent->pWin); 446 MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->underlayMarked = TRUE; 447 } 448 449 return underMarked || overMarked; 450} 451 452static void 453miOverlayComputeClips(WindowPtr pParent, 454 RegionPtr universe, VTKind kind, RegionPtr exposed) 455{ 456 ScreenPtr pScreen = pParent->drawable.pScreen; 457 int oldVis, newVis, dx, dy; 458 BoxRec borderSize; 459 RegionPtr borderVisible; 460 RegionRec childUniverse, childUnion; 461 miOverlayTreePtr tParent = MIOVERLAY_GET_WINDOW_TREE(pParent); 462 miOverlayTreePtr tChild; 463 Bool overlap; 464 465 borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent); 466 borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent); 467 dx = (int) pParent->drawable.x + (int) pParent->drawable.width + 468 wBorderWidth(pParent); 469 if (dx > 32767) 470 dx = 32767; 471 borderSize.x2 = dx; 472 dy = (int) pParent->drawable.y + (int) pParent->drawable.height + 473 wBorderWidth(pParent); 474 if (dy > 32767) 475 dy = 32767; 476 borderSize.y2 = dy; 477 478 oldVis = tParent->visibility; 479 switch (RegionContainsRect(universe, &borderSize)) { 480 case rgnIN: 481 newVis = VisibilityUnobscured; 482 break; 483 case rgnPART: 484 newVis = VisibilityPartiallyObscured; 485 { 486 RegionPtr pBounding; 487 488 if ((pBounding = wBoundingShape(pParent))) { 489 switch (miShapedWindowIn(universe, pBounding, 490 &borderSize, 491 pParent->drawable.x, 492 pParent->drawable.y)) { 493 case rgnIN: 494 newVis = VisibilityUnobscured; 495 break; 496 case rgnOUT: 497 newVis = VisibilityFullyObscured; 498 break; 499 } 500 } 501 } 502 break; 503 default: 504 newVis = VisibilityFullyObscured; 505 break; 506 } 507 tParent->visibility = newVis; 508 509 dx = pParent->drawable.x - tParent->valdata->oldAbsCorner.x; 510 dy = pParent->drawable.y - tParent->valdata->oldAbsCorner.y; 511 512 switch (kind) { 513 case VTMap: 514 case VTStack: 515 case VTUnmap: 516 break; 517 case VTMove: 518 if ((oldVis == newVis) && 519 ((oldVis == VisibilityFullyObscured) || 520 (oldVis == VisibilityUnobscured))) { 521 tChild = tParent; 522 while (1) { 523 if (tChild->pWin->viewable) { 524 if (tChild->visibility != VisibilityFullyObscured) { 525 RegionTranslate(&tChild->borderClip, dx, dy); 526 RegionTranslate(&tChild->clipList, dx, dy); 527 528 tChild->pWin->drawable.serialNumber = 529 NEXT_SERIAL_NUMBER; 530 if (pScreen->ClipNotify) 531 (*pScreen->ClipNotify) (tChild->pWin, dx, dy); 532 } 533 if (tChild->valdata) { 534 RegionNull(&tChild->valdata->borderExposed); 535 if (HasParentRelativeBorder(tChild->pWin)) { 536 RegionSubtract(&tChild->valdata->borderExposed, 537 &tChild->borderClip, 538 &tChild->pWin->winSize); 539 } 540 RegionNull(&tChild->valdata->exposed); 541 } 542 if (tChild->firstChild) { 543 tChild = tChild->firstChild; 544 continue; 545 } 546 } 547 while (!tChild->nextSib && (tChild != tParent)) 548 tChild = tChild->parent; 549 if (tChild == tParent) 550 break; 551 tChild = tChild->nextSib; 552 } 553 return; 554 } 555 /* fall through */ 556 default: 557 if (dx || dy) { 558 RegionTranslate(&tParent->borderClip, dx, dy); 559 RegionTranslate(&tParent->clipList, dx, dy); 560 } 561 break; 562 case VTBroken: 563 RegionEmpty(&tParent->borderClip); 564 RegionEmpty(&tParent->clipList); 565 break; 566 } 567 568 borderVisible = tParent->valdata->borderVisible; 569 RegionNull(&tParent->valdata->borderExposed); 570 RegionNull(&tParent->valdata->exposed); 571 572 if (HasBorder(pParent)) { 573 if (borderVisible) { 574 RegionSubtract(exposed, universe, borderVisible); 575 RegionDestroy(borderVisible); 576 } 577 else 578 RegionSubtract(exposed, universe, &tParent->borderClip); 579 580 if (HasParentRelativeBorder(pParent) && (dx || dy)) 581 RegionSubtract(&tParent->valdata->borderExposed, 582 universe, &pParent->winSize); 583 else 584 RegionSubtract(&tParent->valdata->borderExposed, 585 exposed, &pParent->winSize); 586 587 RegionCopy(&tParent->borderClip, universe); 588 RegionIntersect(universe, universe, &pParent->winSize); 589 } 590 else 591 RegionCopy(&tParent->borderClip, universe); 592 593 if ((tChild = tParent->firstChild) && pParent->mapped) { 594 RegionNull(&childUniverse); 595 RegionNull(&childUnion); 596 597 for (; tChild; tChild = tChild->nextSib) { 598 if (tChild->pWin->viewable) 599 RegionAppend(&childUnion, &tChild->pWin->borderSize); 600 } 601 602 RegionValidate(&childUnion, &overlap); 603 604 for (tChild = tParent->firstChild; tChild; tChild = tChild->nextSib) { 605 if (tChild->pWin->viewable) { 606 if (tChild->valdata) { 607 RegionIntersect(&childUniverse, universe, 608 &tChild->pWin->borderSize); 609 miOverlayComputeClips(tChild->pWin, &childUniverse, 610 kind, exposed); 611 } 612 if (overlap) 613 RegionSubtract(universe, universe, 614 &tChild->pWin->borderSize); 615 } 616 } 617 if (!overlap) 618 RegionSubtract(universe, universe, &childUnion); 619 RegionUninit(&childUnion); 620 RegionUninit(&childUniverse); 621 } 622 623 if (oldVis == VisibilityFullyObscured || oldVis == VisibilityNotViewable) { 624 RegionCopy(&tParent->valdata->exposed, universe); 625 } 626 else if (newVis != VisibilityFullyObscured && 627 newVis != VisibilityNotViewable) { 628 RegionSubtract(&tParent->valdata->exposed, 629 universe, &tParent->clipList); 630 } 631 632 /* HACK ALERT - copying contents of regions, instead of regions */ 633 { 634 RegionRec tmp; 635 636 tmp = tParent->clipList; 637 tParent->clipList = *universe; 638 *universe = tmp; 639 } 640 641 pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; 642 643 if (pScreen->ClipNotify) 644 (*pScreen->ClipNotify) (pParent, dx, dy); 645} 646 647static void 648miOverlayMarkWindow(WindowPtr pWin) 649{ 650 miOverlayTreePtr pTree = NULL; 651 WindowPtr pChild, pGrandChild; 652 653 miMarkWindow(pWin); 654 655 /* look for UnmapValdata among immediate children */ 656 657 if (!(pChild = pWin->firstChild)) 658 return; 659 660 for (; pChild; pChild = pChild->nextSib) { 661 if (pChild->valdata == UnmapValData) { 662 if (IN_UNDERLAY(pChild)) { 663 pTree = MIOVERLAY_GET_WINDOW_TREE(pChild); 664 pTree->valdata = (miOverlayValDataPtr) UnmapValData; 665 continue; 666 } 667 else { 668 if (!(pGrandChild = pChild->firstChild)) 669 continue; 670 671 while (1) { 672 if (IN_UNDERLAY(pGrandChild)) { 673 pTree = MIOVERLAY_GET_WINDOW_TREE(pGrandChild); 674 pTree->valdata = (miOverlayValDataPtr) UnmapValData; 675 } 676 else if (pGrandChild->firstChild) { 677 pGrandChild = pGrandChild->firstChild; 678 continue; 679 } 680 681 while (!pGrandChild->nextSib && (pGrandChild != pChild)) 682 pGrandChild = pGrandChild->parent; 683 684 if (pChild == pGrandChild) 685 break; 686 687 pGrandChild = pGrandChild->nextSib; 688 } 689 } 690 } 691 } 692 693 if (pTree) { 694 MARK_UNDERLAY(pTree->parent->pWin); 695 MIOVERLAY_GET_SCREEN_PRIVATE(pWin->drawable.pScreen)->underlayMarked = 696 TRUE; 697 } 698} 699 700static void 701miOverlayMarkUnrealizedWindow(WindowPtr pChild, 702 WindowPtr pWin, Bool fromConfigure) 703{ 704 if ((pChild != pWin) || fromConfigure) { 705 miOverlayTreePtr pTree; 706 707 RegionEmpty(&pChild->clipList); 708 if (pChild->drawable.pScreen->ClipNotify) 709 (*pChild->drawable.pScreen->ClipNotify) (pChild, 0, 0); 710 RegionEmpty(&pChild->borderClip); 711 if ((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) { 712 if (pTree->valdata != (miOverlayValDataPtr) UnmapValData) { 713 RegionEmpty(&pTree->clipList); 714 RegionEmpty(&pTree->borderClip); 715 } 716 } 717 } 718} 719 720static int 721miOverlayValidateTree(WindowPtr pParent, WindowPtr pChild, /* first child effected */ 722 VTKind kind) 723{ 724 ScreenPtr pScreen = pParent->drawable.pScreen; 725 miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); 726 RegionRec totalClip, childClip, exposed; 727 miOverlayTreePtr tParent, tChild, tWin; 728 Bool overlap; 729 WindowPtr newParent; 730 731 if (!pPriv->underlayMarked) 732 goto SKIP_UNDERLAY; 733 734 if (!pChild) 735 pChild = pParent->firstChild; 736 737 RegionNull(&totalClip); 738 RegionNull(&childClip); 739 RegionNull(&exposed); 740 741 newParent = pParent; 742 743 while (IN_OVERLAY(newParent)) 744 newParent = newParent->parent; 745 746 tParent = MIOVERLAY_GET_WINDOW_TREE(newParent); 747 748 if (IN_UNDERLAY(pChild)) 749 tChild = MIOVERLAY_GET_WINDOW_TREE(pChild); 750 else 751 tChild = tParent->firstChild; 752 753 if (RegionBroken(&tParent->clipList) && !RegionBroken(&tParent->borderClip)) { 754 kind = VTBroken; 755 RegionCopy(&totalClip, &tParent->borderClip); 756 RegionIntersect(&totalClip, &totalClip, &tParent->pWin->winSize); 757 758 for (tWin = tParent->firstChild; tWin != tChild; tWin = tWin->nextSib) { 759 if (tWin->pWin->viewable) 760 RegionSubtract(&totalClip, &totalClip, &tWin->pWin->borderSize); 761 } 762 RegionEmpty(&tParent->clipList); 763 } 764 else { 765 for (tWin = tChild; tWin; tWin = tWin->nextSib) { 766 if (tWin->valdata) 767 RegionAppend(&totalClip, &tWin->borderClip); 768 } 769 RegionValidate(&totalClip, &overlap); 770 } 771 772 if (kind != VTStack) 773 RegionUnion(&totalClip, &totalClip, &tParent->clipList); 774 775 for (tWin = tChild; tWin; tWin = tWin->nextSib) { 776 if (tWin->valdata) { 777 if (tWin->pWin->viewable) { 778 RegionIntersect(&childClip, &totalClip, 779 &tWin->pWin->borderSize); 780 miOverlayComputeClips(tWin->pWin, &childClip, kind, &exposed); 781 RegionSubtract(&totalClip, &totalClip, &tWin->pWin->borderSize); 782 } 783 else { /* Means we are unmapping */ 784 RegionEmpty(&tWin->clipList); 785 RegionEmpty(&tWin->borderClip); 786 tWin->valdata = NULL; 787 } 788 } 789 } 790 791 RegionUninit(&childClip); 792 793 if (!((*pPriv->InOverlay) (newParent))) { 794 RegionNull(&tParent->valdata->exposed); 795 RegionNull(&tParent->valdata->borderExposed); 796 } 797 798 switch (kind) { 799 case VTStack: 800 break; 801 default: 802 if (!((*pPriv->InOverlay) (newParent))) 803 RegionSubtract(&tParent->valdata->exposed, &totalClip, 804 &tParent->clipList); 805 /* fall through */ 806 case VTMap: 807 RegionCopy(&tParent->clipList, &totalClip); 808 if (!((*pPriv->InOverlay) (newParent))) 809 newParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; 810 break; 811 } 812 813 RegionUninit(&totalClip); 814 RegionUninit(&exposed); 815 816 SKIP_UNDERLAY: 817 818 miValidateTree(pParent, pChild, kind); 819 820 return 1; 821} 822 823static void 824miOverlayHandleExposures(WindowPtr pWin) 825{ 826 ScreenPtr pScreen = pWin->drawable.pScreen; 827 miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); 828 WindowPtr pChild; 829 ValidatePtr val; 830 WindowExposuresProcPtr WindowExposures; 831 832 WindowExposures = pWin->drawable.pScreen->WindowExposures; 833 if (pPriv->underlayMarked) { 834 miOverlayTreePtr pTree; 835 miOverlayValDataPtr mival; 836 837 pChild = pWin; 838 while (IN_OVERLAY(pChild)) 839 pChild = pChild->parent; 840 841 pTree = MIOVERLAY_GET_WINDOW_TREE(pChild); 842 843 while (1) { 844 if ((mival = pTree->valdata)) { 845 if (!((*pPriv->InOverlay) (pTree->pWin))) { 846 if (RegionNotEmpty(&mival->borderExposed)) { 847 pScreen->PaintWindow(pTree->pWin, &mival->borderExposed, 848 PW_BORDER); 849 } 850 RegionUninit(&mival->borderExposed); 851 852 (*WindowExposures) (pTree->pWin, &mival->exposed); 853 RegionUninit(&mival->exposed); 854 } 855 free(mival); 856 pTree->valdata = NULL; 857 if (pTree->firstChild) { 858 pTree = pTree->firstChild; 859 continue; 860 } 861 } 862 while (!pTree->nextSib && (pTree->pWin != pChild)) 863 pTree = pTree->parent; 864 if (pTree->pWin == pChild) 865 break; 866 pTree = pTree->nextSib; 867 } 868 pPriv->underlayMarked = FALSE; 869 } 870 871 pChild = pWin; 872 while (1) { 873 if ((val = pChild->valdata)) { 874 if (!((*pPriv->InOverlay) (pChild))) { 875 RegionUnion(&val->after.exposed, &val->after.exposed, 876 &val->after.borderExposed); 877 878 if (RegionNotEmpty(&val->after.exposed)) { 879 (*(MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent)) 880 (pScreen, RegionNumRects(&val->after.exposed), 881 RegionRects(&val->after.exposed)); 882 } 883 } 884 else { 885 if (RegionNotEmpty(&val->after.borderExposed)) { 886 pScreen->PaintWindow(pChild, &val->after.borderExposed, 887 PW_BORDER); 888 } 889 (*WindowExposures) (pChild, &val->after.exposed); 890 } 891 RegionUninit(&val->after.borderExposed); 892 RegionUninit(&val->after.exposed); 893 free(val); 894 pChild->valdata = NULL; 895 if (pChild->firstChild) { 896 pChild = pChild->firstChild; 897 continue; 898 } 899 } 900 while (!pChild->nextSib && (pChild != pWin)) 901 pChild = pChild->parent; 902 if (pChild == pWin) 903 break; 904 pChild = pChild->nextSib; 905 } 906} 907 908static void 909miOverlayMoveWindow(WindowPtr pWin, 910 int x, int y, WindowPtr pNextSib, VTKind kind) 911{ 912 ScreenPtr pScreen = pWin->drawable.pScreen; 913 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); 914 WindowPtr pParent, windowToValidate; 915 Bool WasViewable = (Bool) (pWin->viewable); 916 short bw; 917 RegionRec overReg, underReg; 918 DDXPointRec oldpt; 919 920 if (!(pParent = pWin->parent)) 921 return; 922 bw = wBorderWidth(pWin); 923 924 oldpt.x = pWin->drawable.x; 925 oldpt.y = pWin->drawable.y; 926 if (WasViewable) { 927 RegionNull(&overReg); 928 RegionNull(&underReg); 929 if (pTree) { 930 RegionCopy(&overReg, &pWin->borderClip); 931 RegionCopy(&underReg, &pTree->borderClip); 932 } 933 else { 934 RegionCopy(&overReg, &pWin->borderClip); 935 CollectUnderlayChildrenRegions(pWin, &underReg); 936 } 937 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL); 938 } 939 pWin->origin.x = x + (int) bw; 940 pWin->origin.y = y + (int) bw; 941 x = pWin->drawable.x = pParent->drawable.x + x + (int) bw; 942 y = pWin->drawable.y = pParent->drawable.y + y + (int) bw; 943 944 SetWinSize(pWin); 945 SetBorderSize(pWin); 946 947 (*pScreen->PositionWindow) (pWin, x, y); 948 949 windowToValidate = MoveWindowInStack(pWin, pNextSib); 950 951 ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0); 952 953 if (WasViewable) { 954 miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); 955 956 (*pScreen->MarkOverlappedWindows) (pWin, windowToValidate, NULL); 957 958 (*pScreen->ValidateTree) (pWin->parent, NullWindow, kind); 959 if (RegionNotEmpty(&underReg)) { 960 pPriv->copyUnderlay = TRUE; 961 (*pWin->drawable.pScreen->CopyWindow) (pWin, oldpt, &underReg); 962 } 963 RegionUninit(&underReg); 964 if (RegionNotEmpty(&overReg)) { 965 pPriv->copyUnderlay = FALSE; 966 (*pWin->drawable.pScreen->CopyWindow) (pWin, oldpt, &overReg); 967 } 968 RegionUninit(&overReg); 969 (*pScreen->HandleExposures) (pWin->parent); 970 971 if (pScreen->PostValidateTree) 972 (*pScreen->PostValidateTree) (pWin->parent, NullWindow, kind); 973 } 974 if (pWin->realized) 975 WindowsRestructured(); 976} 977 978#ifndef RECTLIMIT 979#define RECTLIMIT 25 980#endif 981 982static void 983miOverlayWindowExposures(WindowPtr pWin, RegionPtr prgn) 984{ 985 RegionPtr exposures = prgn; 986 ScreenPtr pScreen = pWin->drawable.pScreen; 987 988 if (prgn && !RegionNil(prgn)) { 989 RegionRec expRec; 990 int clientInterested = 991 (pWin->eventMask | wOtherEventMasks(pWin)) & ExposureMask; 992 if (clientInterested && (RegionNumRects(prgn) > RECTLIMIT)) { 993 miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); 994 BoxRec box; 995 996 box = *RegionExtents(prgn); 997 exposures = &expRec; 998 RegionInit(exposures, &box, 1); 999 RegionReset(prgn, &box); 1000 /* This is the only reason why we are replacing mi's version 1001 of this file */ 1002 1003 if (!((*pPriv->InOverlay) (pWin))) { 1004 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); 1005 1006 RegionIntersect(prgn, prgn, &pTree->clipList); 1007 } 1008 else 1009 RegionIntersect(prgn, prgn, &pWin->clipList); 1010 } 1011 pScreen->PaintWindow(pWin, prgn, PW_BACKGROUND); 1012 if (clientInterested) 1013 miSendExposures(pWin, exposures, 1014 pWin->drawable.x, pWin->drawable.y); 1015 if (exposures == &expRec) 1016 RegionUninit(exposures); 1017 RegionEmpty(prgn); 1018 } 1019} 1020 1021typedef struct { 1022 RegionPtr over; 1023 RegionPtr under; 1024} miOverlayTwoRegions; 1025 1026static int 1027miOverlayRecomputeExposures(WindowPtr pWin, void *value) 1028{ 1029 miOverlayTwoRegions *pValid = (miOverlayTwoRegions *) value; 1030 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); 1031 1032 if (pWin->valdata) { 1033 /* 1034 * compute exposed regions of this window 1035 */ 1036 RegionSubtract(&pWin->valdata->after.exposed, 1037 &pWin->clipList, pValid->over); 1038 /* 1039 * compute exposed regions of the border 1040 */ 1041 RegionSubtract(&pWin->valdata->after.borderExposed, 1042 &pWin->borderClip, &pWin->winSize); 1043 RegionSubtract(&pWin->valdata->after.borderExposed, 1044 &pWin->valdata->after.borderExposed, pValid->over); 1045 } 1046 1047 if (pTree && pTree->valdata) { 1048 RegionSubtract(&pTree->valdata->exposed, 1049 &pTree->clipList, pValid->under); 1050 RegionSubtract(&pTree->valdata->borderExposed, 1051 &pTree->borderClip, &pWin->winSize); 1052 RegionSubtract(&pTree->valdata->borderExposed, 1053 &pTree->valdata->borderExposed, pValid->under); 1054 } 1055 else if (!pWin->valdata) 1056 return WT_NOMATCH; 1057 1058 return WT_WALKCHILDREN; 1059} 1060 1061static void 1062miOverlayResizeWindow(WindowPtr pWin, 1063 int x, int y, 1064 unsigned int w, unsigned int h, WindowPtr pSib) 1065{ 1066 ScreenPtr pScreen = pWin->drawable.pScreen; 1067 WindowPtr pParent; 1068 miOverlayTreePtr tChild, pTree; 1069 Bool WasViewable = (Bool) (pWin->viewable); 1070 unsigned short width = pWin->drawable.width; 1071 unsigned short height = pWin->drawable.height; 1072 short oldx = pWin->drawable.x; 1073 short oldy = pWin->drawable.y; 1074 int bw = wBorderWidth(pWin); 1075 short dw, dh; 1076 DDXPointRec oldpt; 1077 RegionPtr oldRegion = NULL, oldRegion2 = NULL; 1078 WindowPtr pFirstChange; 1079 WindowPtr pChild; 1080 RegionPtr gravitate[StaticGravity + 1]; 1081 RegionPtr gravitate2[StaticGravity + 1]; 1082 unsigned g; 1083 int nx, ny; /* destination x,y */ 1084 int newx, newy; /* new inner window position */ 1085 RegionPtr pRegion = NULL; 1086 RegionPtr destClip, destClip2; 1087 RegionPtr oldWinClip = NULL, oldWinClip2 = NULL; 1088 RegionPtr borderVisible = NullRegion; 1089 RegionPtr borderVisible2 = NullRegion; 1090 Bool shrunk = FALSE; /* shrunk in an inner dimension */ 1091 Bool moved = FALSE; /* window position changed */ 1092 Bool doUnderlay; 1093 1094 /* if this is a root window, can't be resized */ 1095 if (!(pParent = pWin->parent)) 1096 return; 1097 1098 pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); 1099 doUnderlay = ((pTree) || HasUnderlayChildren(pWin)); 1100 newx = pParent->drawable.x + x + bw; 1101 newy = pParent->drawable.y + y + bw; 1102 if (WasViewable) { 1103 /* 1104 * save the visible region of the window 1105 */ 1106 oldRegion = RegionCreate(NullBox, 1); 1107 RegionCopy(oldRegion, &pWin->winSize); 1108 if (doUnderlay) { 1109 oldRegion2 = RegionCreate(NullBox, 1); 1110 RegionCopy(oldRegion2, &pWin->winSize); 1111 } 1112 1113 /* 1114 * categorize child windows into regions to be moved 1115 */ 1116 for (g = 0; g <= StaticGravity; g++) 1117 gravitate[g] = gravitate2[g] = NULL; 1118 for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { 1119 g = pChild->winGravity; 1120 if (g != UnmapGravity) { 1121 if (!gravitate[g]) 1122 gravitate[g] = RegionCreate(NullBox, 1); 1123 RegionUnion(gravitate[g], gravitate[g], &pChild->borderClip); 1124 1125 if (doUnderlay) { 1126 if (!gravitate2[g]) 1127 gravitate2[g] = RegionCreate(NullBox, 0); 1128 1129 if ((tChild = MIOVERLAY_GET_WINDOW_TREE(pChild))) { 1130 RegionUnion(gravitate2[g], 1131 gravitate2[g], &tChild->borderClip); 1132 } 1133 else 1134 CollectUnderlayChildrenRegions(pChild, gravitate2[g]); 1135 } 1136 } 1137 else { 1138 UnmapWindow(pChild, TRUE); 1139 } 1140 } 1141 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL); 1142 1143 oldWinClip = oldWinClip2 = NULL; 1144 if (pWin->bitGravity != ForgetGravity) { 1145 oldWinClip = RegionCreate(NullBox, 1); 1146 RegionCopy(oldWinClip, &pWin->clipList); 1147 if (pTree) { 1148 oldWinClip2 = RegionCreate(NullBox, 1); 1149 RegionCopy(oldWinClip2, &pTree->clipList); 1150 } 1151 } 1152 /* 1153 * if the window is changing size, borderExposed 1154 * can't be computed correctly without some help. 1155 */ 1156 if (pWin->drawable.height > h || pWin->drawable.width > w) 1157 shrunk = TRUE; 1158 1159 if (newx != oldx || newy != oldy) 1160 moved = TRUE; 1161 1162 if ((pWin->drawable.height != h || pWin->drawable.width != w) && 1163 HasBorder(pWin)) { 1164 borderVisible = RegionCreate(NullBox, 1); 1165 if (pTree) 1166 borderVisible2 = RegionCreate(NullBox, 1); 1167 /* for tiled borders, we punt and draw the whole thing */ 1168 if (pWin->borderIsPixel || !moved) { 1169 if (shrunk || moved) 1170 RegionSubtract(borderVisible, 1171 &pWin->borderClip, &pWin->winSize); 1172 else 1173 RegionCopy(borderVisible, &pWin->borderClip); 1174 if (pTree) { 1175 if (shrunk || moved) 1176 RegionSubtract(borderVisible, 1177 &pTree->borderClip, &pWin->winSize); 1178 else 1179 RegionCopy(borderVisible, &pTree->borderClip); 1180 } 1181 } 1182 } 1183 } 1184 pWin->origin.x = x + bw; 1185 pWin->origin.y = y + bw; 1186 pWin->drawable.height = h; 1187 pWin->drawable.width = w; 1188 1189 x = pWin->drawable.x = newx; 1190 y = pWin->drawable.y = newy; 1191 1192 SetWinSize(pWin); 1193 SetBorderSize(pWin); 1194 1195 dw = (int) w - (int) width; 1196 dh = (int) h - (int) height; 1197 ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh); 1198 1199 /* let the hardware adjust background and border pixmaps, if any */ 1200 (*pScreen->PositionWindow) (pWin, x, y); 1201 1202 pFirstChange = MoveWindowInStack(pWin, pSib); 1203 1204 if (WasViewable) { 1205 pRegion = RegionCreate(NullBox, 1); 1206 1207 (*pScreen->MarkOverlappedWindows) (pWin, pFirstChange, NULL); 1208 1209 pWin->valdata->before.resized = TRUE; 1210 pWin->valdata->before.borderVisible = borderVisible; 1211 if (pTree) 1212 pTree->valdata->borderVisible = borderVisible2; 1213 1214 (*pScreen->ValidateTree) (pWin->parent, pFirstChange, VTOther); 1215 /* 1216 * the entire window is trashed unless bitGravity 1217 * recovers portions of it 1218 */ 1219 RegionCopy(&pWin->valdata->after.exposed, &pWin->clipList); 1220 if (pTree) 1221 RegionCopy(&pTree->valdata->exposed, &pTree->clipList); 1222 } 1223 1224 GravityTranslate(x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny); 1225 1226 if (WasViewable) { 1227 miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); 1228 miOverlayTwoRegions TwoRegions; 1229 1230 /* avoid the border */ 1231 if (HasBorder(pWin)) { 1232 int offx, offy, dx, dy; 1233 1234 /* kruft to avoid double translates for each gravity */ 1235 offx = 0; 1236 offy = 0; 1237 for (g = 0; g <= StaticGravity; g++) { 1238 if (!gravitate[g] && !gravitate2[g]) 1239 continue; 1240 1241 /* align winSize to gravitate[g]. 1242 * winSize is in new coordinates, 1243 * gravitate[g] is still in old coordinates */ 1244 GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny); 1245 1246 dx = (oldx - nx) - offx; 1247 dy = (oldy - ny) - offy; 1248 if (dx || dy) { 1249 RegionTranslate(&pWin->winSize, dx, dy); 1250 offx += dx; 1251 offy += dy; 1252 } 1253 if (gravitate[g]) 1254 RegionIntersect(gravitate[g], gravitate[g], &pWin->winSize); 1255 if (gravitate2[g]) 1256 RegionIntersect(gravitate2[g], gravitate2[g], 1257 &pWin->winSize); 1258 } 1259 /* get winSize back where it belongs */ 1260 if (offx || offy) 1261 RegionTranslate(&pWin->winSize, -offx, -offy); 1262 } 1263 /* 1264 * add screen bits to the appropriate bucket 1265 */ 1266 1267 if (oldWinClip2) { 1268 RegionCopy(pRegion, oldWinClip2); 1269 RegionTranslate(pRegion, nx - oldx, ny - oldy); 1270 RegionIntersect(oldWinClip2, pRegion, &pTree->clipList); 1271 1272 for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) { 1273 if (gravitate2[g]) 1274 RegionSubtract(oldWinClip2, oldWinClip2, gravitate2[g]); 1275 } 1276 RegionTranslate(oldWinClip2, oldx - nx, oldy - ny); 1277 g = pWin->bitGravity; 1278 if (!gravitate2[g]) 1279 gravitate2[g] = oldWinClip2; 1280 else { 1281 RegionUnion(gravitate2[g], gravitate2[g], oldWinClip2); 1282 RegionDestroy(oldWinClip2); 1283 } 1284 } 1285 1286 if (oldWinClip) { 1287 /* 1288 * clip to new clipList 1289 */ 1290 RegionCopy(pRegion, oldWinClip); 1291 RegionTranslate(pRegion, nx - oldx, ny - oldy); 1292 RegionIntersect(oldWinClip, pRegion, &pWin->clipList); 1293 /* 1294 * don't step on any gravity bits which will be copied after this 1295 * region. Note -- this assumes that the regions will be copied 1296 * in gravity order. 1297 */ 1298 for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) { 1299 if (gravitate[g]) 1300 RegionSubtract(oldWinClip, oldWinClip, gravitate[g]); 1301 } 1302 RegionTranslate(oldWinClip, oldx - nx, oldy - ny); 1303 g = pWin->bitGravity; 1304 if (!gravitate[g]) 1305 gravitate[g] = oldWinClip; 1306 else { 1307 RegionUnion(gravitate[g], gravitate[g], oldWinClip); 1308 RegionDestroy(oldWinClip); 1309 } 1310 } 1311 1312 /* 1313 * move the bits on the screen 1314 */ 1315 1316 destClip = destClip2 = NULL; 1317 1318 for (g = 0; g <= StaticGravity; g++) { 1319 if (!gravitate[g] && !gravitate2[g]) 1320 continue; 1321 1322 GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny); 1323 1324 oldpt.x = oldx + (x - nx); 1325 oldpt.y = oldy + (y - ny); 1326 1327 /* Note that gravitate[g] is *translated* by CopyWindow */ 1328 1329 /* only copy the remaining useful bits */ 1330 1331 if (gravitate[g]) 1332 RegionIntersect(gravitate[g], gravitate[g], oldRegion); 1333 if (gravitate2[g]) 1334 RegionIntersect(gravitate2[g], gravitate2[g], oldRegion2); 1335 1336 /* clip to not overwrite already copied areas */ 1337 1338 if (destClip && gravitate[g]) { 1339 RegionTranslate(destClip, oldpt.x - x, oldpt.y - y); 1340 RegionSubtract(gravitate[g], gravitate[g], destClip); 1341 RegionTranslate(destClip, x - oldpt.x, y - oldpt.y); 1342 } 1343 if (destClip2 && gravitate2[g]) { 1344 RegionTranslate(destClip2, oldpt.x - x, oldpt.y - y); 1345 RegionSubtract(gravitate2[g], gravitate2[g], destClip2); 1346 RegionTranslate(destClip2, x - oldpt.x, y - oldpt.y); 1347 } 1348 1349 /* and move those bits */ 1350 1351 if (oldpt.x != x || oldpt.y != y) { 1352 if (gravitate2[g]) { 1353 pPriv->copyUnderlay = TRUE; 1354 (*pScreen->CopyWindow) (pWin, oldpt, gravitate2[g]); 1355 } 1356 if (gravitate[g]) { 1357 pPriv->copyUnderlay = FALSE; 1358 (*pScreen->CopyWindow) (pWin, oldpt, gravitate[g]); 1359 } 1360 } 1361 1362 /* remove any overwritten bits from the remaining useful bits */ 1363 1364 if (gravitate[g]) 1365 RegionSubtract(oldRegion, oldRegion, gravitate[g]); 1366 if (gravitate2[g]) 1367 RegionSubtract(oldRegion2, oldRegion2, gravitate2[g]); 1368 1369 /* 1370 * recompute exposed regions of child windows 1371 */ 1372 1373 for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { 1374 if (pChild->winGravity != g) 1375 continue; 1376 1377 TwoRegions.over = gravitate[g]; 1378 TwoRegions.under = gravitate2[g]; 1379 1380 TraverseTree(pChild, miOverlayRecomputeExposures, 1381 (void *) (&TwoRegions)); 1382 } 1383 1384 /* 1385 * remove the successfully copied regions of the 1386 * window from its exposed region 1387 */ 1388 1389 if (g == pWin->bitGravity) { 1390 if (gravitate[g]) 1391 RegionSubtract(&pWin->valdata->after.exposed, 1392 &pWin->valdata->after.exposed, gravitate[g]); 1393 if (gravitate2[g] && pTree) 1394 RegionSubtract(&pTree->valdata->exposed, 1395 &pTree->valdata->exposed, gravitate2[g]); 1396 } 1397 if (gravitate[g]) { 1398 if (!destClip) 1399 destClip = gravitate[g]; 1400 else { 1401 RegionUnion(destClip, destClip, gravitate[g]); 1402 RegionDestroy(gravitate[g]); 1403 } 1404 } 1405 if (gravitate2[g]) { 1406 if (!destClip2) 1407 destClip2 = gravitate2[g]; 1408 else { 1409 RegionUnion(destClip2, destClip2, gravitate2[g]); 1410 RegionDestroy(gravitate2[g]); 1411 } 1412 } 1413 } 1414 1415 RegionDestroy(pRegion); 1416 RegionDestroy(oldRegion); 1417 if (doUnderlay) 1418 RegionDestroy(oldRegion2); 1419 if (destClip) 1420 RegionDestroy(destClip); 1421 if (destClip2) 1422 RegionDestroy(destClip2); 1423 (*pScreen->HandleExposures) (pWin->parent); 1424 if (pScreen->PostValidateTree) 1425 (*pScreen->PostValidateTree) (pWin->parent, pFirstChange, VTOther); 1426 } 1427 if (pWin->realized) 1428 WindowsRestructured(); 1429} 1430 1431static void 1432miOverlaySetShape(WindowPtr pWin, int kind) 1433{ 1434 Bool WasViewable = (Bool) (pWin->viewable); 1435 ScreenPtr pScreen = pWin->drawable.pScreen; 1436 1437 if (kind != ShapeInput) { 1438 if (WasViewable) { 1439 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL); 1440 1441 if (HasBorder(pWin)) { 1442 RegionPtr borderVisible; 1443 1444 borderVisible = RegionCreate(NullBox, 1); 1445 RegionSubtract(borderVisible, 1446 &pWin->borderClip, &pWin->winSize); 1447 pWin->valdata->before.borderVisible = borderVisible; 1448 pWin->valdata->before.resized = TRUE; 1449 if (IN_UNDERLAY(pWin)) { 1450 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); 1451 RegionPtr borderVisible2; 1452 1453 borderVisible2 = RegionCreate(NULL, 1); 1454 RegionSubtract(borderVisible2, 1455 &pTree->borderClip, &pWin->winSize); 1456 pTree->valdata->borderVisible = borderVisible2; 1457 } 1458 } 1459 } 1460 1461 SetWinSize(pWin); 1462 SetBorderSize(pWin); 1463 1464 ResizeChildrenWinSize(pWin, 0, 0, 0, 0); 1465 1466 if (WasViewable) { 1467 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL); 1468 (*pScreen->ValidateTree) (pWin->parent, NullWindow, VTOther); 1469 (*pScreen->HandleExposures) (pWin->parent); 1470 if (pScreen->PostValidateTree) 1471 (*pScreen->PostValidateTree) (pWin->parent, NullWindow, 1472 VTOther); 1473 } 1474 } 1475 if (pWin->realized) 1476 WindowsRestructured(); 1477 CheckCursorConfinement(pWin); 1478} 1479 1480static void 1481miOverlayChangeBorderWidth(WindowPtr pWin, unsigned int width) 1482{ 1483 int oldwidth; 1484 ScreenPtr pScreen; 1485 Bool WasViewable = (Bool) (pWin->viewable); 1486 Bool HadBorder; 1487 1488 oldwidth = wBorderWidth(pWin); 1489 if (oldwidth == width) 1490 return; 1491 HadBorder = HasBorder(pWin); 1492 pScreen = pWin->drawable.pScreen; 1493 if (WasViewable && (width < oldwidth)) 1494 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL); 1495 1496 pWin->borderWidth = width; 1497 SetBorderSize(pWin); 1498 1499 if (WasViewable) { 1500 if (width > oldwidth) { 1501 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL); 1502 1503 if (HadBorder) { 1504 RegionPtr borderVisible; 1505 1506 borderVisible = RegionCreate(NULL, 1); 1507 RegionSubtract(borderVisible, 1508 &pWin->borderClip, &pWin->winSize); 1509 pWin->valdata->before.borderVisible = borderVisible; 1510 if (IN_UNDERLAY(pWin)) { 1511 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); 1512 RegionPtr borderVisible2; 1513 1514 borderVisible2 = RegionCreate(NULL, 1); 1515 RegionSubtract(borderVisible2, 1516 &pTree->borderClip, &pWin->winSize); 1517 pTree->valdata->borderVisible = borderVisible2; 1518 } 1519 } 1520 } 1521 (*pScreen->ValidateTree) (pWin->parent, pWin, VTOther); 1522 (*pScreen->HandleExposures) (pWin->parent); 1523 1524 if (pScreen->PostValidateTree) 1525 (*pScreen->PostValidateTree) (pWin->parent, pWin, VTOther); 1526 } 1527 if (pWin->realized) 1528 WindowsRestructured(); 1529} 1530 1531/* We need this as an addition since the xf86 common code doesn't 1532 know about the second tree which is static to this file. */ 1533 1534void 1535miOverlaySetRootClip(ScreenPtr pScreen, Bool enable) 1536{ 1537 WindowPtr pRoot = pScreen->root; 1538 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pRoot); 1539 1540 MARK_UNDERLAY(pRoot); 1541 1542 if (enable) { 1543 BoxRec box; 1544 1545 box.x1 = 0; 1546 box.y1 = 0; 1547 box.x2 = pScreen->width; 1548 box.y2 = pScreen->height; 1549 1550 RegionReset(&pTree->borderClip, &box); 1551 } 1552 else 1553 RegionEmpty(&pTree->borderClip); 1554 1555 RegionBreak(&pTree->clipList); 1556} 1557 1558static void 1559miOverlayClearToBackground(WindowPtr pWin, 1560 int x, int y, int w, int h, Bool generateExposures) 1561{ 1562 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); 1563 BoxRec box; 1564 RegionRec reg; 1565 ScreenPtr pScreen = pWin->drawable.pScreen; 1566 miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); 1567 RegionPtr clipList; 1568 BoxPtr extents; 1569 int x1, y1, x2, y2; 1570 1571 x1 = pWin->drawable.x + x; 1572 y1 = pWin->drawable.y + y; 1573 if (w) 1574 x2 = x1 + (int) w; 1575 else 1576 x2 = x1 + (int) pWin->drawable.width - (int) x; 1577 if (h) 1578 y2 = y1 + h; 1579 else 1580 y2 = y1 + (int) pWin->drawable.height - (int) y; 1581 1582 clipList = ((*pScreenPriv->InOverlay) (pWin)) ? &pWin->clipList : 1583 &pTree->clipList; 1584 1585 extents = RegionExtents(clipList); 1586 1587 if (x1 < extents->x1) 1588 x1 = extents->x1; 1589 if (x2 > extents->x2) 1590 x2 = extents->x2; 1591 if (y1 < extents->y1) 1592 y1 = extents->y1; 1593 if (y2 > extents->y2) 1594 y2 = extents->y2; 1595 1596 if (x2 <= x1 || y2 <= y1) 1597 x2 = x1 = y2 = y1 = 0; 1598 1599 box.x1 = x1; 1600 box.x2 = x2; 1601 box.y1 = y1; 1602 box.y2 = y2; 1603 1604 RegionInit(®, &box, 1); 1605 1606 RegionIntersect(®, ®, clipList); 1607 if (generateExposures) 1608 (*pScreen->WindowExposures) (pWin, ®); 1609 else if (pWin->backgroundState != None) 1610 pScreen->PaintWindow(pWin, ®, PW_BACKGROUND); 1611 RegionUninit(®); 1612} 1613 1614/****************************************************************/ 1615 1616/* not used */ 1617Bool 1618miOverlayGetPrivateClips(WindowPtr pWin, 1619 RegionPtr *borderClip, RegionPtr *clipList) 1620{ 1621 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); 1622 1623 if (pTree) { 1624 *borderClip = &(pTree->borderClip); 1625 *clipList = &(pTree->clipList); 1626 return TRUE; 1627 } 1628 1629 *borderClip = *clipList = NULL; 1630 1631 return FALSE; 1632} 1633 1634void 1635miOverlaySetTransFunction(ScreenPtr pScreen, miOverlayTransFunc transFunc) 1636{ 1637 MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent = transFunc; 1638} 1639 1640Bool 1641miOverlayCopyUnderlay(ScreenPtr pScreen) 1642{ 1643 return MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->copyUnderlay; 1644} 1645 1646void 1647miOverlayComputeCompositeClip(GCPtr pGC, WindowPtr pWin) 1648{ 1649 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); 1650 RegionPtr pregWin; 1651 Bool freeTmpClip, freeCompClip; 1652 1653 if (!pTree) { 1654 miComputeCompositeClip(pGC, &pWin->drawable); 1655 return; 1656 } 1657 1658 if (pGC->subWindowMode == IncludeInferiors) { 1659 pregWin = RegionCreate(NullBox, 1); 1660 freeTmpClip = TRUE; 1661 if (pWin->parent || (screenIsSaved != SCREEN_SAVER_ON) || 1662 !HasSaverWindow(pGC->pScreen)) { 1663 RegionIntersect(pregWin, &pTree->borderClip, &pWin->winSize); 1664 } 1665 } 1666 else { 1667 pregWin = &pTree->clipList; 1668 freeTmpClip = FALSE; 1669 } 1670 freeCompClip = pGC->freeCompClip; 1671 if (!pGC->clientClip) { 1672 if (freeCompClip) 1673 RegionDestroy(pGC->pCompositeClip); 1674 pGC->pCompositeClip = pregWin; 1675 pGC->freeCompClip = freeTmpClip; 1676 } 1677 else { 1678 RegionTranslate(pGC->clientClip, 1679 pWin->drawable.x + pGC->clipOrg.x, 1680 pWin->drawable.y + pGC->clipOrg.y); 1681 1682 if (freeCompClip) { 1683 RegionIntersect(pGC->pCompositeClip, pregWin, pGC->clientClip); 1684 if (freeTmpClip) 1685 RegionDestroy(pregWin); 1686 } 1687 else if (freeTmpClip) { 1688 RegionIntersect(pregWin, pregWin, pGC->clientClip); 1689 pGC->pCompositeClip = pregWin; 1690 } 1691 else { 1692 pGC->pCompositeClip = RegionCreate(NullBox, 0); 1693 RegionIntersect(pGC->pCompositeClip, pregWin, pGC->clientClip); 1694 } 1695 pGC->freeCompClip = TRUE; 1696 RegionTranslate(pGC->clientClip, 1697 -(pWin->drawable.x + pGC->clipOrg.x), 1698 -(pWin->drawable.y + pGC->clipOrg.y)); 1699 } 1700} 1701 1702Bool 1703miOverlayCollectUnderlayRegions(WindowPtr pWin, RegionPtr *region) 1704{ 1705 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); 1706 1707 if (pTree) { 1708 *region = &pTree->borderClip; 1709 return FALSE; 1710 } 1711 1712 *region = RegionCreate(NullBox, 0); 1713 1714 CollectUnderlayChildrenRegions(pWin, *region); 1715 1716 return TRUE; 1717} 1718 1719static miOverlayTreePtr 1720DoLeaf(WindowPtr pWin, miOverlayTreePtr parent, miOverlayTreePtr prevSib) 1721{ 1722 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); 1723 1724 pTree->parent = parent; 1725 pTree->firstChild = NULL; 1726 pTree->lastChild = NULL; 1727 pTree->prevSib = prevSib; 1728 pTree->nextSib = NULL; 1729 1730 if (prevSib) 1731 prevSib->nextSib = pTree; 1732 1733 if (!parent->firstChild) 1734 parent->firstChild = parent->lastChild = pTree; 1735 else if (parent->lastChild == prevSib) 1736 parent->lastChild = pTree; 1737 1738 return pTree; 1739} 1740 1741static void 1742RebuildTree(WindowPtr pWin) 1743{ 1744 miOverlayTreePtr parent, prevSib, tChild; 1745 WindowPtr pChild; 1746 1747 prevSib = tChild = NULL; 1748 1749 pWin = pWin->parent; 1750 1751 while (IN_OVERLAY(pWin)) 1752 pWin = pWin->parent; 1753 1754 parent = MIOVERLAY_GET_WINDOW_TREE(pWin); 1755 1756 pChild = pWin->firstChild; 1757 parent->firstChild = parent->lastChild = NULL; 1758 1759 while (1) { 1760 if (IN_UNDERLAY(pChild)) 1761 prevSib = tChild = DoLeaf(pChild, parent, prevSib); 1762 1763 if (pChild->firstChild) { 1764 if (IN_UNDERLAY(pChild)) { 1765 parent = tChild; 1766 prevSib = NULL; 1767 } 1768 pChild = pChild->firstChild; 1769 continue; 1770 } 1771 1772 while (!pChild->nextSib) { 1773 pChild = pChild->parent; 1774 if (pChild == pWin) 1775 return; 1776 if (IN_UNDERLAY(pChild)) { 1777 prevSib = tChild = MIOVERLAY_GET_WINDOW_TREE(pChild); 1778 parent = tChild->parent; 1779 } 1780 } 1781 1782 pChild = pChild->nextSib; 1783 } 1784} 1785 1786static Bool 1787HasUnderlayChildren(WindowPtr pWin) 1788{ 1789 WindowPtr pChild; 1790 1791 if (!(pChild = pWin->firstChild)) 1792 return FALSE; 1793 1794 while (1) { 1795 if (IN_UNDERLAY(pChild)) 1796 return TRUE; 1797 1798 if (pChild->firstChild) { 1799 pChild = pChild->firstChild; 1800 continue; 1801 } 1802 1803 while (!pChild->nextSib && (pWin != pChild)) 1804 pChild = pChild->parent; 1805 1806 if (pChild == pWin) 1807 break; 1808 1809 pChild = pChild->nextSib; 1810 } 1811 1812 return FALSE; 1813} 1814 1815static Bool 1816CollectUnderlayChildrenRegions(WindowPtr pWin, RegionPtr pReg) 1817{ 1818 WindowPtr pChild; 1819 miOverlayTreePtr pTree; 1820 Bool hasUnderlay; 1821 1822 if (!(pChild = pWin->firstChild)) 1823 return FALSE; 1824 1825 hasUnderlay = FALSE; 1826 1827 while (1) { 1828 if ((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) { 1829 RegionAppend(pReg, &pTree->borderClip); 1830 hasUnderlay = TRUE; 1831 } 1832 else if (pChild->firstChild) { 1833 pChild = pChild->firstChild; 1834 continue; 1835 } 1836 1837 while (!pChild->nextSib && (pWin != pChild)) 1838 pChild = pChild->parent; 1839 1840 if (pChild == pWin) 1841 break; 1842 1843 pChild = pChild->nextSib; 1844 } 1845 1846 if (hasUnderlay) { 1847 Bool overlap; 1848 1849 RegionValidate(pReg, &overlap); 1850 } 1851 1852 return hasUnderlay; 1853} 1854 1855static void 1856MarkUnderlayWindow(WindowPtr pWin) 1857{ 1858 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); 1859 1860 if (pTree->valdata) 1861 return; 1862 pTree->valdata = 1863 (miOverlayValDataPtr) xnfalloc(sizeof(miOverlayValDataRec)); 1864 pTree->valdata->oldAbsCorner.x = pWin->drawable.x; 1865 pTree->valdata->oldAbsCorner.y = pWin->drawable.y; 1866 pTree->valdata->borderVisible = NullRegion; 1867} 1868