]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/mi/miwindow.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / programs / Xserver / mi / miwindow.c
1 /***********************************************************
2
3 Copyright (c) 1987  X Consortium
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
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 X CONSORTIUM 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 X Consortium 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 X Consortium.
25
26
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
28
29                         All Rights Reserved
30
31 Permission to use, copy, modify, and distribute this software and its 
32 documentation for any purpose and without fee is hereby granted, 
33 provided that the above copyright notice appear in all copies and that
34 both that copyright notice and this permission notice appear in 
35 supporting documentation, and that the name of Digital not be
36 used in advertising or publicity pertaining to distribution of the
37 software without specific, written prior permission.  
38
39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 SOFTWARE.
46
47 ******************************************************************/
48 /* $XConsortium: miwindow.c,v 5.16 94/04/17 20:28:03 dpw Exp $ */
49 #include "X.h"
50 #include "miscstruct.h"
51 #include "region.h"
52 #include "mi.h"
53 #include "windowstr.h"
54 #include "scrnintstr.h"
55 #include "pixmapstr.h"
56 #include "mivalidate.h"
57
58 void 
59 miClearToBackground(pWin, x, y, w, h, generateExposures)
60     WindowPtr pWin;
61     int x,y;
62     int w,h;
63     Bool generateExposures;
64 {
65     BoxRec box;
66     RegionRec   reg;
67     RegionPtr pBSReg = NullRegion;
68     ScreenPtr   pScreen;
69     BoxPtr  extents;
70     int     x1, y1, x2, y2;
71
72     /* compute everything using ints to avoid overflow */
73
74     x1 = pWin->drawable.x + x;
75     y1 = pWin->drawable.y + y;
76     if (w)
77         x2 = x1 + (int) w;
78     else
79         x2 = x1 + (int) pWin->drawable.width - (int) x;
80     if (h)
81         y2 = y1 + h;    
82     else
83         y2 = y1 + (int) pWin->drawable.height - (int) y;
84
85     extents = &pWin->clipList.extents;
86     
87     /* clip the resulting rectangle to the window clipList extents.  This
88      * makes sure that the result will fit in a box, given that the
89      * screen is < 32768 on a side.
90      */
91
92     if (x1 < extents->x1)
93         x1 = extents->x1;
94     if (x2 > extents->x2)
95         x2 = extents->x2;
96     if (y1 < extents->y1)
97         y1 = extents->y1;
98     if (y2 > extents->y2)
99         y2 = extents->y2;
100
101     if (x2 <= x1 || y2 <= y1)
102     {
103         x2 = x1 = 0;
104         y2 = y1 = 0;
105     }
106
107     box.x1 = x1;
108     box.x2 = x2;
109     box.y1 = y1;
110     box.y2 = y2;
111
112     pScreen = pWin->drawable.pScreen;
113     REGION_INIT(pScreen, &reg, &box, 1);
114     if (pWin->backStorage)
115     {
116         /*
117          * If the window has backing-store on, call through the
118          * ClearToBackground vector to handle the special semantics
119          * (i.e. things backing store is to be cleared out and
120          * an Expose event is to be generated for those areas in backing
121          * store if generateExposures is TRUE).
122          */
123         pBSReg = (* pScreen->ClearBackingStore)(pWin, x, y, w, h,
124                                                  generateExposures);
125     }
126
127     REGION_INTERSECT(pScreen, &reg, &reg, &pWin->clipList);
128     if (generateExposures)
129         (*pScreen->WindowExposures)(pWin, &reg, pBSReg);
130     else if (pWin->backgroundState != None)
131         (*pScreen->PaintWindowBackground)(pWin, &reg, PW_BACKGROUND);
132     REGION_UNINIT(pScreen, &reg);
133     if (pBSReg)
134         REGION_DESTROY(pScreen, pBSReg);
135 }
136
137 /*
138  * For SaveUnders using backing-store. The idea is that when a window is mapped
139  * with saveUnder set TRUE, any windows it obscures will have its backing
140  * store turned on setting the DIXsaveUnder bit,
141  * The backing-store code must be written to allow for this
142  */
143
144 /*-
145  *-----------------------------------------------------------------------
146  * miCheckSubSaveUnder --
147  *      Check all the inferiors of a window for coverage by saveUnder
148  *      windows. Called from ChangeSaveUnder and CheckSaveUnder.
149  *      This code is very inefficient.
150  *
151  * Results:
152  *      TRUE if any windows need to have backing-store removed.
153  *
154  * Side Effects:
155  *      Windows may have backing-store turned on or off.
156  *
157  *-----------------------------------------------------------------------
158  */
159 static Bool
160 miCheckSubSaveUnder(pParent, pFirst, pRegion)
161     register WindowPtr  pParent;        /* Parent to check */
162     WindowPtr           pFirst;         /* first reconfigured window */
163     RegionPtr           pRegion;        /* Initial area obscured by saveUnder */
164 {
165     register WindowPtr  pChild;         /* Current child */
166     register ScreenPtr  pScreen;        /* Screen to use */
167     RegionRec           SubRegion;      /* Area of children obscured */
168     Bool                res = FALSE;    /* result */
169     Bool                subInited=FALSE;/* SubRegion initialized */
170
171     pScreen = pParent->drawable.pScreen;
172     if ( (pChild = pParent->firstChild) )
173     {
174         /*
175          * build region above first changed window
176          */
177
178         for (; pChild != pFirst; pChild = pChild->nextSib)
179             if (pChild->viewable && pChild->saveUnder)
180                 REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize);
181         
182         /*
183          * check region below and including first changed window
184          */
185
186         for (; pChild; pChild = pChild->nextSib)
187         {
188             if (pChild->viewable)
189             {
190                 /*
191                  * don't save under nephew/niece windows;
192                  * use a separate region
193                  */
194
195                 if (pChild->firstChild)
196                 {
197                     if (!subInited)
198                     {
199                         REGION_INIT(pScreen, &SubRegion, NullBox, 0);
200                         subInited = TRUE;
201                     }
202                     REGION_COPY(pScreen, &SubRegion, pRegion);
203                     res |= miCheckSubSaveUnder(pChild, pChild->firstChild,
204                                              &SubRegion);
205                 }
206                 else
207                 {
208                     res |= miCheckSubSaveUnder(pChild, pChild->firstChild,
209                                              pRegion);
210                 }
211
212                 if (pChild->saveUnder)
213                     REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize);
214             }
215         }
216
217         if (subInited)
218             REGION_UNINIT(pScreen, &SubRegion);
219     }
220
221     /*
222      * Check the state of this window.  DIX save unders are
223      * enabled for viewable windows with some client expressing
224      * exposure interest and which intersect the save under region
225      */
226
227     if (pParent->viewable && 
228         ((pParent->eventMask | wOtherEventMasks(pParent)) & ExposureMask) &&
229         REGION_NOTEMPTY(pScreen, &pParent->borderSize) &&
230         RECT_IN_REGION(pScreen, pRegion, REGION_EXTENTS(pScreen, 
231                                         &pParent->borderSize)) != rgnOUT)
232     {
233         if (!pParent->DIXsaveUnder)
234         {
235             pParent->DIXsaveUnder = TRUE;
236             (*pScreen->ChangeWindowAttributes) (pParent, CWBackingStore);
237         }
238     }
239     else
240     {
241         if (pParent->DIXsaveUnder)
242         {
243             res = TRUE;
244             pParent->DIXsaveUnder = FALSE;
245         }
246     }
247     return res;
248 }
249
250
251 /*-
252  *-----------------------------------------------------------------------
253  * miChangeSaveUnder --
254  *      Change the save-under state of a tree of windows. Called when
255  *      a window with saveUnder TRUE is mapped/unmapped/reconfigured.
256  *      
257  * Results:
258  *      TRUE if any windows need to have backing-store removed (which
259  *      means that PostChangeSaveUnder needs to be called later to 
260  *      finish the job).
261  *
262  * Side Effects:
263  *      Windows may have backing-store turned on or off.
264  *
265  *-----------------------------------------------------------------------
266  */
267 Bool
268 miChangeSaveUnder(pWin, first)
269     register WindowPtr  pWin;
270     WindowPtr           first;          /* First window to check.
271                                          * Used when pWin was restacked */
272 {
273     RegionRec   rgn;    /* Area obscured by saveUnder windows */
274     register ScreenPtr pScreen;
275     Bool        res;
276
277     if (!deltaSaveUndersViewable && !numSaveUndersViewable)
278         return FALSE;
279     numSaveUndersViewable += deltaSaveUndersViewable;
280     deltaSaveUndersViewable = 0;
281     pScreen = pWin->drawable.pScreen;
282     REGION_INIT(pScreen, &rgn, NullBox, 1);
283     res = miCheckSubSaveUnder (pWin->parent,
284                                pWin->saveUnder ? first : pWin->nextSib,
285                                &rgn);
286     REGION_UNINIT(pScreen, &rgn);
287     return res;
288 }
289
290 /*-
291  *-----------------------------------------------------------------------
292  * miPostChangeSaveUnder --
293  *      Actually turn backing-store off for those windows that no longer
294  *      need to have it on.
295  *
296  * Results:
297  *      None.
298  *
299  * Side Effects:
300  *      Backing-store and SAVE_UNDER_CHANGE_BIT are turned off for those
301  *      windows affected.
302  *
303  *-----------------------------------------------------------------------
304  */
305 void
306 miPostChangeSaveUnder(pWin, pFirst)
307     WindowPtr           pWin;
308     WindowPtr           pFirst;
309 {
310     register WindowPtr pParent, pChild;
311     ChangeWindowAttributesProcPtr ChangeWindowAttributes;
312
313     if (!(pParent = pWin->parent))
314         return;
315     ChangeWindowAttributes = pParent->drawable.pScreen->ChangeWindowAttributes;
316     if (!pParent->DIXsaveUnder &&
317         (pParent->backingStore == NotUseful) && pParent->backStorage)
318         (*ChangeWindowAttributes)(pParent, CWBackingStore);
319     if (!(pChild = pFirst))
320         return;
321     while (1)
322     {
323         if (!pChild->DIXsaveUnder &&
324             (pChild->backingStore == NotUseful) && pChild->backStorage)
325             (*ChangeWindowAttributes)(pChild, CWBackingStore);
326         if (pChild->firstChild)
327         {
328             pChild = pChild->firstChild;
329             continue;
330         }
331         while (!pChild->nextSib)
332         {
333             pChild = pChild->parent;
334             if (pChild == pParent)
335                 return;
336         }
337         pChild = pChild->nextSib;
338     }
339 }
340
341 void
342 miMarkWindow(pWin)
343     register WindowPtr pWin;
344 {
345     register ValidatePtr val;
346
347     if (pWin->valdata)
348         return;
349     val = (ValidatePtr)xnfalloc(sizeof(ValidateRec));
350     val->before.oldAbsCorner.x = pWin->drawable.x;
351     val->before.oldAbsCorner.y = pWin->drawable.y;
352     val->before.borderVisible = NullRegion;
353     val->before.resized = FALSE;
354     pWin->valdata = val;
355 }
356
357 Bool
358 miMarkOverlappedWindows(pWin, pFirst, ppLayerWin)
359     WindowPtr pWin;
360     WindowPtr pFirst;
361     WindowPtr *ppLayerWin;
362 {
363     register BoxPtr box;
364     register WindowPtr pChild, pLast;
365     Bool anyMarked = FALSE;
366     void (* MarkWindow)() = pWin->drawable.pScreen->MarkWindow;
367     ScreenPtr pScreen = pWin->drawable.pScreen;
368
369     /* single layered systems are easy */
370     if (ppLayerWin) *ppLayerWin = pWin;
371
372     if (pWin == pFirst)
373     {
374         /* Blindly mark pWin and all of its inferiors.   This is a slight
375          * overkill if there are mapped windows that outside pWin's border,
376          * but it's better than wasting time on RectIn checks.
377          */
378         pChild = pWin;
379         while (1)
380         {
381             if (pChild->viewable)
382             {
383                 (* MarkWindow)(pChild);
384                 if (pChild->firstChild)
385                 {
386                     pChild = pChild->firstChild;
387                     continue;
388                 }
389             }
390             while (!pChild->nextSib && (pChild != pWin))
391                 pChild = pChild->parent;
392             if (pChild == pWin)
393                 break;
394             pChild = pChild->nextSib;
395         }
396         anyMarked = TRUE;
397         pFirst = pFirst->nextSib;
398     }
399     if ( (pChild = pFirst) )
400     {
401         box = REGION_EXTENTS(pChild->drawable.pScreen, &pWin->borderSize);
402         pLast = pChild->parent->lastChild;
403         while (1)
404         {
405             if (pChild->viewable && RECT_IN_REGION(pScreen, &pChild->borderSize,
406                                                        box))
407             {
408                 (* MarkWindow)(pChild);
409                 anyMarked = TRUE;
410                 if (pChild->firstChild)
411                 {
412                     pChild = pChild->firstChild;
413                     continue;
414                 }
415             }
416             while (!pChild->nextSib && (pChild != pLast))
417                 pChild = pChild->parent;
418             if (pChild == pLast)
419                 break;
420             pChild = pChild->nextSib;
421         }
422     }
423     if (anyMarked)
424         (* MarkWindow)(pWin->parent);
425     return anyMarked;
426 }
427
428 /*****
429  *  miHandleValidateExposures(pWin)
430  *    starting at pWin, draw background in any windows that have exposure
431  *    regions, translate the regions, restore any backing store,
432  *    and then send any regions still exposed to the client
433  *****/
434 void
435 miHandleValidateExposures(pWin)
436     WindowPtr pWin;
437 {
438     register WindowPtr pChild;
439     register ValidatePtr val;
440     ScreenPtr pScreen = pWin->drawable.pScreen;
441     void (* WindowExposures)();
442
443     pChild = pWin;
444     WindowExposures = pChild->drawable.pScreen->WindowExposures;
445     while (1)
446     {
447         if ( (val = pChild->valdata) )
448         {
449             if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed))
450                 (*pChild->drawable.pScreen->PaintWindowBorder)(pChild,
451                                                     &val->after.borderExposed,
452                                                     PW_BORDER);
453             REGION_UNINIT(pScreen, &val->after.borderExposed);
454             (*WindowExposures)(pChild, &val->after.exposed, NullRegion);
455             REGION_UNINIT(pScreen, &val->after.exposed);
456             xfree(val);
457             pChild->valdata = (ValidatePtr)NULL;
458             if (pChild->firstChild)
459             {
460                 pChild = pChild->firstChild;
461                 continue;
462             }
463         }
464         while (!pChild->nextSib && (pChild != pWin))
465             pChild = pChild->parent;
466         if (pChild == pWin)
467             break;
468         pChild = pChild->nextSib;
469     }
470 }
471
472 void
473 miMoveWindow(pWin, x, y, pNextSib, kind)
474     register WindowPtr pWin;
475     int x,y;
476     WindowPtr pNextSib;
477     VTKind kind;
478 {
479     WindowPtr pParent;
480     Bool WasViewable = (Bool)(pWin->viewable);
481     short bw;
482     RegionPtr oldRegion;
483     DDXPointRec oldpt;
484     Bool anyMarked;
485     register ScreenPtr pScreen;
486     WindowPtr windowToValidate;
487 #ifdef DO_SAVE_UNDERS
488     Bool dosave = FALSE;
489 #endif
490     WindowPtr pLayerWin;
491
492     /* if this is a root window, can't be moved */
493     if (!(pParent = pWin->parent))
494        return ;
495     pScreen = pWin->drawable.pScreen;
496     bw = wBorderWidth (pWin);
497
498     oldpt.x = pWin->drawable.x;
499     oldpt.y = pWin->drawable.y;
500     if (WasViewable)
501     {
502         oldRegion = REGION_CREATE(pScreen, NullBox, 1);
503         REGION_COPY(pScreen, oldRegion, &pWin->borderClip);
504         anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin);
505     }
506     pWin->origin.x = x + (int)bw;
507     pWin->origin.y = y + (int)bw;
508     x = pWin->drawable.x = pParent->drawable.x + x + (int)bw;
509     y = pWin->drawable.y = pParent->drawable.y + y + (int)bw;
510
511     SetWinSize (pWin);
512     SetBorderSize (pWin);
513
514     (*pScreen->PositionWindow)(pWin, x, y);
515
516     windowToValidate = MoveWindowInStack(pWin, pNextSib);
517
518     ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0);
519
520     if (WasViewable)
521     {
522         if (pLayerWin == pWin)
523             anyMarked |= (*pScreen->MarkOverlappedWindows)
524                                 (pWin, windowToValidate, (WindowPtr *)NULL);
525         else
526             anyMarked |= (*pScreen->MarkOverlappedWindows)
527                                 (pWin, pLayerWin, (WindowPtr *)NULL);
528
529 #ifdef DO_SAVE_UNDERS
530         if (DO_SAVE_UNDERS(pWin))
531         {
532             dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, windowToValidate);
533         }
534 #endif /* DO_SAVE_UNDERS */
535
536         if (anyMarked)
537         {
538             (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind);
539             (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion);
540             REGION_DESTROY(pScreen, oldRegion);
541             /* XXX need to retile border if ParentRelative origin */
542             (*pScreen->HandleExposures)(pLayerWin->parent);
543         }
544 #ifdef DO_SAVE_UNDERS
545         if (dosave)
546             (*pScreen->PostChangeSaveUnder)(pLayerWin, windowToValidate);
547 #endif /* DO_SAVE_UNDERS */
548         if (anyMarked && pScreen->PostValidateTree)
549             (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind);
550     }
551     if (pWin->realized)
552         WindowsRestructured ();
553 }
554
555
556 /*
557  * pValid is a region of the screen which has been
558  * successfully copied -- recomputed exposed regions for affected windows
559  */
560
561 static int
562 miRecomputeExposures (pWin, value)
563     register WindowPtr  pWin;
564     pointer             value; /* must conform to VisitWindowProcPtr */
565 {
566     register ScreenPtr  pScreen;
567     RegionPtr   pValid = (RegionPtr)value;
568
569     if (pWin->valdata)
570     {
571         pScreen = pWin->drawable.pScreen;
572         /*
573          * compute exposed regions of this window
574          */
575         REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed,
576                         &pWin->clipList, pValid);
577         /*
578          * compute exposed regions of the border
579          */
580         REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed,
581                              &pWin->borderClip, &pWin->winSize);
582         REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed,
583                              &pWin->valdata->after.borderExposed, pValid);
584         return WT_WALKCHILDREN;
585     }
586     return WT_NOMATCH;
587 }
588
589 void
590 miSlideAndSizeWindow(pWin, x, y, w, h, pSib)
591     register WindowPtr pWin;
592     int x,y;
593     unsigned int w, h;
594     WindowPtr pSib;
595 {
596     WindowPtr pParent;
597     Bool WasViewable = (Bool)(pWin->viewable);
598     unsigned short width = pWin->drawable.width,
599                    height = pWin->drawable.height;
600     short oldx = pWin->drawable.x,
601           oldy = pWin->drawable.y;
602     int bw = wBorderWidth (pWin);
603     short dw, dh;
604     DDXPointRec oldpt;
605     RegionPtr oldRegion;
606     Bool anyMarked;
607     register ScreenPtr pScreen;
608     WindowPtr pFirstChange;
609     register WindowPtr pChild;
610     RegionPtr   gravitate[StaticGravity + 1];
611     register unsigned g;
612     int         nx, ny;         /* destination x,y */
613     int         newx, newy;     /* new inner window position */
614     RegionPtr   pRegion;
615     RegionPtr   destClip;       /* portions of destination already written */
616     RegionPtr   oldWinClip;     /* old clip list for window */
617     RegionPtr   borderVisible = NullRegion; /* visible area of the border */
618     RegionPtr   bsExposed = NullRegion;     /* backing store exposures */
619     Bool        shrunk = FALSE; /* shrunk in an inner dimension */
620     Bool        moved = FALSE;  /* window position changed */
621 #ifdef DO_SAVE_UNDERS
622     Bool        dosave = FALSE;
623 #endif
624     WindowPtr  pLayerWin;
625
626     /* if this is a root window, can't be resized */
627     if (!(pParent = pWin->parent))
628         return ;
629
630     pScreen = pWin->drawable.pScreen;
631     newx = pParent->drawable.x + x + bw;
632     newy = pParent->drawable.y + y + bw;
633     if (WasViewable)
634     {
635         anyMarked = FALSE;
636         /*
637          * save the visible region of the window
638          */
639         oldRegion = REGION_CREATE(pScreen, NullBox, 1);
640         REGION_COPY(pScreen, oldRegion, &pWin->winSize);
641
642         /*
643          * categorize child windows into regions to be moved
644          */
645         for (g = 0; g <= StaticGravity; g++)
646             gravitate[g] = (RegionPtr) NULL;
647         for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
648         {
649             g = pChild->winGravity;
650             if (g != UnmapGravity)
651             {
652                 if (!gravitate[g])
653                     gravitate[g] = REGION_CREATE(pScreen, NullBox, 1);
654                 REGION_UNION(pScreen, gravitate[g],
655                                    gravitate[g], &pChild->borderClip);
656             }
657             else
658             {
659                 UnmapWindow(pChild, TRUE);
660                 anyMarked = TRUE;
661             }
662         }
663         anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, 
664                                                        &pLayerWin);
665
666         oldWinClip = NULL;
667         if (pWin->bitGravity != ForgetGravity)
668         {
669             oldWinClip = REGION_CREATE(pScreen, NullBox, 1);
670             REGION_COPY(pScreen, oldWinClip, &pWin->clipList);
671         }
672         /*
673          * if the window is changing size, borderExposed
674          * can't be computed correctly without some help.
675          */
676         if (pWin->drawable.height > h || pWin->drawable.width > w)
677             shrunk = TRUE;
678
679         if (newx != oldx || newy != oldy)
680             moved = TRUE;
681
682         if ((pWin->drawable.height != h || pWin->drawable.width != w) &&
683             HasBorder (pWin))
684         {
685             borderVisible = REGION_CREATE(pScreen, NullBox, 1);
686             /* for tiled borders, we punt and draw the whole thing */
687             if (pWin->borderIsPixel || !moved)
688             {
689                 if (shrunk || moved)
690                     REGION_SUBTRACT(pScreen, borderVisible,
691                                           &pWin->borderClip,
692                                           &pWin->winSize);
693                 else
694                     REGION_COPY(pScreen, borderVisible,
695                                             &pWin->borderClip);
696             }
697         }
698     }
699     pWin->origin.x = x + bw;
700     pWin->origin.y = y + bw;
701     pWin->drawable.height = h;
702     pWin->drawable.width = w;
703
704     x = pWin->drawable.x = newx;
705     y = pWin->drawable.y = newy;
706
707     SetWinSize (pWin);
708     SetBorderSize (pWin);
709
710     dw = (int)w - (int)width;
711     dh = (int)h - (int)height;
712     ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh);
713
714     /* let the hardware adjust background and border pixmaps, if any */
715     (*pScreen->PositionWindow)(pWin, x, y);
716
717     pFirstChange = MoveWindowInStack(pWin, pSib);
718
719     if (WasViewable)
720     {
721         pRegion = REGION_CREATE(pScreen, NullBox, 1);
722         if (pWin->backStorage)
723             REGION_COPY(pScreen, pRegion, &pWin->clipList);
724
725         if (pLayerWin == pWin)
726             anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange,
727                                                 (WindowPtr *)NULL);
728         else
729             anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin,
730                                                 (WindowPtr *)NULL);
731
732         if (pWin->valdata)
733         {
734             pWin->valdata->before.resized = TRUE;
735             pWin->valdata->before.borderVisible = borderVisible;
736         }
737
738 #ifdef DO_SAVE_UNDERS
739         if (DO_SAVE_UNDERS(pWin))
740         {
741             dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange);
742         }
743 #endif /* DO_SAVE_UNDERS */
744
745         if (anyMarked)
746             (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, VTOther);
747         /*
748          * the entire window is trashed unless bitGravity
749          * recovers portions of it
750          */
751         REGION_COPY(pScreen, &pWin->valdata->after.exposed, &pWin->clipList);
752     }
753
754     GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny);
755
756     if (pWin->backStorage &&
757         ((pWin->backingStore == Always) || WasViewable))
758     {
759         if (!WasViewable)
760             pRegion = &pWin->clipList; /* a convenient empty region */
761         if (pWin->bitGravity == ForgetGravity)
762             bsExposed = (*pScreen->TranslateBackingStore)
763                                 (pWin, 0, 0, NullRegion, oldx, oldy);
764         else
765         {
766             bsExposed = (*pScreen->TranslateBackingStore)
767                              (pWin, nx - x, ny - y, pRegion, oldx, oldy);
768         }
769     }
770
771     if (WasViewable)
772     {
773         /* avoid the border */
774         if (HasBorder (pWin))
775         {
776             int offx, offy, dx, dy;
777
778             /* kruft to avoid double translates for each gravity */
779             offx = 0;
780             offy = 0;
781             for (g = 0; g <= StaticGravity; g++)
782             {
783                 if (!gravitate[g])
784                     continue;
785
786                 /* align winSize to gravitate[g].
787                  * winSize is in new coordinates,
788                  * gravitate[g] is still in old coordinates */
789                 GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
790                 
791                 dx = (oldx - nx) - offx;
792                 dy = (oldy - ny) - offy;
793                 if (dx || dy)
794                 {
795                     REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy);
796                     offx += dx;
797                     offy += dy;
798                 }
799                 REGION_INTERSECT(pScreen, gravitate[g], gravitate[g],
800                                  &pWin->winSize);
801             }
802             /* get winSize back where it belongs */
803             if (offx || offy)
804                 REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy);
805         }
806         /*
807          * add screen bits to the appropriate bucket
808          */
809
810         if (oldWinClip)
811         {
812             /*
813              * clip to new clipList
814              */
815             REGION_COPY(pScreen, pRegion, oldWinClip);
816             REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy);
817             REGION_INTERSECT(pScreen, oldWinClip, pRegion, &pWin->clipList);
818             /*
819              * don't step on any gravity bits which will be copied after this
820              * region.  Note -- this assumes that the regions will be copied
821              * in gravity order.
822              */
823             for (g = pWin->bitGravity + 1; g <= StaticGravity; g++)
824             {
825                 if (gravitate[g])
826                     REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip,
827                                         gravitate[g]);
828             }
829             REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny);
830             g = pWin->bitGravity;
831             if (!gravitate[g])
832                 gravitate[g] = oldWinClip;
833             else
834             {
835                 REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip);
836                 REGION_DESTROY(pScreen, oldWinClip);
837             }
838         }
839
840         /*
841          * move the bits on the screen
842          */
843
844         destClip = NULL;
845
846         for (g = 0; g <= StaticGravity; g++)
847         {
848             if (!gravitate[g])
849                 continue;
850
851             GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
852
853             oldpt.x = oldx + (x - nx);
854             oldpt.y = oldy + (y - ny);
855
856             /* Note that gravitate[g] is *translated* by CopyWindow */
857
858             /* only copy the remaining useful bits */
859
860             REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], oldRegion);
861
862             /* clip to not overwrite already copied areas */
863
864             if (destClip) {
865                 REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y);
866                 REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip);
867                 REGION_TRANSLATE(pScreen, destClip, x - oldpt.x, y - oldpt.y);
868             }
869
870             /* and move those bits */
871
872             if (oldpt.x != x || oldpt.y != y)
873                 (*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]);
874
875             /* remove any overwritten bits from the remaining useful bits */
876
877             REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]);
878
879             /*
880              * recompute exposed regions of child windows
881              */
882         
883             for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
884             {
885                 if (pChild->winGravity != g)
886                     continue;
887                 REGION_INTERSECT(pScreen, pRegion,
888                                        &pChild->borderClip, gravitate[g]);
889                 TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion);
890             }
891
892             /*
893              * remove the successfully copied regions of the
894              * window from its exposed region
895              */
896
897             if (g == pWin->bitGravity)
898                 REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed,
899                                      &pWin->valdata->after.exposed, gravitate[g]);
900             if (!destClip)
901                 destClip = gravitate[g];
902             else
903             {
904                 REGION_UNION(pScreen, destClip, destClip, gravitate[g]);
905                 REGION_DESTROY(pScreen, gravitate[g]);
906             }
907         }
908
909         REGION_DESTROY(pScreen, oldRegion);
910         REGION_DESTROY(pScreen, pRegion);
911         if (destClip)
912             REGION_DESTROY(pScreen, destClip);
913         if (bsExposed)
914         {
915             RegionPtr   valExposed = NullRegion;
916
917             if (pWin->valdata)
918                 valExposed = &pWin->valdata->after.exposed;
919             (*pScreen->WindowExposures) (pWin, valExposed, bsExposed);
920             if (valExposed)
921                 REGION_EMPTY(pScreen, valExposed);
922             REGION_DESTROY(pScreen, bsExposed);
923         }
924         if (anyMarked)
925             (*pScreen->HandleExposures)(pLayerWin->parent);
926 #ifdef DO_SAVE_UNDERS
927         if (dosave)
928         {
929             (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange);
930         }
931 #endif /* DO_SAVE_UNDERS */
932         if (anyMarked && pScreen->PostValidateTree)
933             (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange,
934                                           VTOther);
935     }
936     else if (bsExposed)
937     {
938         (*pScreen->WindowExposures) (pWin, NullRegion, bsExposed);
939         REGION_DESTROY(pScreen, bsExposed);
940     }
941     if (pWin->realized)
942         WindowsRestructured ();
943 }
944
945 WindowPtr
946 miGetLayerWindow(pWin)
947     WindowPtr pWin;
948 {
949     return pWin->firstChild;
950 }
951
952 #ifdef SHAPE
953 /******
954  *
955  * miSetShape
956  *    The border/window shape has changed.  Recompute winSize/borderSize
957  *    and send appropriate exposure events
958  */
959
960 void
961 miSetShape(pWin)
962     register WindowPtr  pWin;
963 {
964     Bool        WasViewable = (Bool)(pWin->viewable);
965     register ScreenPtr pScreen = pWin->drawable.pScreen;
966     Bool        anyMarked;
967     WindowPtr   pParent = pWin->parent;
968     RegionPtr   pOldClip, bsExposed;
969 #ifdef DO_SAVE_UNDERS
970     Bool        dosave = FALSE;
971 #endif
972     WindowPtr   pLayerWin;
973
974     if (WasViewable)
975     {
976         anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
977                                                       &pLayerWin);
978         if (pWin->valdata)
979         {
980             if (HasBorder (pWin))
981             {
982                 RegionPtr       borderVisible;
983
984                 borderVisible = REGION_CREATE(pScreen, NullBox, 1);
985                 REGION_SUBTRACT(pScreen, borderVisible,
986                                       &pWin->borderClip, &pWin->winSize);
987                 pWin->valdata->before.borderVisible = borderVisible;
988             }
989             pWin->valdata->before.resized = TRUE;
990         }
991     }
992
993     SetWinSize (pWin);
994     SetBorderSize (pWin);
995
996     ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
997
998     if (WasViewable)
999     {
1000         if (pWin->backStorage)
1001         {
1002             pOldClip = REGION_CREATE(pScreen, NullBox, 1);
1003             REGION_COPY(pScreen, pOldClip, &pWin->clipList);
1004         }
1005
1006         anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin,
1007                                                 (WindowPtr *)NULL);
1008
1009 #ifdef DO_SAVE_UNDERS
1010         if (DO_SAVE_UNDERS(pWin))
1011         {
1012             dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin);
1013         }
1014 #endif /* DO_SAVE_UNDERS */
1015
1016         if (anyMarked)
1017             (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, VTOther);
1018     }
1019
1020     if (pWin->backStorage &&
1021         ((pWin->backingStore == Always) || WasViewable))
1022     {
1023         if (!WasViewable)
1024             pOldClip = &pWin->clipList; /* a convenient empty region */
1025         bsExposed = (*pScreen->TranslateBackingStore)
1026                              (pWin, 0, 0, pOldClip,
1027                               pWin->drawable.x, pWin->drawable.y);
1028         if (WasViewable)
1029             REGION_DESTROY(pScreen, pOldClip);
1030         if (bsExposed)
1031         {
1032             RegionPtr   valExposed = NullRegion;
1033     
1034             if (pWin->valdata)
1035                 valExposed = &pWin->valdata->after.exposed;
1036             (*pScreen->WindowExposures) (pWin, valExposed, bsExposed);
1037             if (valExposed)
1038                 REGION_EMPTY(pScreen, valExposed);
1039             REGION_DESTROY(pScreen, bsExposed);
1040         }
1041     }
1042     if (WasViewable)
1043     {
1044         if (anyMarked)
1045             (*pScreen->HandleExposures)(pLayerWin->parent);
1046 #ifdef DO_SAVE_UNDERS
1047         if (dosave)
1048             (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin);
1049 #endif /* DO_SAVE_UNDERS */
1050         if (anyMarked && pScreen->PostValidateTree)
1051             (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, VTOther);
1052     }
1053     if (pWin->realized)
1054         WindowsRestructured ();
1055     CheckCursorConfinement(pWin);
1056 }
1057 #endif
1058
1059 /* Keeps the same inside(!) origin */
1060
1061 void
1062 miChangeBorderWidth(pWin, width)
1063     register WindowPtr pWin;
1064     unsigned int width;
1065 {
1066     WindowPtr pParent;
1067     int oldwidth;
1068     Bool anyMarked;
1069     register ScreenPtr pScreen;
1070     Bool WasViewable = (Bool)(pWin->viewable);
1071     Bool HadBorder;
1072 #ifdef DO_SAVE_UNDERS
1073     Bool        dosave = FALSE;
1074 #endif
1075     WindowPtr  pLayerWin;
1076
1077     oldwidth = wBorderWidth (pWin);
1078     if (oldwidth == width)
1079         return;
1080     HadBorder = HasBorder(pWin);
1081     pScreen = pWin->drawable.pScreen;
1082     pParent = pWin->parent;
1083     if (WasViewable && width < oldwidth)
1084         anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin);
1085
1086     pWin->borderWidth = width;
1087     SetBorderSize (pWin);
1088
1089     if (WasViewable)
1090     {
1091         if (width > oldwidth)
1092         {
1093             anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
1094                                                           &pLayerWin);
1095             /*
1096              * save the old border visible region to correctly compute
1097              * borderExposed.
1098              */
1099             if (pWin->valdata && HadBorder)
1100             {
1101                 RegionPtr   borderVisible;
1102                 borderVisible = REGION_CREATE(pScreen, NULL, 1);
1103                 REGION_SUBTRACT(pScreen, borderVisible,
1104                                       &pWin->borderClip, &pWin->winSize);
1105                 pWin->valdata->before.borderVisible = borderVisible;
1106             }
1107         }
1108 #ifdef DO_SAVE_UNDERS
1109         if (DO_SAVE_UNDERS(pWin))
1110         {
1111             dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib);
1112         }
1113 #endif /* DO_SAVE_UNDERS */
1114
1115         if (anyMarked)
1116         {
1117             (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther);
1118             (*pScreen->HandleExposures)(pLayerWin->parent);
1119         }
1120 #ifdef DO_SAVE_UNDERS
1121         if (dosave)
1122             (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib);
1123 #endif /* DO_SAVE_UNDERS */
1124         if (anyMarked && pScreen->PostValidateTree)
1125             (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin,
1126                                           VTOther);
1127     }
1128     if (pWin->realized)
1129         WindowsRestructured ();
1130 }
1131
1132 void
1133 miMarkUnrealizedWindow(pChild, pWin, fromConfigure)
1134     WindowPtr pChild;
1135     WindowPtr pWin;
1136     Bool fromConfigure;
1137 {
1138     if ((pChild != pWin) || fromConfigure)
1139     {
1140         REGION_EMPTY(pChild->drawable.pScreen, &pChild->clipList);
1141         if (pChild->drawable.pScreen->ClipNotify)
1142             (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0);
1143         REGION_EMPTY(pChild->drawable.pScreen, &pChild->borderClip);
1144     }
1145 }