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
miClearToBackground(WindowPtr pWin,int x,int y,int w,int h,Bool generateExposures)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
miMarkWindow(WindowPtr pWin)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
miMarkOverlappedWindows(WindowPtr pWin,WindowPtr pFirst,WindowPtr * ppLayerWin)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
miHandleValidateExposures(WindowPtr pWin)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
miMoveWindow(WindowPtr pWin,int x,int y,WindowPtr pNextSib,VTKind kind)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
miRecomputeExposures(WindowPtr pWin,void * value)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
miResizeWindow(WindowPtr pWin,int x,int y,unsigned int w,unsigned int h,WindowPtr pSib)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
miGetLayerWindow(WindowPtr pWin)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
miSetShape(WindowPtr pWin,int kind)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
miChangeBorderWidth(WindowPtr pWin,unsigned int width)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
miMarkUnrealizedWindow(WindowPtr pChild,WindowPtr pWin,Bool fromConfigure)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
miSpriteTrace(SpritePtr pSprite,int x,int y)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
miXYToWindow(ScreenPtr pScreen,SpritePtr pSprite,int x,int y)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 }
809