xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

mioverlay.c (58947B)


      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 typedef struct {
     22     RegionRec exposed;
     23     RegionRec borderExposed;
     24     RegionPtr borderVisible;
     25     DDXPointRec oldAbsCorner;
     26 } miOverlayValDataRec, *miOverlayValDataPtr;
     27 
     28 typedef 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 
     41 typedef struct {
     42     miOverlayTreePtr tree;
     43 } miOverlayWindowRec, *miOverlayWindowPtr;
     44 
     45 typedef 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 
     57 static DevPrivateKeyRec miOverlayWindowKeyRec;
     58 
     59 #define miOverlayWindowKey (&miOverlayWindowKeyRec)
     60 static DevPrivateKeyRec miOverlayScreenKeyRec;
     61 
     62 #define miOverlayScreenKey (&miOverlayScreenKeyRec)
     63 
     64 static void RebuildTree(WindowPtr);
     65 static Bool HasUnderlayChildren(WindowPtr);
     66 static void MarkUnderlayWindow(WindowPtr);
     67 static Bool CollectUnderlayChildrenRegions(WindowPtr, RegionPtr);
     68 
     69 static Bool miOverlayCloseScreen(ScreenPtr);
     70 static Bool miOverlayCreateWindow(WindowPtr);
     71 static Bool miOverlayDestroyWindow(WindowPtr);
     72 static Bool miOverlayUnrealizeWindow(WindowPtr);
     73 static Bool miOverlayRealizeWindow(WindowPtr);
     74 static void miOverlayMarkWindow(WindowPtr);
     75 static void miOverlayReparentWindow(WindowPtr, WindowPtr);
     76 static void miOverlayRestackWindow(WindowPtr, WindowPtr);
     77 static Bool miOverlayMarkOverlappedWindows(WindowPtr, WindowPtr, WindowPtr *);
     78 static void miOverlayMarkUnrealizedWindow(WindowPtr, WindowPtr, Bool);
     79 static int miOverlayValidateTree(WindowPtr, WindowPtr, VTKind);
     80 static void miOverlayHandleExposures(WindowPtr);
     81 static void miOverlayMoveWindow(WindowPtr, int, int, WindowPtr, VTKind);
     82 static void miOverlayWindowExposures(WindowPtr, RegionPtr);
     83 static void miOverlayResizeWindow(WindowPtr, int, int, unsigned int,
     84                                   unsigned int, WindowPtr);
     85 static void miOverlayClearToBackground(WindowPtr, int, int, int, int, Bool);
     86 
     87 static void miOverlaySetShape(WindowPtr, int);
     88 static 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 
    107 Bool
    108 miInitOverlay(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 
    162 static Bool
    163 miOverlayCloseScreen(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 
    178 static Bool
    179 miOverlayCreateWindow(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 
    228 static Bool
    229 miOverlayDestroyWindow(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 
    261 static Bool
    262 miOverlayUnrealizeWindow(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 
    281 static Bool
    282 miOverlayRealizeWindow(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 
    308 static void
    309 miOverlayReparentWindow(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 
    317 static void
    318 miOverlayRestackWindow(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 
    326 static Bool
    327 miOverlayMarkOverlappedWindows(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 
    452 static void
    453 miOverlayComputeClips(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 
    647 static void
    648 miOverlayMarkWindow(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 
    700 static void
    701 miOverlayMarkUnrealizedWindow(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 
    720 static int
    721 miOverlayValidateTree(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 
    823 static void
    824 miOverlayHandleExposures(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 
    908 static void
    909 miOverlayMoveWindow(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 
    982 static void
    983 miOverlayWindowExposures(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 
   1021 typedef struct {
   1022     RegionPtr over;
   1023     RegionPtr under;
   1024 } miOverlayTwoRegions;
   1025 
   1026 static int
   1027 miOverlayRecomputeExposures(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 
   1061 static void
   1062 miOverlayResizeWindow(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 
   1431 static void
   1432 miOverlaySetShape(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 
   1480 static void
   1481 miOverlayChangeBorderWidth(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 
   1534 void
   1535 miOverlaySetRootClip(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 
   1558 static void
   1559 miOverlayClearToBackground(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(&reg, &box, 1);
   1605 
   1606     RegionIntersect(&reg, &reg, clipList);
   1607     if (generateExposures)
   1608         (*pScreen->WindowExposures) (pWin, &reg);
   1609     else if (pWin->backgroundState != None)
   1610         pScreen->PaintWindow(pWin, &reg, PW_BACKGROUND);
   1611     RegionUninit(&reg);
   1612 }
   1613 
   1614 /****************************************************************/
   1615 
   1616 /* not used */
   1617 Bool
   1618 miOverlayGetPrivateClips(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 
   1634 void
   1635 miOverlaySetTransFunction(ScreenPtr pScreen, miOverlayTransFunc transFunc)
   1636 {
   1637     MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent = transFunc;
   1638 }
   1639 
   1640 Bool
   1641 miOverlayCopyUnderlay(ScreenPtr pScreen)
   1642 {
   1643     return MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->copyUnderlay;
   1644 }
   1645 
   1646 void
   1647 miOverlayComputeCompositeClip(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 
   1702 Bool
   1703 miOverlayCollectUnderlayRegions(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 
   1719 static miOverlayTreePtr
   1720 DoLeaf(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 
   1741 static void
   1742 RebuildTree(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 
   1786 static Bool
   1787 HasUnderlayChildren(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 
   1815 static Bool
   1816 CollectUnderlayChildrenRegions(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 
   1855 static void
   1856 MarkUnderlayWindow(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 }