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