1
2/***********************************************************
3
4Copyright 1987, 1998  The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall not be
23used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from The Open Group.
25
26Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
27
28                        All Rights Reserved
29
30Permission to use, copy, modify, and distribute this software and its
31documentation for any purpose and without fee is hereby granted,
32provided that the above copyright notice appear in all copies and that
33both that copyright notice and this permission notice appear in
34supporting documentation, and that the name of Digital not be
35used in advertising or publicity pertaining to distribution of the
36software without specific, written prior permission.
37
38DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44SOFTWARE.
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
62void
63miClearToBackground(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
120void
121miMarkWindow(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
135Bool
136miMarkOverlappedWindows(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 *****/
210void
211miHandleValidateExposures(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
243void
244miMoveWindow(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
310static int
311miRecomputeExposures(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
341void
342miResizeWindow(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
623WindowPtr
624miGetLayerWindow(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
636void
637miSetShape(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
686void
687miChangeBorderWidth(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
737void
738miMarkUnrealizedWindow(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
748WindowPtr
749miSpriteTrace(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 */
803WindowPtr
804miXYToWindow(ScreenPtr pScreen, SpritePtr pSprite, int x, int y)
805{
806    pSprite->spriteTraceGood = 1;       /* root window still there */
807    return miSpriteTrace(pSprite, x, y);
808}
809