xserver

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

miwindow.c (27083B)


      1 
      2 /***********************************************************
      3 
      4 Copyright 1987, 1998  The Open Group
      5 
      6 Permission to use, copy, modify, distribute, and sell this software and its
      7 documentation for any purpose is hereby granted without fee, provided that
      8 the above copyright notice appear in all copies and that both that
      9 copyright notice and this permission notice appear in supporting
     10 documentation.
     11 
     12 The above copyright notice and this permission notice shall be included in
     13 all copies or substantial portions of the Software.
     14 
     15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     21 
     22 Except as contained in this notice, the name of The Open Group shall not be
     23 used in advertising or otherwise to promote the sale, use or other dealings
     24 in this Software without prior written authorization from The Open Group.
     25 
     26 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
     27 
     28                         All Rights Reserved
     29 
     30 Permission to use, copy, modify, and distribute this software and its
     31 documentation for any purpose and without fee is hereby granted,
     32 provided that the above copyright notice appear in all copies and that
     33 both that copyright notice and this permission notice appear in
     34 supporting documentation, and that the name of Digital not be
     35 used in advertising or publicity pertaining to distribution of the
     36 software without specific, written prior permission.
     37 
     38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     44 SOFTWARE.
     45 
     46 ******************************************************************/
     47 #ifdef HAVE_DIX_CONFIG_H
     48 #include <dix-config.h>
     49 #endif
     50 
     51 #include <X11/X.h>
     52 #include <X11/extensions/shapeconst.h>
     53 #include "regionstr.h"
     54 #include "region.h"
     55 #include "mi.h"
     56 #include "windowstr.h"
     57 #include "scrnintstr.h"
     58 #include "pixmapstr.h"
     59 #include "mivalidate.h"
     60 #include "inputstr.h"
     61 
     62 void
     63 miClearToBackground(WindowPtr pWin,
     64                     int x, int y, int w, int h, Bool generateExposures)
     65 {
     66     BoxRec box;
     67     RegionRec reg;
     68     BoxPtr extents;
     69     int x1, y1, x2, y2;
     70 
     71     /* compute everything using ints to avoid overflow */
     72 
     73     x1 = pWin->drawable.x + x;
     74     y1 = pWin->drawable.y + y;
     75     if (w)
     76         x2 = x1 + (int) w;
     77     else
     78         x2 = x1 + (int) pWin->drawable.width - (int) x;
     79     if (h)
     80         y2 = y1 + h;
     81     else
     82         y2 = y1 + (int) pWin->drawable.height - (int) y;
     83 
     84     extents = &pWin->clipList.extents;
     85 
     86     /* clip the resulting rectangle to the window clipList extents.  This
     87      * makes sure that the result will fit in a box, given that the
     88      * screen is < 32768 on a side.
     89      */
     90 
     91     if (x1 < extents->x1)
     92         x1 = extents->x1;
     93     if (x2 > extents->x2)
     94         x2 = extents->x2;
     95     if (y1 < extents->y1)
     96         y1 = extents->y1;
     97     if (y2 > extents->y2)
     98         y2 = extents->y2;
     99 
    100     if (x2 <= x1 || y2 <= y1) {
    101         x2 = x1 = 0;
    102         y2 = y1 = 0;
    103     }
    104 
    105     box.x1 = x1;
    106     box.x2 = x2;
    107     box.y1 = y1;
    108     box.y2 = y2;
    109 
    110     RegionInit(&reg, &box, 1);
    111 
    112     RegionIntersect(&reg, &reg, &pWin->clipList);
    113     if (generateExposures)
    114         (*pWin->drawable.pScreen->WindowExposures) (pWin, &reg);
    115     else if (pWin->backgroundState != None)
    116         pWin->drawable.pScreen->PaintWindow(pWin, &reg, PW_BACKGROUND);
    117     RegionUninit(&reg);
    118 }
    119 
    120 void
    121 miMarkWindow(WindowPtr pWin)
    122 {
    123     ValidatePtr val;
    124 
    125     if (pWin->valdata)
    126         return;
    127     val = (ValidatePtr) xnfalloc(sizeof(ValidateRec));
    128     val->before.oldAbsCorner.x = pWin->drawable.x;
    129     val->before.oldAbsCorner.y = pWin->drawable.y;
    130     val->before.borderVisible = NullRegion;
    131     val->before.resized = FALSE;
    132     pWin->valdata = val;
    133 }
    134 
    135 Bool
    136 miMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, WindowPtr *ppLayerWin)
    137 {
    138     BoxPtr box;
    139     WindowPtr pChild, pLast;
    140     Bool anyMarked = FALSE;
    141     MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow;
    142 
    143     /* single layered systems are easy */
    144     if (ppLayerWin)
    145         *ppLayerWin = pWin;
    146 
    147     if (pWin == pFirst) {
    148         /* Blindly mark pWin and all of its inferiors.   This is a slight
    149          * overkill if there are mapped windows that outside pWin's border,
    150          * but it's better than wasting time on RectIn checks.
    151          */
    152         pChild = pWin;
    153         while (1) {
    154             if (pChild->viewable) {
    155                 if (RegionBroken(&pChild->winSize))
    156                     SetWinSize(pChild);
    157                 if (RegionBroken(&pChild->borderSize))
    158                     SetBorderSize(pChild);
    159                 (*MarkWindow) (pChild);
    160                 if (pChild->firstChild) {
    161                     pChild = pChild->firstChild;
    162                     continue;
    163                 }
    164             }
    165             while (!pChild->nextSib && (pChild != pWin))
    166                 pChild = pChild->parent;
    167             if (pChild == pWin)
    168                 break;
    169             pChild = pChild->nextSib;
    170         }
    171         anyMarked = TRUE;
    172         pFirst = pFirst->nextSib;
    173     }
    174     if ((pChild = pFirst)) {
    175         box = RegionExtents(&pWin->borderSize);
    176         pLast = pChild->parent->lastChild;
    177         while (1) {
    178             if (pChild->viewable) {
    179                 if (RegionBroken(&pChild->winSize))
    180                     SetWinSize(pChild);
    181                 if (RegionBroken(&pChild->borderSize))
    182                     SetBorderSize(pChild);
    183                 if (RegionContainsRect(&pChild->borderSize, box)) {
    184                     (*MarkWindow) (pChild);
    185                     anyMarked = TRUE;
    186                     if (pChild->firstChild) {
    187                         pChild = pChild->firstChild;
    188                         continue;
    189                     }
    190                 }
    191             }
    192             while (!pChild->nextSib && (pChild != pLast))
    193                 pChild = pChild->parent;
    194             if (pChild == pLast)
    195                 break;
    196             pChild = pChild->nextSib;
    197         }
    198     }
    199     if (anyMarked)
    200         (*MarkWindow) (pWin->parent);
    201     return anyMarked;
    202 }
    203 
    204 /*****
    205  *  miHandleValidateExposures(pWin)
    206  *    starting at pWin, draw background in any windows that have exposure
    207  *    regions, translate the regions, restore any backing store,
    208  *    and then send any regions still exposed to the client
    209  *****/
    210 void
    211 miHandleValidateExposures(WindowPtr pWin)
    212 {
    213     WindowPtr pChild;
    214     ValidatePtr val;
    215     WindowExposuresProcPtr WindowExposures;
    216 
    217     pChild = pWin;
    218     WindowExposures = pChild->drawable.pScreen->WindowExposures;
    219     while (1) {
    220         if ((val = pChild->valdata)) {
    221             if (RegionNotEmpty(&val->after.borderExposed))
    222                 pWin->drawable.pScreen->PaintWindow(pChild,
    223                                                     &val->after.borderExposed,
    224                                                     PW_BORDER);
    225             RegionUninit(&val->after.borderExposed);
    226             (*WindowExposures) (pChild, &val->after.exposed);
    227             RegionUninit(&val->after.exposed);
    228             free(val);
    229             pChild->valdata = NULL;
    230             if (pChild->firstChild) {
    231                 pChild = pChild->firstChild;
    232                 continue;
    233             }
    234         }
    235         while (!pChild->nextSib && (pChild != pWin))
    236             pChild = pChild->parent;
    237         if (pChild == pWin)
    238             break;
    239         pChild = pChild->nextSib;
    240     }
    241 }
    242 
    243 void
    244 miMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pNextSib, VTKind kind)
    245 {
    246     WindowPtr pParent;
    247     Bool WasViewable = (Bool) (pWin->viewable);
    248     short bw;
    249     RegionPtr oldRegion = NULL;
    250     DDXPointRec oldpt;
    251     Bool anyMarked = FALSE;
    252     ScreenPtr pScreen;
    253     WindowPtr windowToValidate;
    254     WindowPtr pLayerWin;
    255 
    256     /* if this is a root window, can't be moved */
    257     if (!(pParent = pWin->parent))
    258         return;
    259     pScreen = pWin->drawable.pScreen;
    260     bw = wBorderWidth(pWin);
    261 
    262     oldpt.x = pWin->drawable.x;
    263     oldpt.y = pWin->drawable.y;
    264     if (WasViewable) {
    265         oldRegion = RegionCreate(NullBox, 1);
    266         RegionCopy(oldRegion, &pWin->borderClip);
    267         anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin);
    268     }
    269     pWin->origin.x = x + (int) bw;
    270     pWin->origin.y = y + (int) bw;
    271     x = pWin->drawable.x = pParent->drawable.x + x + (int) bw;
    272     y = pWin->drawable.y = pParent->drawable.y + y + (int) bw;
    273 
    274     SetWinSize(pWin);
    275     SetBorderSize(pWin);
    276 
    277     (*pScreen->PositionWindow) (pWin, x, y);
    278 
    279     windowToValidate = MoveWindowInStack(pWin, pNextSib);
    280 
    281     ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0);
    282 
    283     if (WasViewable) {
    284         if (pLayerWin == pWin)
    285             anyMarked |= (*pScreen->MarkOverlappedWindows)
    286                 (pWin, windowToValidate, NULL);
    287         else
    288             anyMarked |= (*pScreen->MarkOverlappedWindows)
    289                 (pWin, pLayerWin, NULL);
    290 
    291         if (anyMarked) {
    292             (*pScreen->ValidateTree) (pLayerWin->parent, NullWindow, kind);
    293             (*pWin->drawable.pScreen->CopyWindow) (pWin, oldpt, oldRegion);
    294             RegionDestroy(oldRegion);
    295             /* XXX need to retile border if ParentRelative origin */
    296             (*pScreen->HandleExposures) (pLayerWin->parent);
    297             if (pScreen->PostValidateTree)
    298                 (*pScreen->PostValidateTree) (pLayerWin->parent, NULL, kind);
    299         }
    300     }
    301     if (pWin->realized)
    302         WindowsRestructured();
    303 }
    304 
    305 /*
    306  * pValid is a region of the screen which has been
    307  * successfully copied -- recomputed exposed regions for affected windows
    308  */
    309 
    310 static int
    311 miRecomputeExposures(WindowPtr pWin, void *value)
    312 {                               /* must conform to VisitWindowProcPtr */
    313     RegionPtr pValid = (RegionPtr) value;
    314 
    315     if (pWin->valdata) {
    316 #ifdef COMPOSITE
    317         /*
    318          * Redirected windows are not affected by parent window
    319          * gravity manipulations, so don't recompute their
    320          * exposed areas here.
    321          */
    322         if (pWin->redirectDraw != RedirectDrawNone)
    323             return WT_DONTWALKCHILDREN;
    324 #endif
    325         /*
    326          * compute exposed regions of this window
    327          */
    328         RegionSubtract(&pWin->valdata->after.exposed, &pWin->clipList, pValid);
    329         /*
    330          * compute exposed regions of the border
    331          */
    332         RegionSubtract(&pWin->valdata->after.borderExposed,
    333                        &pWin->borderClip, &pWin->winSize);
    334         RegionSubtract(&pWin->valdata->after.borderExposed,
    335                        &pWin->valdata->after.borderExposed, pValid);
    336         return WT_WALKCHILDREN;
    337     }
    338     return WT_NOMATCH;
    339 }
    340 
    341 void
    342 miResizeWindow(WindowPtr pWin, int x, int y, unsigned int w, unsigned int h,
    343                WindowPtr pSib)
    344 {
    345     WindowPtr pParent;
    346     Bool WasViewable = (Bool) (pWin->viewable);
    347     unsigned short width = pWin->drawable.width, height = pWin->drawable.height;
    348     short oldx = pWin->drawable.x, oldy = pWin->drawable.y;
    349     int bw = wBorderWidth(pWin);
    350     short dw, dh;
    351     DDXPointRec oldpt;
    352     RegionPtr oldRegion = NULL;
    353     Bool anyMarked = FALSE;
    354     ScreenPtr pScreen;
    355     WindowPtr pFirstChange;
    356     WindowPtr pChild;
    357     RegionPtr gravitate[StaticGravity + 1];
    358     unsigned g;
    359     int nx, ny;                 /* destination x,y */
    360     int newx, newy;             /* new inner window position */
    361     RegionPtr pRegion = NULL;
    362     RegionPtr destClip;         /* portions of destination already written */
    363     RegionPtr oldWinClip = NULL;        /* old clip list for window */
    364     RegionPtr borderVisible = NullRegion;       /* visible area of the border */
    365     Bool shrunk = FALSE;        /* shrunk in an inner dimension */
    366     Bool moved = FALSE;         /* window position changed */
    367     WindowPtr pLayerWin;
    368 
    369     /* if this is a root window, can't be resized */
    370     if (!(pParent = pWin->parent))
    371         return;
    372 
    373     pScreen = pWin->drawable.pScreen;
    374     newx = pParent->drawable.x + x + bw;
    375     newy = pParent->drawable.y + y + bw;
    376     if (WasViewable) {
    377         anyMarked = FALSE;
    378         /*
    379          * save the visible region of the window
    380          */
    381         oldRegion = RegionCreate(NullBox, 1);
    382         RegionCopy(oldRegion, &pWin->winSize);
    383 
    384         /*
    385          * categorize child windows into regions to be moved
    386          */
    387         for (g = 0; g <= StaticGravity; g++)
    388             gravitate[g] = (RegionPtr) NULL;
    389         for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
    390             g = pChild->winGravity;
    391             if (g != UnmapGravity) {
    392                 if (!gravitate[g])
    393                     gravitate[g] = RegionCreate(NullBox, 1);
    394                 RegionUnion(gravitate[g], gravitate[g], &pChild->borderClip);
    395             }
    396             else {
    397                 UnmapWindow(pChild, TRUE);
    398                 anyMarked = TRUE;
    399             }
    400         }
    401         anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin);
    402 
    403         oldWinClip = NULL;
    404         if (pWin->bitGravity != ForgetGravity) {
    405             oldWinClip = RegionCreate(NullBox, 1);
    406             RegionCopy(oldWinClip, &pWin->clipList);
    407         }
    408         /*
    409          * if the window is changing size, borderExposed
    410          * can't be computed correctly without some help.
    411          */
    412         if (pWin->drawable.height > h || pWin->drawable.width > w)
    413             shrunk = TRUE;
    414 
    415         if (newx != oldx || newy != oldy)
    416             moved = TRUE;
    417 
    418         if ((pWin->drawable.height != h || pWin->drawable.width != w) &&
    419             HasBorder(pWin)) {
    420             borderVisible = RegionCreate(NullBox, 1);
    421             /* for tiled borders, we punt and draw the whole thing */
    422             if (pWin->borderIsPixel || !moved) {
    423                 if (shrunk || moved)
    424                     RegionSubtract(borderVisible,
    425                                    &pWin->borderClip, &pWin->winSize);
    426                 else
    427                     RegionCopy(borderVisible, &pWin->borderClip);
    428             }
    429         }
    430     }
    431     pWin->origin.x = x + bw;
    432     pWin->origin.y = y + bw;
    433     pWin->drawable.height = h;
    434     pWin->drawable.width = w;
    435 
    436     x = pWin->drawable.x = newx;
    437     y = pWin->drawable.y = newy;
    438 
    439     SetWinSize(pWin);
    440     SetBorderSize(pWin);
    441 
    442     dw = (int) w - (int) width;
    443     dh = (int) h - (int) height;
    444     ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh);
    445 
    446     /* let the hardware adjust background and border pixmaps, if any */
    447     (*pScreen->PositionWindow) (pWin, x, y);
    448 
    449     pFirstChange = MoveWindowInStack(pWin, pSib);
    450 
    451     if (WasViewable) {
    452         pRegion = RegionCreate(NullBox, 1);
    453 
    454         if (pLayerWin == pWin)
    455             anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pFirstChange,
    456                                                             NULL);
    457         else
    458             anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pLayerWin,
    459                                                             NULL);
    460 
    461         if (pWin->valdata) {
    462             pWin->valdata->before.resized = TRUE;
    463             pWin->valdata->before.borderVisible = borderVisible;
    464         }
    465 
    466         if (anyMarked)
    467             (*pScreen->ValidateTree) (pLayerWin->parent, pFirstChange, VTOther);
    468         /*
    469          * the entire window is trashed unless bitGravity
    470          * recovers portions of it
    471          */
    472         RegionCopy(&pWin->valdata->after.exposed, &pWin->clipList);
    473     }
    474 
    475     GravityTranslate(x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny);
    476 
    477     if (WasViewable) {
    478         /* avoid the border */
    479         if (HasBorder(pWin)) {
    480             int offx, offy, dx, dy;
    481 
    482             /* kruft to avoid double translates for each gravity */
    483             offx = 0;
    484             offy = 0;
    485             for (g = 0; g <= StaticGravity; g++) {
    486                 if (!gravitate[g])
    487                     continue;
    488 
    489                 /* align winSize to gravitate[g].
    490                  * winSize is in new coordinates,
    491                  * gravitate[g] is still in old coordinates */
    492                 GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny);
    493 
    494                 dx = (oldx - nx) - offx;
    495                 dy = (oldy - ny) - offy;
    496                 if (dx || dy) {
    497                     RegionTranslate(&pWin->winSize, dx, dy);
    498                     offx += dx;
    499                     offy += dy;
    500                 }
    501                 RegionIntersect(gravitate[g], gravitate[g], &pWin->winSize);
    502             }
    503             /* get winSize back where it belongs */
    504             if (offx || offy)
    505                 RegionTranslate(&pWin->winSize, -offx, -offy);
    506         }
    507         /*
    508          * add screen bits to the appropriate bucket
    509          */
    510 
    511         if (oldWinClip) {
    512             /*
    513              * clip to new clipList
    514              */
    515             RegionCopy(pRegion, oldWinClip);
    516             RegionTranslate(pRegion, nx - oldx, ny - oldy);
    517             RegionIntersect(oldWinClip, pRegion, &pWin->clipList);
    518             /*
    519              * don't step on any gravity bits which will be copied after this
    520              * region.  Note -- this assumes that the regions will be copied
    521              * in gravity order.
    522              */
    523             for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) {
    524                 if (gravitate[g])
    525                     RegionSubtract(oldWinClip, oldWinClip, gravitate[g]);
    526             }
    527             RegionTranslate(oldWinClip, oldx - nx, oldy - ny);
    528             g = pWin->bitGravity;
    529             if (!gravitate[g])
    530                 gravitate[g] = oldWinClip;
    531             else {
    532                 RegionUnion(gravitate[g], gravitate[g], oldWinClip);
    533                 RegionDestroy(oldWinClip);
    534             }
    535         }
    536 
    537         /*
    538          * move the bits on the screen
    539          */
    540 
    541         destClip = NULL;
    542 
    543         for (g = 0; g <= StaticGravity; g++) {
    544             if (!gravitate[g])
    545                 continue;
    546 
    547             GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny);
    548 
    549             oldpt.x = oldx + (x - nx);
    550             oldpt.y = oldy + (y - ny);
    551 
    552             /* Note that gravitate[g] is *translated* by CopyWindow */
    553 
    554             /* only copy the remaining useful bits */
    555 
    556             RegionIntersect(gravitate[g], gravitate[g], oldRegion);
    557 
    558             /* clip to not overwrite already copied areas */
    559 
    560             if (destClip) {
    561                 RegionTranslate(destClip, oldpt.x - x, oldpt.y - y);
    562                 RegionSubtract(gravitate[g], gravitate[g], destClip);
    563                 RegionTranslate(destClip, x - oldpt.x, y - oldpt.y);
    564             }
    565 
    566             /* and move those bits */
    567 
    568             if (oldpt.x != x || oldpt.y != y
    569 #ifdef COMPOSITE
    570                 || pWin->redirectDraw
    571 #endif
    572                 ) {
    573                 (*pWin->drawable.pScreen->CopyWindow) (pWin, oldpt,
    574                                                        gravitate[g]);
    575             }
    576 
    577             /* remove any overwritten bits from the remaining useful bits */
    578 
    579             RegionSubtract(oldRegion, oldRegion, gravitate[g]);
    580 
    581             /*
    582              * recompute exposed regions of child windows
    583              */
    584 
    585             for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
    586                 if (pChild->winGravity != g)
    587                     continue;
    588                 RegionIntersect(pRegion, &pChild->borderClip, gravitate[g]);
    589                 TraverseTree(pChild, miRecomputeExposures, (void *) pRegion);
    590             }
    591 
    592             /*
    593              * remove the successfully copied regions of the
    594              * window from its exposed region
    595              */
    596 
    597             if (g == pWin->bitGravity)
    598                 RegionSubtract(&pWin->valdata->after.exposed,
    599                                &pWin->valdata->after.exposed, gravitate[g]);
    600             if (!destClip)
    601                 destClip = gravitate[g];
    602             else {
    603                 RegionUnion(destClip, destClip, gravitate[g]);
    604                 RegionDestroy(gravitate[g]);
    605             }
    606         }
    607 
    608         RegionDestroy(oldRegion);
    609         RegionDestroy(pRegion);
    610         if (destClip)
    611             RegionDestroy(destClip);
    612         if (anyMarked) {
    613             (*pScreen->HandleExposures) (pLayerWin->parent);
    614             if (pScreen->PostValidateTree)
    615                 (*pScreen->PostValidateTree) (pLayerWin->parent, pFirstChange,
    616                                               VTOther);
    617         }
    618     }
    619     if (pWin->realized)
    620         WindowsRestructured();
    621 }
    622 
    623 WindowPtr
    624 miGetLayerWindow(WindowPtr pWin)
    625 {
    626     return pWin->firstChild;
    627 }
    628 
    629 /******
    630  *
    631  * miSetShape
    632  *    The border/window shape has changed.  Recompute winSize/borderSize
    633  *    and send appropriate exposure events
    634  */
    635 
    636 void
    637 miSetShape(WindowPtr pWin, int kind)
    638 {
    639     Bool WasViewable = (Bool) (pWin->viewable);
    640     ScreenPtr pScreen = pWin->drawable.pScreen;
    641     Bool anyMarked = FALSE;
    642     WindowPtr pLayerWin;
    643 
    644     if (kind != ShapeInput) {
    645         if (WasViewable) {
    646             anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin,
    647                                                            &pLayerWin);
    648             if (pWin->valdata) {
    649                 if (HasBorder(pWin)) {
    650                     RegionPtr borderVisible;
    651 
    652                     borderVisible = RegionCreate(NullBox, 1);
    653                     RegionSubtract(borderVisible,
    654                                    &pWin->borderClip, &pWin->winSize);
    655                     pWin->valdata->before.borderVisible = borderVisible;
    656                 }
    657                 pWin->valdata->before.resized = TRUE;
    658             }
    659         }
    660 
    661         SetWinSize(pWin);
    662         SetBorderSize(pWin);
    663 
    664         ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
    665 
    666         if (WasViewable) {
    667             anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL);
    668 
    669             if (anyMarked) {
    670                 (*pScreen->ValidateTree) (pLayerWin->parent, NullWindow,
    671                                           VTOther);
    672                 (*pScreen->HandleExposures) (pLayerWin->parent);
    673                 if (pScreen->PostValidateTree)
    674                     (*pScreen->PostValidateTree) (pLayerWin->parent, NULL,
    675                                                   VTOther);
    676             }
    677         }
    678     }
    679     if (pWin->realized)
    680         WindowsRestructured();
    681     CheckCursorConfinement(pWin);
    682 }
    683 
    684 /* Keeps the same inside(!) origin */
    685 
    686 void
    687 miChangeBorderWidth(WindowPtr pWin, unsigned int width)
    688 {
    689     int oldwidth;
    690     Bool anyMarked = FALSE;
    691     ScreenPtr pScreen;
    692     Bool WasViewable = (Bool) (pWin->viewable);
    693     Bool HadBorder;
    694     WindowPtr pLayerWin;
    695 
    696     oldwidth = wBorderWidth(pWin);
    697     if (oldwidth == width)
    698         return;
    699     HadBorder = HasBorder(pWin);
    700     pScreen = pWin->drawable.pScreen;
    701     if (WasViewable && width < oldwidth)
    702         anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin);
    703 
    704     pWin->borderWidth = width;
    705     SetBorderSize(pWin);
    706 
    707     if (WasViewable) {
    708         if (width > oldwidth) {
    709             anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin,
    710                                                            &pLayerWin);
    711             /*
    712              * save the old border visible region to correctly compute
    713              * borderExposed.
    714              */
    715             if (pWin->valdata && HadBorder) {
    716                 RegionPtr borderVisible;
    717 
    718                 borderVisible = RegionCreate(NULL, 1);
    719                 RegionSubtract(borderVisible,
    720                                &pWin->borderClip, &pWin->winSize);
    721                 pWin->valdata->before.borderVisible = borderVisible;
    722             }
    723         }
    724 
    725         if (anyMarked) {
    726             (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTOther);
    727             (*pScreen->HandleExposures) (pLayerWin->parent);
    728             if (pScreen->PostValidateTree)
    729                 (*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin,
    730                                               VTOther);
    731         }
    732     }
    733     if (pWin->realized)
    734         WindowsRestructured();
    735 }
    736 
    737 void
    738 miMarkUnrealizedWindow(WindowPtr pChild, WindowPtr pWin, Bool fromConfigure)
    739 {
    740     if ((pChild != pWin) || fromConfigure) {
    741         RegionEmpty(&pChild->clipList);
    742         if (pChild->drawable.pScreen->ClipNotify)
    743             (*pChild->drawable.pScreen->ClipNotify) (pChild, 0, 0);
    744         RegionEmpty(&pChild->borderClip);
    745     }
    746 }
    747 
    748 WindowPtr
    749 miSpriteTrace(SpritePtr pSprite, int x, int y)
    750 {
    751     WindowPtr pWin;
    752     BoxRec box;
    753 
    754     pWin = DeepestSpriteWin(pSprite)->firstChild;
    755     while (pWin) {
    756         if ((pWin->mapped) &&
    757             (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
    758             (x < pWin->drawable.x + (int) pWin->drawable.width +
    759              wBorderWidth(pWin)) &&
    760             (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
    761             (y < pWin->drawable.y + (int) pWin->drawable.height +
    762              wBorderWidth(pWin))
    763             /* When a window is shaped, a further check
    764              * is made to see if the point is inside
    765              * borderSize
    766              */
    767             && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
    768             && (!wInputShape(pWin) ||
    769                 RegionContainsPoint(wInputShape(pWin),
    770                                     x - pWin->drawable.x,
    771                                     y - pWin->drawable.y, &box))
    772             /* In rootless mode windows may be offscreen, even when
    773              * they're in X's stack. (E.g. if the native window system
    774              * implements some form of virtual desktop system).
    775              */
    776             && !pWin->unhittable) {
    777             if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) {
    778                 pSprite->spriteTraceSize += 10;
    779                 pSprite->spriteTrace = reallocarray(pSprite->spriteTrace,
    780                                                     pSprite->spriteTraceSize,
    781                                                     sizeof(WindowPtr));
    782             }
    783             pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
    784             pWin = pWin->firstChild;
    785         }
    786         else
    787             pWin = pWin->nextSib;
    788     }
    789     return DeepestSpriteWin(pSprite);
    790 }
    791 
    792 /**
    793  * Traversed from the root window to the window at the position x/y. While
    794  * traversing, it sets up the traversal history in the spriteTrace array.
    795  * After completing, the spriteTrace history is set in the following way:
    796  *   spriteTrace[0] ... root window
    797  *   spriteTrace[1] ... top level window that encloses x/y
    798  *       ...
    799  *   spriteTrace[spriteTraceGood - 1] ... window at x/y
    800  *
    801  * @returns the window at the given coordinates.
    802  */
    803 WindowPtr
    804 miXYToWindow(ScreenPtr pScreen, SpritePtr pSprite, int x, int y)
    805 {
    806     pSprite->spriteTraceGood = 1;       /* root window still there */
    807     return miSpriteTrace(pSprite, x, y);
    808 }