]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/dix/window.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / programs / Xserver / dix / window.c
1 /* $XConsortium: window.c /main/210 1996/10/28 07:24:59 kaleb $ */
2 /* $XFree86: xc/programs/Xserver/dix/window.c,v 3.6 1997/01/18 06:53:16 dawes Exp $ */
3 /*
4
5 Copyright (c) 1987  X Consortium
6
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 OTHER DEALINGS IN THE SOFTWARE.
25
26 Except as contained in this notice, the name of the X Consortium shall
27 not be used in advertising or otherwise to promote the sale, use or
28 other dealings in this Software without prior written authorization
29 from the X Consortium.
30
31
32 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
33
34                         All Rights Reserved
35
36 Permission to use, copy, modify, and distribute this software and its 
37 documentation for any purpose and without fee is hereby granted, 
38 provided that the above copyright notice appear in all copies and that
39 both that copyright notice and this permission notice appear in 
40 supporting documentation, and that the name of Digital not be
41 used in advertising or publicity pertaining to distribution of the
42 software without specific, written prior permission.  
43
44 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
45 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
46 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
47 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
48 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
49 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
50 SOFTWARE.
51
52 */
53
54 #include "misc.h"
55 #include "scrnintstr.h"
56 #include "os.h"
57 #include "regionstr.h"
58 #include "validate.h"
59 #include "windowstr.h"
60 #include "input.h"
61 #include "resource.h"
62 #include "colormapst.h"
63 #include "cursorstr.h"
64 #include "dixstruct.h"
65 #include "gcstruct.h"
66 #include "servermd.h"
67 #include "dixevents.h"
68 #ifdef XAPPGROUP
69 #include "extensions/Xagsrv.h"
70 #endif
71 #ifdef XCSECURITY
72 #define _SECURITY_SERVER
73 #include "extensions/security.h"
74 #endif
75
76 extern Bool permitOldBugs;
77
78 #if defined(NEED_SCREEN_REGIONS)
79 #define REGION_PTR(pScreen,pWin) \
80     register ScreenPtr pScreen = pWin->drawable.pScreen;
81 #else
82 #define REGION_PTR(pScreen,pWin) /* nothing */
83 #endif
84
85 /******
86  * Window stuff for server 
87  *
88  *    CreateRootWindow, CreateWindow, ChangeWindowAttributes,
89  *    GetWindowAttributes, DeleteWindow, DestroySubWindows,
90  *    HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows,
91  *    UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow,
92  *
93  ******/
94
95 static unsigned char _back_lsb[4] = {0x88, 0x22, 0x44, 0x11};
96 static unsigned char _back_msb[4] = {0x11, 0x44, 0x22, 0x88};
97
98 int screenIsSaved = SCREEN_SAVER_OFF;
99
100 ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
101
102 extern WindowPtr *WindowTable;
103
104 extern int rand();
105
106 static Bool TileScreenSaver(
107 #if NeedFunctionPrototypes
108     int /*i*/,
109     int /*kind*/
110 #endif
111 );
112
113
114 #define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \
115                               CWDontPropagate | CWOverrideRedirect | CWCursor )
116
117 #define BOXES_OVERLAP(b1, b2) \
118       (!( ((b1)->x2 <= (b2)->x1)  || \
119         ( ((b1)->x1 >= (b2)->x2)) || \
120         ( ((b1)->y2 <= (b2)->y1)) || \
121         ( ((b1)->y1 >= (b2)->y2)) ) )
122
123 #define RedirectSend(pWin) \
124     ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask)
125
126 #define SubSend(pWin) \
127     ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask)
128
129 #define StrSend(pWin) \
130     ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask)
131
132 #define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent))
133
134
135 int numSaveUndersViewable = 0;
136 int deltaSaveUndersViewable = 0;
137
138 #ifdef DEBUG
139 /******
140  * PrintWindowTree
141  *    For debugging only
142  ******/
143
144 int
145 PrintChildren(p1, indent)
146     WindowPtr p1;
147     int indent;
148 {
149     WindowPtr p2;
150     int i;
151
152     while (p1)
153     {
154         p2 = p1->firstChild;
155         for (i=0; i<indent; i++) ErrorF( " ");
156         ErrorF( "%x\n", p1->drawable.id);
157         miPrintRegion(&p1->clipList);
158         PrintChildren(p2, indent+4);
159         p1 = p1->nextSib;
160     }
161 }
162
163 PrintWindowTree()
164 {
165     int i;
166     WindowPtr pWin, p1;
167
168     for (i=0; i<screenInfo.numScreens; i++)
169     {
170         ErrorF( "WINDOW %d\n", i);
171         pWin = WindowTable[i];
172         miPrintRegion(&pWin->clipList);
173         p1 = pWin->firstChild;
174         PrintChildren(p1, 4);
175     }
176 }
177 #endif
178
179 int
180 TraverseTree(pWin, func, data)
181     register WindowPtr pWin;
182     VisitWindowProcPtr func;
183     pointer data;
184 {
185     register int result;
186     register WindowPtr pChild;
187
188     if (!(pChild = pWin))
189        return(WT_NOMATCH);
190     while (1)
191     {
192         result = (* func)(pChild, data);
193         if (result == WT_STOPWALKING)
194             return(WT_STOPWALKING);
195         if ((result == WT_WALKCHILDREN) && pChild->firstChild)
196         {
197             pChild = pChild->firstChild;
198             continue;
199         }
200         while (!pChild->nextSib && (pChild != pWin))
201             pChild = pChild->parent;
202         if (pChild == pWin)
203             break;
204         pChild = pChild->nextSib;
205     }
206     return(WT_NOMATCH);
207 }
208
209 /*****
210  * WalkTree
211  *   Walk the window tree, for SCREEN, preforming FUNC(pWin, data) on
212  *   each window.  If FUNC returns WT_WALKCHILDREN, traverse the children,
213  *   if it returns WT_DONTWALKCHILDREN, dont.  If it returns WT_STOPWALKING
214  *   exit WalkTree.  Does depth-first traverse.
215  *****/
216
217 int
218 WalkTree(pScreen, func, data)
219     ScreenPtr pScreen;
220     VisitWindowProcPtr func;
221     pointer data;
222 {
223     return(TraverseTree(WindowTable[pScreen->myNum], func, data));
224 }
225
226 /* hack for forcing backing store on all windows */
227 int     defaultBackingStore = NotUseful;
228 /* hack to force no backing store */
229 Bool    disableBackingStore = FALSE;
230 /* hack to force no save unders */
231 Bool    disableSaveUnders = FALSE;
232
233 static void
234 #if NeedFunctionPrototypes
235 SetWindowToDefaults(register WindowPtr pWin)
236 #else
237 SetWindowToDefaults(pWin)
238     register WindowPtr pWin;
239 #endif
240 {
241     pWin->prevSib = NullWindow;
242     pWin->firstChild = NullWindow;
243     pWin->lastChild = NullWindow;
244
245     pWin->valdata = (ValidatePtr)NULL;
246     pWin->optional = (WindowOptPtr)NULL;
247     pWin->cursorIsNone = TRUE;
248
249     pWin->backingStore = NotUseful;
250     pWin->DIXsaveUnder = FALSE;
251     pWin->backStorage = (pointer) NULL;
252
253     pWin->mapped = FALSE;           /* off */
254     pWin->realized = FALSE;     /* off */
255     pWin->viewable = FALSE;
256     pWin->visibility = VisibilityNotViewable;
257     pWin->overrideRedirect = FALSE;
258     pWin->saveUnder = FALSE;
259
260     pWin->bitGravity = ForgetGravity;
261     pWin->winGravity = NorthWestGravity;
262
263     pWin->eventMask = 0;
264     pWin->deliverableEvents = 0;
265     pWin->dontPropagate = 0;
266     pWin->forcedBS = FALSE;
267 #ifdef NEED_DBE_BUF_BITS
268     pWin->srcBuffer = DBE_FRONT_BUFFER;
269     pWin->dstBuffer = DBE_FRONT_BUFFER;
270 #endif
271 }
272
273 static void
274 #if NeedFunctionPrototypes
275 MakeRootTile(WindowPtr pWin)
276 #else
277 MakeRootTile(pWin)
278     WindowPtr pWin;
279 #endif
280 {
281     ScreenPtr pScreen = pWin->drawable.pScreen;
282     GCPtr pGC;
283     unsigned char back[128];
284     int len = BitmapBytePad(4);
285     register unsigned char *from, *to;
286     register int i, j;
287
288     pWin->background.pixmap = (*pScreen->CreatePixmap)(pScreen, 4, 4,
289                                                     pScreen->rootDepth);
290
291     pWin->backgroundState = BackgroundPixmap;
292     pGC = GetScratchGC(pScreen->rootDepth, pScreen);
293     if (!pWin->background.pixmap || !pGC)
294         FatalError("cound not create root tile");
295
296     {
297         CARD32 attributes[2];
298
299         attributes[0] = pScreen->whitePixel;
300         attributes[1] = pScreen->blackPixel;
301
302         (void)ChangeGC(pGC, GCForeground | GCBackground, attributes);
303     }
304
305    ValidateGC((DrawablePtr)pWin->background.pixmap, pGC);
306
307    from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb;
308    to = back;
309
310    for (i = 4; i > 0; i--, from++)
311         for (j = len; j > 0; j--)
312             *to++ = *from;
313
314    (*pGC->ops->PutImage)((DrawablePtr)pWin->background.pixmap, pGC, 1,
315                     0, 0, 4, 4, 0, XYBitmap, (char *)back);
316
317    FreeScratchGC(pGC);
318
319 }
320
321 WindowPtr
322 AllocateWindow(pScreen)
323     ScreenPtr pScreen;
324 {
325     WindowPtr pWin;
326     register char *ptr;
327     register DevUnion *ppriv;
328     register unsigned *sizes;
329     register unsigned size;
330     register int i;
331
332     pWin = (WindowPtr)xalloc(pScreen->totalWindowSize);
333     if (pWin)
334     {
335         ppriv = (DevUnion *)(pWin + 1);
336         pWin->devPrivates = ppriv;
337         sizes = pScreen->WindowPrivateSizes;
338         ptr = (char *)(ppriv + pScreen->WindowPrivateLen);
339         for (i = pScreen->WindowPrivateLen; --i >= 0; ppriv++, sizes++)
340         {
341             if ( (size = *sizes) )
342             {
343                 ppriv->ptr = (pointer)ptr;
344                 ptr += size;
345             }
346             else
347                 ppriv->ptr = (pointer)NULL;
348         }
349     }
350     return pWin;
351 }
352
353 /*****
354  * CreateRootWindow
355  *    Makes a window at initialization time for specified screen
356  *****/
357
358 Bool
359 CreateRootWindow(pScreen)
360     ScreenPtr   pScreen;
361 {
362     WindowPtr   pWin;
363     BoxRec      box;
364     PixmapFormatRec *format;
365
366     pWin = AllocateWindow(pScreen);
367     if (!pWin)
368         return FALSE;
369
370     savedScreenInfo[pScreen->myNum].pWindow = NULL;
371     savedScreenInfo[pScreen->myNum].wid = FakeClientID(0);
372     savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL;
373     screenIsSaved = SCREEN_SAVER_OFF;
374
375     WindowTable[pScreen->myNum] = pWin;
376
377     pWin->drawable.pScreen = pScreen;
378     pWin->drawable.type = DRAWABLE_WINDOW;
379
380     pWin->drawable.depth = pScreen->rootDepth;
381     for (format = screenInfo.formats;
382          format->depth != pScreen->rootDepth;
383          format++)
384         ;
385     pWin->drawable.bitsPerPixel = format->bitsPerPixel;
386
387     pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
388
389     pWin->parent = NullWindow;
390     SetWindowToDefaults(pWin);
391
392     pWin->optional = (WindowOptRec *) xalloc (sizeof (WindowOptRec));
393
394     pWin->optional->dontPropagateMask = 0;
395     pWin->optional->otherEventMasks = 0;
396     pWin->optional->otherClients = NULL;
397     pWin->optional->passiveGrabs = NULL;
398     pWin->optional->userProps = NULL;
399     pWin->optional->backingBitPlanes = ~0L;
400     pWin->optional->backingPixel = 0;
401 #ifdef SHAPE
402     pWin->optional->boundingShape = NULL;
403     pWin->optional->clipShape = NULL;
404 #endif
405 #ifdef XINPUT
406     pWin->optional->inputMasks = NULL;
407 #endif
408     pWin->optional->colormap = pScreen->defColormap;
409     pWin->optional->visual = pScreen->rootVisual;
410
411     pWin->nextSib = NullWindow;
412
413     pWin->drawable.id = FakeClientID(0);
414
415     pWin->origin.x = pWin->origin.y = 0;
416     pWin->drawable.height = pScreen->height;
417     pWin->drawable.width = pScreen->width;
418     pWin->drawable.x = pWin->drawable.y = 0;
419
420     box.x1 = 0;
421     box.y1 = 0;
422     box.x2 = pScreen->width;
423     box.y2 = pScreen->height;
424     REGION_INIT(pScreen, &pWin->clipList, &box, 1);
425     REGION_INIT(pScreen, &pWin->winSize, &box, 1);
426     REGION_INIT(pScreen, &pWin->borderSize, &box, 1);
427     REGION_INIT(pScreen, &pWin->borderClip, &box, 1);
428
429     pWin->drawable.class = InputOutput;
430     pWin->optional->visual = pScreen->rootVisual;
431
432     pWin->backgroundState = BackgroundPixel;
433     pWin->background.pixel = pScreen->whitePixel;
434
435     pWin->borderIsPixel = TRUE;
436     pWin->border.pixel = pScreen->blackPixel;
437     pWin->borderWidth = 0;
438
439     if (!AddResource(pWin->drawable.id, RT_WINDOW, (pointer)pWin))
440         return FALSE;
441
442     if (disableBackingStore)
443         pScreen->backingStoreSupport = NotUseful;
444
445 #ifdef DO_SAVE_UNDERS
446     if ((pScreen->backingStoreSupport != NotUseful) &&
447         (pScreen->saveUnderSupport == NotUseful))
448     {
449         /*
450          * If the screen has backing-store but no save-unders, let the
451          * clients know we can support save-unders using backing-store.
452          */
453         pScreen->saveUnderSupport = USE_DIX_SAVE_UNDERS;
454     }
455 #endif /* DO_SAVE_UNDERS */
456                 
457     if (disableSaveUnders)
458         pScreen->saveUnderSupport = NotUseful;
459
460     return TRUE;
461 }
462
463 void
464 InitRootWindow(pWin)
465     WindowPtr pWin;
466 {
467     ScreenPtr pScreen;
468
469     pScreen = pWin->drawable.pScreen;
470     if (!(*pScreen->CreateWindow)(pWin))
471         return; /* XXX */
472     (*pScreen->PositionWindow)(pWin, 0, 0);
473
474     pWin->cursorIsNone = FALSE;
475     pWin->optional->cursor = rootCursor;
476     rootCursor->refcnt++;
477     MakeRootTile(pWin);
478     pWin->backingStore = defaultBackingStore;
479     pWin->forcedBS = (defaultBackingStore != NotUseful);
480     /* We SHOULD check for an error value here XXX */
481     (*pScreen->ChangeWindowAttributes)(pWin,
482                        CWBackPixmap|CWBorderPixel|CWCursor|CWBackingStore);
483
484     MapWindow(pWin, serverClient);
485 }
486
487 /* Set the region to the intersection of the rectangle and the
488  * window's winSize.  The window is typically the parent of the
489  * window from which the region came.
490  */
491
492 void
493 ClippedRegionFromBox(pWin, Rgn, x, y, w, h)
494     register WindowPtr pWin;
495     RegionPtr Rgn;
496     register int x, y;
497     int w, h;
498 {
499     REGION_PTR(pScreen, pWin)
500     BoxRec box;
501
502     box = *(REGION_EXTENTS(pScreen, &pWin->winSize));
503     /* we do these calculations to avoid overflows */
504     if (x > box.x1)
505         box.x1 = x;
506     if (y > box.y1)
507         box.y1 = y;
508     x += w;
509     if (x < box.x2)
510         box.x2 = x;
511     y += h;
512     if (y < box.y2)
513         box.y2 = y;
514     if (box.x1 > box.x2)
515         box.x2 = box.x1;
516     if (box.y1 > box.y2)
517         box.y2 = box.y1;
518     REGION_RESET(pScreen, Rgn, &box);
519     REGION_INTERSECT(pScreen, Rgn, Rgn, &pWin->winSize);
520 }
521
522 WindowPtr
523 RealChildHead(pWin)
524     register WindowPtr pWin;
525 {
526     if (!pWin->parent &&
527         (screenIsSaved == SCREEN_SAVER_ON) &&
528         (HasSaverWindow (pWin->drawable.pScreen->myNum)))
529         return (pWin->firstChild);
530     else
531         return (NullWindow);
532 }
533
534 /*****
535  * CreateWindow
536  *    Makes a window in response to client request 
537  *****/
538
539 WindowPtr
540 CreateWindow(wid, pParent, x, y, w, h, bw, class, vmask, vlist,
541              depth, client, visual, error)
542     Window wid;
543     register WindowPtr pParent;
544     int x,y;
545     unsigned int w, h, bw;
546     unsigned int class;
547     register Mask vmask;
548     XID *vlist;
549     int depth;
550     ClientPtr client;
551     VisualID visual;
552     int *error;
553 {
554     register WindowPtr pWin;
555     WindowPtr pHead;
556     register ScreenPtr pScreen;
557     xEvent event;
558     int idepth, ivisual;
559     Bool fOK;
560     DepthPtr pDepth;
561     PixmapFormatRec *format;
562     register WindowOptPtr ancwopt;
563
564     if (class == CopyFromParent)
565         class = pParent->drawable.class;
566
567     if ((class != InputOutput) && (class != InputOnly))
568     {
569         *error = BadValue;
570         client->errorValue = class;
571         return NullWindow;
572     }
573
574     if ((class != InputOnly) && (pParent->drawable.class == InputOnly))
575     {
576         *error = BadMatch;
577         return NullWindow;
578     }
579
580     if ((class == InputOnly) && ((bw != 0) || (depth != 0)))
581     {
582         *error = BadMatch;
583         return NullWindow;
584     }
585
586     pScreen = pParent->drawable.pScreen;
587
588     if ((class == InputOutput) && (depth == 0))
589         depth = pParent->drawable.depth;
590     ancwopt = pParent->optional;
591     if (!ancwopt)
592         ancwopt = FindWindowWithOptional(pParent)->optional;
593     if (visual == CopyFromParent) {
594 #ifdef XAPPGROUP
595         VisualID ag_visual;
596
597         if (client->appgroup && !pParent->parent &&
598             (ag_visual = XagRootVisual (client)))
599             visual = ag_visual;
600         else
601 #endif
602         visual = ancwopt->visual;
603     }
604
605     /* Find out if the depth and visual are acceptable for this Screen */
606     if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth))
607     {
608         fOK = FALSE;
609         for(idepth = 0; idepth < pScreen->numDepths; idepth++)
610         {
611             pDepth = (DepthPtr) &pScreen->allowedDepths[idepth];
612             if ((depth == pDepth->depth) || (depth == 0))
613             {
614                 for (ivisual = 0; ivisual < pDepth->numVids; ivisual++)
615                 {
616                     if (visual == pDepth->vids[ivisual])
617                     {
618                         fOK = TRUE;
619                         break;
620                     }
621                 }
622             }
623         }
624         if (fOK == FALSE)
625         {
626             *error = BadMatch;
627             return NullWindow;
628         }
629     }
630
631     if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) &&
632         (class != InputOnly) &&
633         (depth != pParent->drawable.depth))
634     {
635         *error = BadMatch;
636         return NullWindow;
637     }
638
639     if (((vmask & CWColormap) == 0) &&
640         (class != InputOnly) &&
641         ((visual != ancwopt->visual) || (ancwopt->colormap == None)))
642     {
643         *error = BadMatch;
644         return NullWindow;
645     }
646
647     pWin = AllocateWindow(pScreen);
648     if (!pWin)
649     {
650         *error = BadAlloc;
651         return NullWindow;
652     }
653     pWin->drawable = pParent->drawable;
654     pWin->drawable.depth = depth;
655     if (depth == pParent->drawable.depth)
656         pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel;
657     else
658     {
659         for (format = screenInfo.formats; format->depth != depth; format++)
660             ;
661         pWin->drawable.bitsPerPixel = format->bitsPerPixel;
662     }
663     if (class == InputOnly)
664         pWin->drawable.type = (short) UNDRAWABLE_WINDOW;
665     pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
666
667     pWin->drawable.id = wid;
668     pWin->drawable.class = class;
669
670     pWin->parent = pParent;
671     SetWindowToDefaults(pWin);
672
673     if (visual != ancwopt->visual)
674     {
675         if (!MakeWindowOptional (pWin))
676         {
677             xfree (pWin);
678             *error = BadAlloc;
679             return NullWindow;
680         }
681         pWin->optional->visual = visual;
682         pWin->optional->colormap = None;
683     }
684
685     pWin->borderWidth = bw;
686 #ifdef XCSECURITY
687     /*  can't let untrusted clients have background None windows;
688      *  they make it too easy to steal window contents
689      */
690     if (client->trustLevel != XSecurityClientTrusted)
691     {
692         pWin->backgroundState = BackgroundPixel;
693         pWin->background.pixel = 0;
694     }
695     else
696 #endif
697     pWin->backgroundState = None;
698
699     pWin->borderIsPixel = pParent->borderIsPixel;
700     pWin->border = pParent->border;
701     if (pWin->borderIsPixel == FALSE)
702         pWin->border.pixmap->refcnt++;
703                 
704     pWin->origin.x = x + (int)bw;
705     pWin->origin.y = y + (int)bw;
706     pWin->drawable.width = w;
707     pWin->drawable.height = h;
708     pWin->drawable.x = pParent->drawable.x + x + (int)bw;
709     pWin->drawable.y = pParent->drawable.y + y + (int)bw;
710
711         /* set up clip list correctly for unobscured WindowPtr */
712     REGION_INIT(pScreen, &pWin->clipList, NullBox, 1);
713     REGION_INIT(pScreen, &pWin->borderClip, NullBox, 1);
714     REGION_INIT(pScreen, &pWin->winSize, NullBox, 1);
715     REGION_INIT(pScreen, &pWin->borderSize, NullBox, 1);
716
717     pHead = RealChildHead(pParent);
718     if (pHead)
719     {
720         pWin->nextSib = pHead->nextSib;
721         if (pHead->nextSib)
722             pHead->nextSib->prevSib = pWin;
723         else
724             pParent->lastChild = pWin;
725         pHead->nextSib = pWin;
726         pWin->prevSib = pHead;
727     }
728     else
729     {
730         pWin->nextSib = pParent->firstChild;
731         if (pParent->firstChild)
732             pParent->firstChild->prevSib = pWin;
733         else
734             pParent->lastChild = pWin;
735         pParent->firstChild = pWin;
736     }
737
738     SetWinSize (pWin);
739     SetBorderSize (pWin);
740
741     /* We SHOULD check for an error value here XXX */
742     if (!(*pScreen->CreateWindow)(pWin))
743     {
744         *error = BadAlloc;
745         DeleteWindow(pWin, None);
746         return NullWindow;
747     }
748     /* We SHOULD check for an error value here XXX */
749     (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y);
750
751     if (!(vmask & CWEventMask))
752         RecalculateDeliverableEvents(pWin);
753
754     if (vmask)
755         *error = ChangeWindowAttributes(pWin, vmask, vlist, wClient (pWin));
756     else
757         *error = Success;
758
759     if (*error != Success)
760     {
761         DeleteWindow(pWin, None);
762         return NullWindow;
763     }
764     if (!(vmask & CWBackingStore) && (defaultBackingStore != NotUseful))
765     {
766         XID value = defaultBackingStore;
767         (void)ChangeWindowAttributes(pWin, CWBackingStore, &value, wClient (pWin));
768         pWin->forcedBS = TRUE;
769     }
770
771     if (SubSend(pParent))
772     {
773         event.u.u.type = CreateNotify;
774         event.u.createNotify.window = wid;
775         event.u.createNotify.parent = pParent->drawable.id;
776         event.u.createNotify.x = x;
777         event.u.createNotify.y = y;
778         event.u.createNotify.width = w;
779         event.u.createNotify.height = h;
780         event.u.createNotify.borderWidth = bw;
781         event.u.createNotify.override = pWin->overrideRedirect;
782         DeliverEvents(pParent, &event, 1, NullWindow);          
783     }
784
785     return pWin;
786 }
787
788 static void
789 #if NeedFunctionPrototypes
790 FreeWindowResources(register WindowPtr pWin)
791 #else
792 FreeWindowResources(pWin)
793     register WindowPtr pWin;
794 #endif
795 {
796     register ScreenPtr pScreen = pWin->drawable.pScreen;
797
798     DeleteWindowFromAnySaveSet(pWin);
799     DeleteWindowFromAnySelections(pWin);
800     DeleteWindowFromAnyEvents(pWin, TRUE);
801     REGION_UNINIT(pScreen, &pWin->clipList);
802     REGION_UNINIT(pScreen, &pWin->winSize);
803     REGION_UNINIT(pScreen, &pWin->borderClip);
804     REGION_UNINIT(pScreen, &pWin->borderSize);
805 #ifdef SHAPE
806     if (wBoundingShape (pWin))
807         REGION_DESTROY(pScreen, wBoundingShape (pWin));
808     if (wClipShape (pWin))
809         REGION_DESTROY(pScreen, wClipShape (pWin));
810 #endif
811     if (pWin->borderIsPixel == FALSE)
812         (*pScreen->DestroyPixmap)(pWin->border.pixmap);
813     if (pWin->backgroundState == BackgroundPixmap)
814         (*pScreen->DestroyPixmap)(pWin->background.pixmap);
815
816     DeleteAllWindowProperties(pWin);
817     /* We SHOULD check for an error value here XXX */
818     (*pScreen->DestroyWindow)(pWin);
819     DisposeWindowOptional (pWin);
820 }
821
822 static void
823 #if NeedFunctionPrototypes
824 CrushTree(WindowPtr pWin)
825 #else
826 CrushTree(pWin)
827     WindowPtr pWin;
828 #endif
829 {
830     register WindowPtr pChild, pSib, pParent;
831     UnrealizeWindowProcPtr UnrealizeWindow;
832     xEvent event;
833
834     if (!(pChild = pWin->firstChild))
835         return;
836     UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow;
837     while (1)
838     {
839         if (pChild->firstChild)
840         {
841             pChild = pChild->firstChild;
842             continue;
843         }
844         while (1)
845         {
846             pParent = pChild->parent;
847             if (SubStrSend(pChild, pParent))
848             {
849                 event.u.u.type = DestroyNotify;
850                 event.u.destroyNotify.window = pChild->drawable.id;
851                 DeliverEvents(pChild, &event, 1, NullWindow);           
852             }
853             FreeResource(pChild->drawable.id, RT_WINDOW);
854             pSib = pChild->nextSib;
855 #ifdef DO_SAVE_UNDERS
856             if (pChild->saveUnder && pChild->viewable)
857                 deltaSaveUndersViewable--;
858 #endif
859             pChild->viewable = FALSE;
860             if (pChild->realized)
861             {
862                 pChild->realized = FALSE;
863                 (*UnrealizeWindow)(pChild);
864             }
865             FreeWindowResources(pChild);
866             xfree(pChild);
867             if ( (pChild = pSib) )
868                 break;
869             pChild = pParent;
870             pChild->firstChild = NullWindow;
871             pChild->lastChild = NullWindow;
872             if (pChild == pWin)
873                 return;
874         }
875     }
876 }
877         
878 /*****
879  *  DeleteWindow
880  *       Deletes child of window then window itself
881  *       If wid is None, don't send any events
882  *****/
883
884 /*ARGSUSED*/
885 int
886 DeleteWindow(value, wid)
887     pointer value;
888     XID wid;
889  {
890     register WindowPtr pParent;
891     register WindowPtr pWin = (WindowPtr)value;
892     xEvent event;
893
894     UnmapWindow(pWin, FALSE);
895
896     CrushTree(pWin);
897
898     pParent = pWin->parent;
899     if (wid && pParent && SubStrSend(pWin, pParent))
900     {
901         event.u.u.type = DestroyNotify;
902         event.u.destroyNotify.window = pWin->drawable.id;
903         DeliverEvents(pWin, &event, 1, NullWindow);             
904     }
905
906     FreeWindowResources(pWin);
907     if (pParent)
908     {
909         if (pParent->firstChild == pWin)
910             pParent->firstChild = pWin->nextSib;
911         if (pParent->lastChild == pWin)
912             pParent->lastChild = pWin->prevSib;
913         if (pWin->nextSib)
914             pWin->nextSib->prevSib = pWin->prevSib;
915         if (pWin->prevSib)
916             pWin->prevSib->nextSib = pWin->nextSib;
917     }
918     xfree(pWin);
919     return Success;
920 }
921
922 /*ARGSUSED*/
923 void
924 DestroySubwindows(pWin, client)
925     register WindowPtr pWin;
926     ClientPtr client;
927 {
928     /* XXX
929      * The protocol is quite clear that each window should be
930      * destroyed in turn, however, unmapping all of the first
931      * eliminates most of the calls to ValidateTree.  So,
932      * this implementation is incorrect in that all of the
933      * UnmapNotifies occur before all of the DestroyNotifies.
934      * If you care, simply delete the call to UnmapSubwindows.
935      */
936     UnmapSubwindows(pWin);
937     while (pWin->lastChild)
938         FreeResource(pWin->lastChild->drawable.id, RT_NONE);
939 }
940
941 #define DeviceEventMasks (KeyPressMask | KeyReleaseMask | ButtonPressMask | \
942     ButtonReleaseMask | PointerMotionMask)
943
944 /*****
945  *  ChangeWindowAttributes
946  *   
947  *  The value-mask specifies which attributes are to be changed; the
948  *  value-list contains one value for each one bit in the mask, from least
949  *  to most significant bit in the mask.  
950  *****/
951  
952 int
953 ChangeWindowAttributes(pWin, vmask, vlist, client)
954     register WindowPtr pWin;
955     Mask vmask;
956     XID *vlist;
957     ClientPtr client;
958 {
959     register Mask index2;
960     register XID *pVlist;
961     PixmapPtr pPixmap;
962     Pixmap pixID;
963     CursorPtr pCursor, pOldCursor;
964     Cursor cursorID;
965     WindowPtr pChild;
966     Colormap cmap;
967     ColormapPtr pCmap;
968     xEvent xE;
969     int result;
970     register ScreenPtr pScreen;
971     Mask vmaskCopy = 0;
972     register Mask tmask;
973     unsigned int val;
974     int error;
975     Bool checkOptional = FALSE;
976     Bool borderRelative = FALSE;
977     WindowPtr pLayerWin;
978
979     if ((pWin->drawable.class == InputOnly) && (vmask & (~INPUTONLY_LEGAL_MASK)))
980         return BadMatch;
981
982     error = Success;
983     pScreen = pWin->drawable.pScreen;
984     pVlist = vlist;
985     tmask = vmask;
986     while (tmask)
987     {
988         index2 = (Mask) lowbit (tmask);
989         tmask &= ~index2;
990         switch (index2)
991         {
992           case CWBackPixmap:
993             pixID = (Pixmap )*pVlist;
994             pVlist++;
995             if (pWin->backgroundState == ParentRelative)
996                 borderRelative = TRUE;
997             if (pixID == None)
998             {
999 #ifdef XCSECURITY
1000                 /*  can't let untrusted clients have background None windows */
1001                 if (client->trustLevel == XSecurityClientTrusted)
1002                 {
1003 #endif
1004                 if (pWin->backgroundState == BackgroundPixmap)
1005                     (*pScreen->DestroyPixmap)(pWin->background.pixmap);
1006                 if (!pWin->parent)
1007                     MakeRootTile(pWin);
1008                 else
1009                     pWin->backgroundState = None;
1010 #ifdef XCSECURITY
1011                 }
1012                 else
1013                 { /* didn't change the background to None, so don't tell ddx */
1014                     index2 = 0; 
1015                 }
1016 #endif
1017             }
1018             else if (pixID == ParentRelative)
1019             {
1020                 if (pWin->parent &&
1021                     pWin->drawable.depth != pWin->parent->drawable.depth)
1022                 {
1023                     error = BadMatch;
1024                     goto PatchUp;
1025                 }
1026                 if (pWin->backgroundState == BackgroundPixmap)
1027                     (*pScreen->DestroyPixmap)(pWin->background.pixmap);
1028                 if (!pWin->parent)
1029                     MakeRootTile(pWin);
1030                 else
1031                     pWin->backgroundState = ParentRelative;
1032                 borderRelative = TRUE;
1033                 /* Note that the parent's backgroundTile's refcnt is NOT
1034                  * incremented. */
1035             }
1036             else
1037             {   
1038                 pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID,
1039                                                 RT_PIXMAP, SecurityReadAccess);
1040                 if (pPixmap != (PixmapPtr) NULL)
1041                 {
1042                     if  ((pPixmap->drawable.depth != pWin->drawable.depth) ||
1043                          (pPixmap->drawable.pScreen != pScreen))
1044                     {
1045                         error = BadMatch;
1046                         goto PatchUp;
1047                     }
1048                     if (pWin->backgroundState == BackgroundPixmap)
1049                         (*pScreen->DestroyPixmap)(pWin->background.pixmap);
1050                     pWin->backgroundState = BackgroundPixmap;
1051                     pWin->background.pixmap = pPixmap;
1052                     pPixmap->refcnt++;
1053                 }
1054                 else
1055                 {
1056                     error = BadPixmap;
1057                     client->errorValue = pixID;
1058                     goto PatchUp;
1059                 }
1060             }
1061             break;
1062           case CWBackPixel:
1063             if (pWin->backgroundState == ParentRelative)
1064                 borderRelative = TRUE;
1065             if (pWin->backgroundState == BackgroundPixmap)
1066                 (*pScreen->DestroyPixmap)(pWin->background.pixmap);
1067             pWin->backgroundState = BackgroundPixel;
1068             pWin->background.pixel = (CARD32 ) *pVlist;
1069                    /* background pixel overrides background pixmap,
1070                       so don't let the ddx layer see both bits */
1071             vmaskCopy &= ~CWBackPixmap;
1072             pVlist++;
1073             break;
1074           case CWBorderPixmap:
1075             pixID = (Pixmap ) *pVlist;
1076             pVlist++;
1077             if (pixID == CopyFromParent)
1078             {
1079                 if (!pWin->parent ||
1080                     (pWin->drawable.depth != pWin->parent->drawable.depth))
1081                 {
1082                     error = BadMatch;
1083                     goto PatchUp;
1084                 }
1085                 if (pWin->borderIsPixel == FALSE)
1086                     (*pScreen->DestroyPixmap)(pWin->border.pixmap);
1087                 pWin->border = pWin->parent->border;
1088                 if ((pWin->borderIsPixel = pWin->parent->borderIsPixel) == TRUE)
1089                 {
1090                     index2 = CWBorderPixel;
1091                 }
1092                 else
1093                 {
1094                     pWin->parent->border.pixmap->refcnt++;
1095                 }
1096             }
1097             else
1098             {   
1099                 pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID,
1100                                         RT_PIXMAP, SecurityReadAccess);
1101                 if (pPixmap)
1102                 {
1103                     if  ((pPixmap->drawable.depth != pWin->drawable.depth) ||
1104                          (pPixmap->drawable.pScreen != pScreen))
1105                     {
1106                         error = BadMatch;
1107                         goto PatchUp;
1108                     }
1109                     if (pWin->borderIsPixel == FALSE)
1110                         (*pScreen->DestroyPixmap)(pWin->border.pixmap);
1111                     pWin->borderIsPixel = FALSE;
1112                     pWin->border.pixmap = pPixmap;
1113                     pPixmap->refcnt++;
1114                 }
1115                 else
1116                 {
1117                     error = BadPixmap;
1118                     client->errorValue = pixID;
1119                     goto PatchUp;
1120                 }
1121             }
1122             break;
1123           case CWBorderPixel:
1124             if (pWin->borderIsPixel == FALSE)
1125                 (*pScreen->DestroyPixmap)(pWin->border.pixmap);
1126             pWin->borderIsPixel = TRUE;
1127             pWin->border.pixel = (CARD32) *pVlist;
1128                     /* border pixel overrides border pixmap,
1129                        so don't let the ddx layer see both bits */
1130             vmaskCopy &= ~CWBorderPixmap;
1131             pVlist++;
1132             break;
1133           case CWBitGravity:
1134             val = (CARD8 )*pVlist;
1135             pVlist++;
1136             if (val > StaticGravity)
1137             {
1138                 error = BadValue;
1139                 client->errorValue = val;
1140                 goto PatchUp;
1141             }
1142             pWin->bitGravity = val;
1143             break;
1144           case CWWinGravity:
1145             val = (CARD8 )*pVlist;
1146             pVlist++;
1147             if (val > StaticGravity)
1148             {
1149                 error = BadValue;
1150                 client->errorValue = val;
1151                 goto PatchUp;
1152             }
1153             pWin->winGravity = val;
1154             break;
1155           case CWBackingStore:
1156             val = (CARD8 )*pVlist;
1157             pVlist++;
1158             if ((val != NotUseful) && (val != WhenMapped) && (val != Always))
1159             {
1160                 error = BadValue;
1161                 client->errorValue = val;
1162                 goto PatchUp;
1163             }
1164             pWin->backingStore = val;
1165             pWin->forcedBS = FALSE;
1166             break;
1167           case CWBackingPlanes:
1168             if (pWin->optional || ((CARD32)*pVlist != (CARD32)~0L)) {
1169                 if (!pWin->optional && !MakeWindowOptional (pWin))
1170                 {
1171                     error = BadAlloc;
1172                     goto PatchUp;
1173                 }
1174                 pWin->optional->backingBitPlanes = (CARD32) *pVlist;
1175                 if ((CARD32)*pVlist == (CARD32)~0L)
1176                     checkOptional = TRUE;
1177             }
1178             pVlist++;
1179             break;
1180           case CWBackingPixel:
1181             if (pWin->optional || (CARD32) *pVlist) {
1182                 if (!pWin->optional && !MakeWindowOptional (pWin))
1183                 {
1184                     error = BadAlloc;
1185                     goto PatchUp;
1186                 }
1187                 pWin->optional->backingPixel = (CARD32) *pVlist;
1188                 if (!*pVlist)
1189                     checkOptional = TRUE;
1190             }
1191             pVlist++;
1192             break;
1193           case CWSaveUnder:
1194             val = (BOOL) *pVlist;
1195             pVlist++;
1196             if ((val != xTrue) && (val != xFalse))
1197             {
1198                 error = BadValue;
1199                 client->errorValue = val;
1200                 goto PatchUp;
1201             }
1202 #ifdef DO_SAVE_UNDERS
1203             if (pWin->parent && (pWin->saveUnder != val) && (pWin->viewable) &&
1204                 DO_SAVE_UNDERS(pWin))
1205             {
1206                 /*
1207                  * Re-check all siblings and inferiors for obscurity or
1208                  * exposition (hee hee).
1209                  */
1210                 if (pWin->saveUnder)
1211                     deltaSaveUndersViewable--;
1212                 else
1213                     deltaSaveUndersViewable++;
1214                 pWin->saveUnder = val;
1215
1216                 if (pWin->firstChild)
1217                 {
1218                     pLayerWin = (*pScreen->GetLayerWindow)(pWin);
1219                    if ((*pScreen->ChangeSaveUnder)(pLayerWin->parent, pWin->nextSib))
1220                        (*pScreen->PostChangeSaveUnder)(pLayerWin->parent,
1221                                                        pWin->nextSib);
1222                }
1223                else
1224                {
1225                    if ((*pScreen->ChangeSaveUnder)(pWin, pWin->nextSib))
1226                        (*pScreen->PostChangeSaveUnder)(pWin,
1227                                                        pWin->nextSib);
1228                }                                   
1229             }
1230             else
1231             {
1232                 /*  If we're changing the saveUnder attribute of the root 
1233                  *  window, all we do is set pWin->saveUnder so that
1234                  *  GetWindowAttributes returns the right value.  We don't
1235                  *  do the "normal" save-under processing (as above).
1236                  *  Hope that doesn't cause any problems.
1237                  */
1238                 pWin->saveUnder = val;
1239             }
1240 #else
1241             pWin->saveUnder = val;
1242 #endif /* DO_SAVE_UNDERS */
1243             break;
1244           case CWEventMask:
1245             result = EventSelectForWindow(pWin, client, (Mask )*pVlist);
1246             if (result)
1247             {
1248                 error = result;
1249                 goto PatchUp;
1250             }
1251             pVlist++;
1252             break;
1253           case CWDontPropagate:
1254             result = EventSuppressForWindow(pWin, client, (Mask )*pVlist,
1255                                             &checkOptional);
1256             if (result)
1257             {
1258                 error = result;
1259                 goto PatchUp;
1260             }
1261             pVlist++;
1262             break;
1263           case CWOverrideRedirect:
1264             val = (BOOL ) *pVlist;
1265             pVlist++;
1266             if ((val != xTrue) && (val != xFalse))
1267             {
1268                 error = BadValue;
1269                 client->errorValue = val;
1270                 goto PatchUp;
1271             }
1272             pWin->overrideRedirect = val;
1273             break;
1274           case CWColormap:
1275             cmap = (Colormap) *pVlist;
1276             pVlist++;
1277             if (cmap == CopyFromParent)
1278             {
1279 #ifdef XAPPGROUP
1280                 Colormap ag_colormap;
1281                 ClientPtr win_owner;
1282
1283                 /*
1284                  * win_owner == client for CreateWindow, other clients
1285                  * can ChangeWindowAttributes
1286                  */
1287                 win_owner = LookupClient (pWin->drawable.id, client);
1288
1289                 if ( win_owner && win_owner->appgroup &&
1290                     !pWin->parent->parent &&
1291                     (ag_colormap = XagDefaultColormap (win_owner)))
1292                     cmap = ag_colormap;
1293                 else
1294 #endif
1295                 if (pWin->parent &&
1296                     (!pWin->optional ||
1297                      pWin->optional->visual == wVisual (pWin->parent)))
1298                 {
1299                     cmap = wColormap (pWin->parent);
1300                 }
1301                 else
1302                     cmap = None;
1303             }
1304             if (cmap == None)
1305             {
1306                 error = BadMatch;
1307                 goto PatchUp;
1308             }
1309             pCmap = (ColormapPtr)SecurityLookupIDByType(client, cmap,
1310                                               RT_COLORMAP, SecurityReadAccess);
1311             if (!pCmap)
1312             {
1313                 error = BadColor;
1314                 client->errorValue = cmap;
1315                 goto PatchUp;
1316             }
1317             if (pCmap->pVisual->vid != wVisual (pWin) ||
1318                 pCmap->pScreen != pScreen)
1319             {
1320                 error = BadMatch;
1321                 goto PatchUp;
1322             }
1323             if (cmap != wColormap (pWin))
1324             {
1325                 if (!pWin->optional)
1326                 {
1327                     if (!MakeWindowOptional (pWin))
1328                     {
1329                         error = BadAlloc;
1330                         goto PatchUp;
1331                     }
1332                 }
1333                 else if (pWin->parent && cmap == wColormap (pWin->parent))
1334                     checkOptional = TRUE;
1335
1336                 /*
1337                  * propagate the original colormap to any children
1338                  * inheriting it
1339                  */
1340
1341                 for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib)
1342                 {
1343                     if (!pChild->optional && !MakeWindowOptional (pChild))
1344                     {
1345                         error = BadAlloc;
1346                         goto PatchUp;
1347                     }
1348                 }
1349
1350                 pWin->optional->colormap = cmap;
1351
1352                 /*
1353                  * check on any children now matching the new colormap
1354                  */
1355
1356                 for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib)
1357                 {
1358                     if (pChild->optional->colormap == cmap)
1359                         CheckWindowOptionalNeed (pChild);
1360                 }
1361
1362                 xE.u.u.type = ColormapNotify;
1363                 xE.u.colormap.window = pWin->drawable.id;
1364                 xE.u.colormap.colormap = cmap;
1365                 xE.u.colormap.new = xTrue;
1366                 xE.u.colormap.state = IsMapInstalled(cmap, pWin);
1367                 DeliverEvents(pWin, &xE, 1, NullWindow);
1368             }
1369             break;
1370           case CWCursor:
1371             cursorID = (Cursor ) *pVlist;
1372             pVlist++;
1373             /*
1374              * install the new
1375              */
1376             if ( cursorID == None)
1377             {
1378                 if (pWin == WindowTable[pWin->drawable.pScreen->myNum])
1379                     pCursor = rootCursor;
1380                 else
1381                     pCursor = (CursorPtr) None;
1382             }
1383             else
1384             {
1385                 pCursor = (CursorPtr)SecurityLookupIDByType(client, cursorID,
1386                                                 RT_CURSOR, SecurityReadAccess);
1387                 if (!pCursor)
1388                 {
1389                     error = BadCursor;
1390                     client->errorValue = cursorID;
1391                     goto PatchUp;
1392                 }
1393             }
1394
1395             if (pCursor != wCursor (pWin))
1396             {
1397                 /*
1398                  * patch up child windows so they don't lose cursors.
1399                  */
1400
1401                 for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib)
1402                 {
1403                     if (!pChild->optional && !pChild->cursorIsNone &&
1404                         !MakeWindowOptional (pChild))
1405                     {
1406                         error = BadAlloc;
1407                         goto PatchUp;
1408                     }
1409                 }
1410
1411                 pOldCursor = 0;
1412                 if (pCursor == (CursorPtr) None)
1413                 {
1414                     pWin->cursorIsNone = TRUE;
1415                     if (pWin->optional)
1416                     {
1417                         pOldCursor = pWin->optional->cursor;
1418                         pWin->optional->cursor = (CursorPtr) None;
1419                         checkOptional = TRUE;
1420                     }
1421                 } else {
1422                     if (!pWin->optional)
1423                     {
1424                         if (!MakeWindowOptional (pWin))
1425                         {
1426                             error = BadAlloc;
1427                             goto PatchUp;
1428                         }
1429                     }
1430                     else if (pWin->parent && pCursor == wCursor (pWin->parent))
1431                         checkOptional = TRUE;
1432                     pOldCursor = pWin->optional->cursor;
1433                     pWin->optional->cursor = pCursor;
1434                     pCursor->refcnt++;
1435                     pWin->cursorIsNone = FALSE;
1436                     /*
1437                      * check on any children now matching the new cursor
1438                      */
1439
1440                     for (pChild=pWin->firstChild; pChild; pChild=pChild->nextSib)
1441                     {
1442                         if (pChild->optional &&
1443                             (pChild->optional->cursor == pCursor))
1444                             CheckWindowOptionalNeed (pChild);
1445                     }
1446                 }
1447
1448                 if (pWin->realized)
1449                     WindowHasNewCursor( pWin);
1450
1451                 /* Can't free cursor until here - old cursor
1452                  * is needed in WindowHasNewCursor
1453                  */
1454                 if (pOldCursor)
1455                     FreeCursor (pOldCursor, (Cursor)0);
1456             }
1457             break;
1458          default:
1459             error = BadValue;
1460             client->errorValue = vmask;
1461             goto PatchUp;
1462       }
1463       vmaskCopy |= index2;
1464     }
1465 PatchUp:
1466     if (checkOptional)
1467         CheckWindowOptionalNeed (pWin);
1468
1469         /* We SHOULD check for an error value here XXX */
1470     (*pScreen->ChangeWindowAttributes)(pWin, vmaskCopy);
1471
1472     /* 
1473         If the border contents have changed, redraw the border. 
1474         Note that this has to be done AFTER pScreen->ChangeWindowAttributes
1475         for the tile to be rotated, and the correct function selected.
1476     */
1477     if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative)
1478         && pWin->viewable && HasBorder (pWin))
1479     {
1480         RegionRec exposed;
1481
1482         REGION_INIT(pScreen, &exposed, NullBox, 0);
1483         REGION_SUBTRACT(pScreen, &exposed, &pWin->borderClip, &pWin->winSize);
1484         (*pWin->drawable.pScreen->PaintWindowBorder)(pWin, &exposed, PW_BORDER);
1485         REGION_UNINIT(pScreen, &exposed);
1486     }
1487     return error;
1488 }
1489
1490
1491 /*****
1492  * GetWindowAttributes
1493  *    Notice that this is different than ChangeWindowAttributes
1494  *****/
1495
1496 void
1497 GetWindowAttributes(pWin, client, wa)
1498     register WindowPtr pWin;
1499     ClientPtr client;
1500     xGetWindowAttributesReply *wa;
1501 {
1502     wa->type = X_Reply;
1503     wa->bitGravity = pWin->bitGravity;
1504     wa->winGravity = pWin->winGravity;
1505     if (pWin->forcedBS && pWin->backingStore != Always)
1506         wa->backingStore = NotUseful;
1507     else
1508         wa->backingStore = pWin->backingStore;
1509     wa->length = (sizeof(xGetWindowAttributesReply) -
1510                  sizeof(xGenericReply)) >> 2;
1511     wa->sequenceNumber = client->sequence;
1512     wa->backingBitPlanes =  wBackingBitPlanes (pWin);
1513     wa->backingPixel =  wBackingPixel (pWin);
1514     wa->saveUnder = (BOOL)pWin->saveUnder;
1515     wa->override = pWin->overrideRedirect;
1516     if (!pWin->mapped)
1517         wa->mapState = IsUnmapped;
1518     else if (pWin->realized)
1519         wa->mapState = IsViewable;
1520     else
1521         wa->mapState = IsUnviewable;
1522
1523     wa->colormap =  wColormap (pWin);
1524     wa->mapInstalled = (wa->colormap == None) ? xFalse
1525                                 : IsMapInstalled(wa->colormap, pWin);
1526
1527     wa->yourEventMask = EventMaskForClient(pWin, client);
1528     wa->allEventMasks = pWin->eventMask | wOtherEventMasks (pWin);
1529     wa->doNotPropagateMask = wDontPropagateMask (pWin);
1530     wa->class = pWin->drawable.class;
1531     wa->visualID = wVisual (pWin);
1532 }
1533
1534
1535 WindowPtr
1536 MoveWindowInStack(pWin, pNextSib)
1537     register WindowPtr pWin, pNextSib;
1538 {
1539     register WindowPtr pParent = pWin->parent;
1540     WindowPtr pFirstChange = pWin; /* highest window where list changes */
1541
1542     if (pWin->nextSib != pNextSib)
1543     {
1544         if (!pNextSib)        /* move to bottom */
1545         {
1546             if (pParent->firstChild == pWin)
1547                 pParent->firstChild = pWin->nextSib;
1548             /* if (pWin->nextSib) */     /* is always True: pNextSib == NULL
1549                                           * and pWin->nextSib != pNextSib
1550                                           * therefore pWin->nextSib != NULL */
1551             pFirstChange = pWin->nextSib;
1552             pWin->nextSib->prevSib = pWin->prevSib;
1553             if (pWin->prevSib)
1554                 pWin->prevSib->nextSib = pWin->nextSib;
1555             pParent->lastChild->nextSib = pWin;
1556             pWin->prevSib = pParent->lastChild;
1557             pWin->nextSib = NullWindow;
1558             pParent->lastChild = pWin;
1559         }
1560         else if (pParent->firstChild == pNextSib) /* move to top */
1561         {
1562             pFirstChange = pWin;
1563             if (pParent->lastChild == pWin)
1564                pParent->lastChild = pWin->prevSib;
1565             if (pWin->nextSib)
1566                 pWin->nextSib->prevSib = pWin->prevSib;
1567             if (pWin->prevSib)
1568                 pWin->prevSib->nextSib = pWin->nextSib;
1569             pWin->nextSib = pParent->firstChild;
1570             pWin->prevSib = (WindowPtr ) NULL;
1571             pNextSib->prevSib = pWin;
1572             pParent->firstChild = pWin;
1573         }
1574         else                    /* move in middle of list */
1575         {
1576             WindowPtr pOldNext = pWin->nextSib;
1577
1578             pFirstChange = NullWindow;
1579             if (pParent->firstChild == pWin)
1580                 pFirstChange = pParent->firstChild = pWin->nextSib;
1581             if (pParent->lastChild == pWin) {
1582                pFirstChange = pWin;
1583                pParent->lastChild = pWin->prevSib;
1584             }
1585             if (pWin->nextSib)
1586                 pWin->nextSib->prevSib = pWin->prevSib;
1587             if (pWin->prevSib)
1588                 pWin->prevSib->nextSib = pWin->nextSib;
1589             pWin->nextSib = pNextSib;
1590             pWin->prevSib = pNextSib->prevSib;
1591             if (pNextSib->prevSib)
1592                 pNextSib->prevSib->nextSib = pWin;
1593             pNextSib->prevSib = pWin;
1594             if (!pFirstChange) {                     /* do we know it yet? */
1595                 pFirstChange = pParent->firstChild;  /* no, search from top */
1596                 while ((pFirstChange != pWin) && (pFirstChange != pOldNext))
1597                      pFirstChange = pFirstChange->nextSib;
1598             }
1599         }
1600     }
1601
1602     return( pFirstChange );
1603 }
1604
1605 RegionPtr
1606 CreateUnclippedWinSize (pWin)
1607     register WindowPtr   pWin;
1608 {
1609     RegionPtr   pRgn;
1610     BoxRec      box;
1611
1612     box.x1 = pWin->drawable.x;
1613     box.y1 = pWin->drawable.y;
1614     box.x2 = pWin->drawable.x + (int) pWin->drawable.width;
1615     box.y2 = pWin->drawable.y + (int) pWin->drawable.height;
1616     pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1);
1617 #ifdef SHAPE
1618     if (wBoundingShape (pWin) || wClipShape (pWin)) {
1619         REGION_PTR(pScreen, pWin)
1620
1621         REGION_TRANSLATE(pScreen, pRgn, - pWin->drawable.x,
1622                          - pWin->drawable.y);
1623         if (wBoundingShape (pWin))
1624             REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin));
1625         if (wClipShape (pWin))
1626             REGION_INTERSECT(pScreen, pRgn, pRgn, wClipShape (pWin));
1627         REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x, pWin->drawable.y);
1628     }
1629 #endif
1630     return pRgn;
1631 }
1632
1633 void
1634 SetWinSize (pWin)
1635     register WindowPtr pWin;
1636 {
1637     ClippedRegionFromBox(pWin->parent, &pWin->winSize,
1638                          pWin->drawable.x, pWin->drawable.y,
1639                          (int)pWin->drawable.width,
1640                          (int)pWin->drawable.height);
1641 #ifdef SHAPE
1642     if (wBoundingShape (pWin) || wClipShape (pWin)) {
1643         REGION_PTR(pScreen, pWin)
1644
1645         REGION_TRANSLATE(pScreen, &pWin->winSize, - pWin->drawable.x,
1646                          - pWin->drawable.y);
1647         if (wBoundingShape (pWin))
1648             REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize,
1649                              wBoundingShape (pWin));
1650         if (wClipShape (pWin))
1651             REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize,
1652                              wClipShape (pWin));
1653         REGION_TRANSLATE(pScreen, &pWin->winSize, pWin->drawable.x,
1654                          pWin->drawable.y);
1655     }
1656 #endif
1657 }
1658
1659 void
1660 SetBorderSize (pWin)
1661     register WindowPtr pWin;
1662 {
1663     int bw;
1664
1665     if (HasBorder (pWin)) {
1666         bw = wBorderWidth (pWin);
1667         ClippedRegionFromBox(pWin->parent, &pWin->borderSize,
1668                 pWin->drawable.x - bw, pWin->drawable.y - bw,
1669                 (int)(pWin->drawable.width + (bw<<1)),
1670                 (int)(pWin->drawable.height + (bw<<1)));
1671 #ifdef SHAPE
1672         if (wBoundingShape (pWin)) {
1673             REGION_PTR(pScreen, pWin)
1674
1675             REGION_TRANSLATE(pScreen, &pWin->borderSize, - pWin->drawable.x,
1676                              - pWin->drawable.y);
1677             REGION_INTERSECT(pScreen, &pWin->borderSize, &pWin->borderSize,
1678                              wBoundingShape (pWin));
1679             REGION_TRANSLATE(pScreen, &pWin->borderSize, pWin->drawable.x,
1680                              pWin->drawable.y);
1681             REGION_UNION(pScreen, &pWin->borderSize, &pWin->borderSize,
1682                          &pWin->winSize);
1683         }
1684 #endif
1685     } else {
1686         REGION_COPY(pWin->drawable.pScreen, &pWin->borderSize,
1687                                                &pWin->winSize);
1688     }
1689 }
1690
1691 void
1692 GravityTranslate (x, y, oldx, oldy, dw, dh, gravity, destx, desty)
1693     register int x, y;          /* new window position */
1694     int         oldx, oldy;     /* old window position */
1695     int         dw, dh;
1696     unsigned    gravity;
1697     register int *destx, *desty;        /* position relative to gravity */
1698 {
1699     switch (gravity) {
1700     case NorthGravity:
1701         *destx = x + dw / 2;
1702         *desty = y;
1703         break;
1704     case NorthEastGravity:
1705         *destx = x + dw;
1706         *desty = y;
1707         break;
1708     case WestGravity:
1709         *destx = x;
1710         *desty = y + dh / 2;
1711         break;
1712     case CenterGravity:
1713         *destx = x + dw / 2;
1714         *desty = y + dh / 2;
1715         break;
1716     case EastGravity:
1717         *destx = x + dw;
1718         *desty = y + dh / 2;
1719         break;
1720     case SouthWestGravity:
1721         *destx = x;
1722         *desty = y + dh;
1723         break;
1724     case SouthGravity:
1725         *destx = x + dw / 2;
1726         *desty = y + dh;
1727         break;
1728     case SouthEastGravity:
1729         *destx = x + dw;
1730         *desty = y + dh;
1731         break;
1732     case StaticGravity:
1733         *destx = oldx;
1734         *desty = oldy;
1735         break;
1736     default:
1737         *destx = x;
1738         *desty = y;
1739         break;
1740     }
1741 }
1742
1743 /* XXX need to retile border on each window with ParentRelative origin */
1744 void
1745 ResizeChildrenWinSize(pWin, dx, dy, dw, dh)
1746     register WindowPtr pWin;
1747     int dx, dy, dw, dh;
1748 {
1749     register ScreenPtr pScreen;
1750     register WindowPtr pSib, pChild;
1751     Bool resized = (dw || dh);
1752
1753     pScreen = pWin->drawable.pScreen;
1754
1755     for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib)
1756     {
1757         if (resized && (pSib->winGravity > NorthWestGravity))
1758         {
1759             int cwsx, cwsy;
1760
1761             cwsx = pSib->origin.x;
1762             cwsy = pSib->origin.y;
1763             GravityTranslate (cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh,
1764                         pSib->winGravity, &cwsx, &cwsy);
1765             if (cwsx != pSib->origin.x || cwsy != pSib->origin.y)
1766             {
1767                 xEvent event;
1768
1769                 event.u.u.type = GravityNotify;
1770                 event.u.gravity.window = pSib->drawable.id;
1771                 event.u.gravity.x = cwsx - wBorderWidth (pSib);
1772                 event.u.gravity.y = cwsy - wBorderWidth (pSib);
1773                 DeliverEvents (pSib, &event, 1, NullWindow);
1774                 pSib->origin.x = cwsx;
1775                 pSib->origin.y = cwsy;
1776             }
1777         }
1778         pSib->drawable.x = pWin->drawable.x + pSib->origin.x;
1779         pSib->drawable.y = pWin->drawable.y + pSib->origin.y;
1780         SetWinSize (pSib);
1781         SetBorderSize (pSib);
1782         (*pScreen->PositionWindow)(pSib, pSib->drawable.x, pSib->drawable.y);
1783         if ( (pChild = pSib->firstChild) )
1784         {
1785             while (1)
1786             {
1787                 pChild->drawable.x = pChild->parent->drawable.x +
1788                                      pChild->origin.x;
1789                 pChild->drawable.y = pChild->parent->drawable.y +
1790                                      pChild->origin.y;
1791                 SetWinSize (pChild);
1792                 SetBorderSize (pChild);
1793                 (*pScreen->PositionWindow)(pChild,
1794                                     pChild->drawable.x, pChild->drawable.y);
1795                 if (pChild->firstChild)
1796                 {
1797                     pChild = pChild->firstChild;
1798                     continue;
1799                 }
1800                 while (!pChild->nextSib && (pChild != pSib))
1801                     pChild = pChild->parent;
1802                 if (pChild == pSib)
1803                     break;
1804                 pChild = pChild->nextSib;
1805             }
1806         }
1807     }
1808 }
1809
1810 #define GET_INT16(m, f) \
1811         if (m & mask) \
1812           { \
1813              f = (INT16) *pVlist;\
1814             pVlist++; \
1815          }
1816 #define GET_CARD16(m, f) \
1817         if (m & mask) \
1818          { \
1819             f = (CARD16) *pVlist;\
1820             pVlist++;\
1821          }
1822
1823 #define GET_CARD8(m, f) \
1824         if (m & mask) \
1825          { \
1826             f = (CARD8) *pVlist;\
1827             pVlist++;\
1828          }
1829
1830 #define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight))
1831
1832 #define IllegalInputOnlyConfigureMask (CWBorderWidth)
1833
1834 /*
1835  * IsSiblingAboveMe
1836  *     returns Above if pSib above pMe in stack or Below otherwise 
1837  */
1838
1839 static int
1840 #if NeedFunctionPrototypes
1841 IsSiblingAboveMe(
1842     register WindowPtr pMe,
1843     register WindowPtr pSib)
1844 #else
1845 IsSiblingAboveMe(pMe, pSib)
1846     register WindowPtr pMe, pSib;
1847 #endif
1848 {
1849     register WindowPtr pWin;
1850
1851     pWin = pMe->parent->firstChild;
1852     while (pWin)
1853     {
1854         if (pWin == pSib)
1855             return(Above);
1856         else if (pWin == pMe)
1857             return(Below);
1858         pWin = pWin->nextSib;
1859     }
1860     return(Below);
1861 }
1862
1863 static BoxPtr
1864 #if NeedFunctionPrototypes
1865 WindowExtents(
1866     register WindowPtr pWin,
1867     register BoxPtr pBox)
1868 #else
1869 WindowExtents(pWin, pBox)
1870     register WindowPtr pWin;
1871     register BoxPtr pBox;
1872 #endif
1873 {
1874     pBox->x1 = pWin->drawable.x - wBorderWidth (pWin);
1875     pBox->y1 = pWin->drawable.y - wBorderWidth (pWin);
1876     pBox->x2 = pWin->drawable.x + (int)pWin->drawable.width
1877                + wBorderWidth (pWin);
1878     pBox->y2 = pWin->drawable.y + (int)pWin->drawable.height
1879                + wBorderWidth (pWin);
1880     return(pBox);
1881 }
1882
1883 #ifdef SHAPE
1884 #define IS_SHAPED(pWin) (wBoundingShape (pWin) != (RegionPtr) NULL)
1885
1886 static RegionPtr
1887 #if NeedFunctionPrototypes
1888 MakeBoundingRegion (
1889     register WindowPtr  pWin,
1890     BoxPtr      pBox)
1891 #else
1892 MakeBoundingRegion (pWin, pBox)
1893     register WindowPtr  pWin;
1894     BoxPtr      pBox;
1895 #endif
1896 {
1897     RegionPtr   pRgn;
1898     REGION_PTR(pScreen, pWin)
1899
1900     pRgn = REGION_CREATE(pScreen, pBox, 1);
1901     if (wBoundingShape (pWin)) {
1902             REGION_TRANSLATE(pScreen, pRgn, -pWin->origin.x,
1903                                                   -pWin->origin.y);
1904             REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin));
1905             REGION_TRANSLATE(pScreen, pRgn, pWin->origin.x,
1906                                                   pWin->origin.y);
1907     }
1908     return pRgn;
1909 }
1910
1911 static Bool
1912 #if NeedFunctionPrototypes
1913 ShapeOverlap (
1914     WindowPtr   pWin,
1915     BoxPtr      pWinBox,
1916     WindowPtr   pSib,
1917     BoxPtr      pSibBox)
1918 #else
1919 ShapeOverlap (pWin, pWinBox, pSib, pSibBox)
1920     WindowPtr   pWin, pSib;
1921     BoxPtr      pWinBox, pSibBox;
1922 #endif
1923 {
1924     RegionPtr   pWinRgn, pSibRgn;
1925     register ScreenPtr  pScreen;
1926     Bool        ret;
1927
1928     if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib))
1929         return TRUE;
1930     pScreen = pWin->drawable.pScreen;
1931     pWinRgn = MakeBoundingRegion (pWin, pWinBox);
1932     pSibRgn = MakeBoundingRegion (pSib, pSibBox);
1933     REGION_INTERSECT(pScreen, pWinRgn, pWinRgn, pSibRgn);
1934     ret = REGION_NOTEMPTY(pScreen, pWinRgn);
1935     REGION_DESTROY(pScreen, pWinRgn);
1936     REGION_DESTROY(pScreen, pSibRgn);
1937     return ret;
1938 }
1939 #endif
1940
1941 static Bool
1942 #if NeedFunctionPrototypes
1943 AnyWindowOverlapsMe(
1944     WindowPtr pWin,
1945     WindowPtr pHead,
1946     register BoxPtr box)
1947 #else
1948 AnyWindowOverlapsMe(pWin, pHead, box)
1949     WindowPtr pWin, pHead;
1950     register BoxPtr box;
1951 #endif
1952 {
1953     register WindowPtr pSib;
1954     BoxRec sboxrec;
1955     register BoxPtr sbox;
1956
1957     for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib)
1958     {
1959         if (pSib->mapped)
1960         {
1961             sbox = WindowExtents(pSib, &sboxrec);
1962             if (BOXES_OVERLAP(sbox, box)
1963 #ifdef SHAPE
1964             && ShapeOverlap (pWin, box, pSib, sbox)
1965 #endif
1966             )
1967                 return(TRUE);
1968         }
1969     }
1970     return(FALSE);
1971 }
1972
1973 static Bool
1974 #if NeedFunctionPrototypes
1975 IOverlapAnyWindow(
1976     WindowPtr pWin,
1977     register BoxPtr box)
1978 #else
1979 IOverlapAnyWindow(pWin, box)
1980     WindowPtr pWin;
1981     register BoxPtr box;
1982 #endif
1983 {
1984     register WindowPtr pSib;
1985     BoxRec sboxrec;
1986     register BoxPtr sbox;
1987
1988     for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib)
1989     {
1990         if (pSib->mapped)
1991         {
1992             sbox = WindowExtents(pSib, &sboxrec);
1993             if (BOXES_OVERLAP(sbox, box)
1994 #ifdef SHAPE
1995             && ShapeOverlap (pWin, box, pSib, sbox)
1996 #endif
1997             )
1998                 return(TRUE);
1999         }
2000     }
2001     return(FALSE);
2002 }
2003
2004 /*
2005  *   WhereDoIGoInTheStack() 
2006  *        Given pWin and pSib and the relationshipe smode, return
2007  *        the window that pWin should go ABOVE.
2008  *        If a pSib is specified:
2009  *            Above:  pWin is placed just above pSib
2010  *            Below:  pWin is placed just below pSib
2011  *            TopIf:  if pSib occludes pWin, then pWin is placed
2012  *                    at the top of the stack
2013  *            BottomIf:  if pWin occludes pSib, then pWin is 
2014  *                       placed at the bottom of the stack
2015  *            Opposite: if pSib occludes pWin, then pWin is placed at the
2016  *                      top of the stack, else if pWin occludes pSib, then
2017  *                      pWin is placed at the bottom of the stack
2018  *
2019  *        If pSib is NULL:
2020  *            Above:  pWin is placed at the top of the stack
2021  *            Below:  pWin is placed at the bottom of the stack
2022  *            TopIf:  if any sibling occludes pWin, then pWin is placed at
2023  *                    the top of the stack
2024  *            BottomIf: if pWin occludes any sibline, then pWin is placed at
2025  *                      the bottom of the stack
2026  *            Opposite: if any sibling occludes pWin, then pWin is placed at
2027  *                      the top of the stack, else if pWin occludes any
2028  *                      sibling, then pWin is placed at the bottom of the stack
2029  *
2030  */
2031
2032 static WindowPtr
2033 #if NeedFunctionPrototypes
2034 WhereDoIGoInTheStack(
2035     register WindowPtr pWin,
2036     register WindowPtr pSib,
2037     short x,
2038     short y,
2039     unsigned short w,
2040     unsigned short h,
2041     int smode)
2042 #else
2043 WhereDoIGoInTheStack(pWin, pSib, x, y, w, h, smode)
2044     register WindowPtr pWin, pSib;
2045     short x, y;
2046     unsigned short w, h;
2047     int smode;
2048 #endif
2049 {
2050     BoxRec box;
2051     register ScreenPtr pScreen;
2052     WindowPtr pHead, pFirst;
2053
2054     if ((pWin == pWin->parent->firstChild) &&
2055         (pWin == pWin->parent->lastChild))
2056         return((WindowPtr ) NULL);
2057     pHead = RealChildHead(pWin->parent);
2058     pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild;
2059     pScreen = pWin->drawable.pScreen;
2060     box.x1 = x;
2061     box.y1 = y;
2062     box.x2 = x + (int)w;
2063     box.y2 = y + (int)h;
2064     switch (smode)
2065     {
2066       case Above:
2067         if (pSib)
2068            return(pSib);
2069         else if (pWin == pFirst)
2070             return(pWin->nextSib);
2071         else
2072             return(pFirst);
2073       case Below:
2074         if (pSib)
2075             if (pSib->nextSib != pWin)
2076                 return(pSib->nextSib);
2077             else
2078                 return(pWin->nextSib);
2079         else
2080             return NullWindow;
2081       case TopIf:
2082         if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs)
2083             return(pWin->nextSib);
2084         else if (pSib)
2085         {
2086             if ((IsSiblingAboveMe(pWin, pSib) == Above) &&
2087                 (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT))
2088                 return(pFirst);
2089             else
2090                 return(pWin->nextSib);
2091         }
2092         else if (AnyWindowOverlapsMe(pWin, pHead, &box))
2093             return(pFirst);
2094         else
2095             return(pWin->nextSib);
2096       case BottomIf:
2097         if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs)
2098             return(pWin->nextSib);
2099         else if (pSib)
2100         {
2101             if ((IsSiblingAboveMe(pWin, pSib) == Below) &&
2102                 (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT))
2103                 return NullWindow;
2104             else
2105                 return(pWin->nextSib);
2106         }
2107         else if (IOverlapAnyWindow(pWin, &box))
2108             return NullWindow;
2109         else
2110             return(pWin->nextSib);
2111       case Opposite:
2112         if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs)
2113             return(pWin->nextSib);
2114         else if (pSib)
2115         {
2116             if (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)
2117             {
2118                 if (IsSiblingAboveMe(pWin, pSib) == Above)
2119                     return(pFirst);
2120                 else
2121                     return NullWindow;
2122             }
2123             else
2124                 return(pWin->nextSib);
2125         }
2126         else if (AnyWindowOverlapsMe(pWin, pHead, &box))
2127         {
2128             /* If I'm occluded, I can't possibly be the first child
2129              * if (pWin == pWin->parent->firstChild)
2130              *    return pWin->nextSib;
2131              */
2132             return(pFirst);
2133         }
2134         else if (IOverlapAnyWindow(pWin, &box))
2135             return NullWindow;
2136         else
2137             return pWin->nextSib;
2138       default:
2139       {
2140         ErrorF("Internal error in ConfigureWindow, smode == %d\n",smode );
2141         return pWin->nextSib;
2142       }
2143     }
2144 }
2145
2146 static void
2147 #if NeedFunctionPrototypes
2148 ReflectStackChange(
2149     register WindowPtr pWin,
2150     register WindowPtr pSib,
2151     VTKind  kind)
2152 #else
2153 ReflectStackChange(pWin, pSib, kind)
2154     register WindowPtr pWin, pSib;
2155     VTKind  kind;
2156 #endif
2157 {
2158 /* Note that pSib might be NULL */
2159
2160     Bool WasViewable = (Bool)pWin->viewable;
2161     WindowPtr pParent;
2162     Bool anyMarked;
2163     WindowPtr pFirstChange;
2164 #ifdef DO_SAVE_UNDERS
2165     Bool        dosave = FALSE;
2166 #endif
2167     WindowPtr  pLayerWin;
2168     ScreenPtr pScreen = pWin->drawable.pScreen;
2169
2170     /* if this is a root window, can't be restacked */
2171     if (!(pParent = pWin->parent))
2172         return ;
2173
2174     pFirstChange = MoveWindowInStack(pWin, pSib);
2175
2176     if (WasViewable)
2177     {
2178         anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange,
2179                                                       &pLayerWin);
2180         if (pLayerWin != pWin) pFirstChange = pLayerWin;
2181 #ifdef DO_SAVE_UNDERS
2182         if (DO_SAVE_UNDERS(pWin))
2183         {
2184             dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange);
2185         }
2186 #endif /* DO_SAVE_UNDERS */
2187         if (anyMarked)
2188         {
2189             (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, kind);
2190             (*pScreen->HandleExposures)(pLayerWin->parent);
2191         }
2192 #ifdef DO_SAVE_UNDERS
2193         if (dosave)
2194             (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange);
2195 #endif /* DO_SAVE_UNDERS */
2196         if (anyMarked && pWin->drawable.pScreen->PostValidateTree)
2197             (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, kind);
2198     }
2199     if (pWin->realized)
2200         WindowsRestructured ();
2201 }
2202
2203 /*****
2204  * ConfigureWindow
2205  *****/
2206
2207 int
2208 ConfigureWindow(pWin, mask, vlist, client)
2209     register WindowPtr pWin;
2210     register Mask mask;
2211     XID *vlist;
2212     ClientPtr client;
2213 {
2214 #define RESTACK_WIN    0
2215 #define MOVE_WIN       1
2216 #define RESIZE_WIN     2
2217 #define REBORDER_WIN   3
2218     register WindowPtr pSib = NullWindow;
2219     register WindowPtr pParent = pWin->parent;
2220     Window sibwid;
2221     Mask index2, tmask;
2222     register XID *pVlist;
2223     short x,   y, beforeX, beforeY;
2224     unsigned short w = pWin->drawable.width,
2225                    h = pWin->drawable.height,
2226                    bw = pWin->borderWidth;
2227     int action, smode = Above;
2228 #ifdef XAPPGROUP
2229     ClientPtr win_owner;
2230     ClientPtr ag_leader = NULL;
2231 #endif
2232     xEvent event;
2233
2234     if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask))
2235         return(BadMatch);
2236
2237     if ((mask & CWSibling) && !(mask & CWStackMode))
2238         return(BadMatch);
2239
2240     pVlist = vlist;
2241
2242     if (pParent)
2243     {
2244         x = pWin->drawable.x - pParent->drawable.x - (int)bw;
2245         y = pWin->drawable.y - pParent->drawable.y - (int)bw;
2246     }
2247     else
2248     {
2249         x = pWin->drawable.x;
2250         y = pWin->drawable.y;
2251     }
2252     beforeX = x;
2253     beforeY = y;
2254     action = RESTACK_WIN;       
2255     if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth))))
2256     {
2257         GET_INT16(CWX, x);
2258         GET_INT16(CWY, y);
2259         action = MOVE_WIN;
2260     }
2261         /* or should be resized */
2262     else if (mask & (CWX |  CWY | CWWidth | CWHeight))
2263     {
2264         GET_INT16(CWX, x);
2265         GET_INT16(CWY, y);
2266         GET_CARD16(CWWidth, w);
2267         GET_CARD16 (CWHeight, h);
2268         if (!w || !h)
2269         {
2270             client->errorValue = 0;
2271             return BadValue;
2272         }
2273         action = RESIZE_WIN;
2274     }
2275     tmask = mask & ~ChangeMask;
2276     while (tmask)
2277     {
2278         index2 = (Mask)lowbit (tmask);
2279         tmask &= ~index2;
2280         switch (index2)
2281         {
2282           case CWBorderWidth:
2283             GET_CARD16(CWBorderWidth, bw);
2284             break;
2285           case CWSibling:
2286             sibwid = (Window ) *pVlist;
2287             pVlist++;
2288             pSib = (WindowPtr )SecurityLookupIDByType(client, sibwid,
2289                                                 RT_WINDOW, SecurityReadAccess);
2290             if (!pSib)
2291             {
2292                 client->errorValue = sibwid;
2293                 return(BadWindow);
2294             }
2295             if (pSib->parent != pParent)
2296                 return(BadMatch);
2297             if (pSib == pWin)
2298                 return(BadMatch);
2299             break;
2300           case CWStackMode:
2301             GET_CARD8(CWStackMode, smode);
2302             if ((smode != TopIf) && (smode != BottomIf) &&
2303                 (smode != Opposite) && (smode != Above) && (smode != Below))
2304             {
2305                 client->errorValue = smode;
2306                 return(BadValue);
2307             }
2308             break;
2309           default:
2310             client->errorValue = mask;
2311             return(BadValue);
2312         }
2313     }
2314         /* root really can't be reconfigured, so just return */
2315     if (!pParent)
2316         return Success;
2317
2318         /* Figure out if the window should be moved.  Doesnt
2319            make the changes to the window if event sent */
2320
2321     if (mask & CWStackMode)
2322         pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x,
2323                                     pParent->drawable.y + y,
2324                                     w + (bw << 1), h + (bw << 1), smode);
2325     else
2326         pSib = pWin->nextSib;
2327
2328 #ifdef XAPPGROUP
2329     win_owner = clients[CLIENT_ID(pWin->drawable.id)];
2330     ag_leader = XagLeader (win_owner);
2331 #endif
2332
2333     if ((!pWin->overrideRedirect) && 
2334         (RedirectSend(pParent)
2335 #ifdef XAPPGROUP
2336         || (win_owner->appgroup && ag_leader && 
2337             XagIsControlledRoot (client, pParent))
2338 #endif
2339         ))
2340     {
2341         event.u.u.type = ConfigureRequest;
2342         event.u.configureRequest.window = pWin->drawable.id;
2343         if (mask & CWSibling)
2344            event.u.configureRequest.sibling = sibwid;
2345         else
2346             event.u.configureRequest.sibling = None;
2347         if (mask & CWStackMode)
2348            event.u.u.detail = smode;
2349         else
2350             event.u.u.detail = Above;
2351         event.u.configureRequest.x = x;
2352         event.u.configureRequest.y = y;
2353         event.u.configureRequest.width = w;
2354         event.u.configureRequest.height = h;
2355         event.u.configureRequest.borderWidth = bw;
2356         event.u.configureRequest.valueMask = mask;
2357 #ifdef XAPPGROUP
2358         /* make sure if the ag_leader maps the window it goes to the wm */
2359         if (ag_leader && ag_leader != client && 
2360             XagIsControlledRoot (client, pParent)) {
2361             event.u.configureRequest.parent = XagId (win_owner);
2362             (void) TryClientEvents (ag_leader, &event, 1,
2363                                     NoEventMask, NoEventMask, NullGrab);
2364             return Success;
2365         }
2366 #endif
2367         event.u.configureRequest.parent = pParent->drawable.id;
2368         if (MaybeDeliverEventsToClient(pParent, &event, 1,
2369                 SubstructureRedirectMask, client) == 1)
2370             return(Success);
2371     }
2372     if (action == RESIZE_WIN)
2373     {
2374         Bool size_change = (w != pWin->drawable.width)
2375                         || (h != pWin->drawable.height);
2376         if (size_change && ((pWin->eventMask|wOtherEventMasks(pWin)) & ResizeRedirectMask))
2377         {
2378             xEvent eventT;
2379             eventT.u.u.type = ResizeRequest;
2380             eventT.u.resizeRequest.window = pWin->drawable.id;
2381             eventT.u.resizeRequest.width = w;
2382             eventT.u.resizeRequest.height = h;
2383             if (MaybeDeliverEventsToClient(pWin, &eventT, 1,
2384                                        ResizeRedirectMask, client) == 1)
2385             {
2386                 /* if event is delivered, leave the actual size alone. */
2387                 w = pWin->drawable.width;
2388                 h = pWin->drawable.height;
2389                 size_change = FALSE;
2390             }
2391         }
2392         if (!size_change)
2393         {
2394             if (mask & (CWX | CWY))
2395                 action = MOVE_WIN;
2396             else if (mask & (CWStackMode | CWBorderWidth))
2397                 action = RESTACK_WIN;
2398             else   /* really nothing to do */
2399                 return(Success) ;
2400         }
2401     }
2402
2403     if (action == RESIZE_WIN)
2404             /* we've already checked whether there's really a size change */
2405             goto ActuallyDoSomething;
2406     if ((mask & CWX) && (x != beforeX))
2407             goto ActuallyDoSomething;
2408     if ((mask & CWY) && (y != beforeY))
2409             goto ActuallyDoSomething;
2410     if ((mask & CWBorderWidth) && (bw != wBorderWidth (pWin)))
2411             goto ActuallyDoSomething;
2412     if (mask & CWStackMode)
2413     {
2414         if (pWin->nextSib != pSib)
2415             goto ActuallyDoSomething;
2416     }
2417     return(Success);
2418
2419 ActuallyDoSomething:
2420     if (SubStrSend(pWin, pParent))
2421     {
2422         event.u.u.type = ConfigureNotify;
2423         event.u.configureNotify.window = pWin->drawable.id;
2424         if (pSib)
2425             event.u.configureNotify.aboveSibling = pSib->drawable.id;
2426         else
2427             event.u.configureNotify.aboveSibling = None;
2428         event.u.configureNotify.x = x;
2429         event.u.configureNotify.y = y;
2430         event.u.configureNotify.width = w;
2431         event.u.configureNotify.height = h;
2432         event.u.configureNotify.borderWidth = bw;
2433         event.u.configureNotify.override = pWin->overrideRedirect;
2434         DeliverEvents(pWin, &event, 1, NullWindow);
2435     }
2436     if (mask & CWBorderWidth)
2437     {
2438         if (action == RESTACK_WIN)
2439         {
2440             action = MOVE_WIN;
2441             pWin->borderWidth = bw;
2442         }
2443         else if ((action == MOVE_WIN) &&
2444                  (beforeX + wBorderWidth (pWin) == x + (int)bw) &&
2445                  (beforeY + wBorderWidth (pWin) == y + (int)bw))
2446         {
2447             action = REBORDER_WIN;
2448             (*pWin->drawable.pScreen->ChangeBorderWidth)(pWin, bw);
2449         }
2450         else
2451             pWin->borderWidth = bw;
2452     }
2453     if (action == MOVE_WIN)
2454         (*pWin->drawable.pScreen->MoveWindow)(pWin, x, y, pSib,
2455                    (mask & CWBorderWidth) ? VTOther : VTMove);
2456     else if (action == RESIZE_WIN)
2457         (*pWin->drawable.pScreen->ResizeWindow)(pWin, x, y, w, h, pSib);
2458     else if (mask & CWStackMode)
2459         ReflectStackChange(pWin, pSib, VTOther);
2460
2461     if (action != RESTACK_WIN)
2462         CheckCursorConfinement(pWin);
2463
2464     return(Success);
2465 #undef RESTACK_WIN
2466 #undef MOVE_WIN
2467 #undef RESIZE_WIN
2468 #undef REBORDER_WIN
2469 }
2470
2471
2472 /******
2473  *
2474  * CirculateWindow
2475  *    For RaiseLowest, raises the lowest mapped child (if any) that is
2476  *    obscured by another child to the top of the stack.  For LowerHighest,
2477  *    lowers the highest mapped child (if any) that is obscuring another
2478  *    child to the bottom of the stack.  Exposure processing is performed 
2479  *
2480  ******/
2481
2482 int
2483 CirculateWindow(pParent, direction, client)
2484     WindowPtr pParent;
2485     int direction;
2486     ClientPtr client;
2487 {
2488     register WindowPtr pWin, pHead, pFirst;
2489     xEvent event;
2490     BoxRec box;
2491
2492     pHead = RealChildHead(pParent);
2493     pFirst = pHead ? pHead->nextSib : pParent->firstChild;
2494     if (direction == RaiseLowest)
2495     {
2496         for (pWin = pParent->lastChild;
2497              (pWin != pHead) &&
2498              !(pWin->mapped &&
2499                AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box)));
2500              pWin = pWin->prevSib) ;
2501         if (pWin == pHead)
2502             return Success;
2503     }
2504     else
2505     {
2506         for (pWin = pFirst;
2507              pWin &&
2508              !(pWin->mapped &&
2509                IOverlapAnyWindow(pWin, WindowExtents(pWin, &box)));
2510              pWin = pWin->nextSib) ;
2511         if (!pWin)
2512             return Success;
2513     }
2514
2515     event.u.circulate.window = pWin->drawable.id;
2516     event.u.circulate.parent = pParent->drawable.id;
2517     event.u.circulate.event = pParent->drawable.id;
2518     if (direction == RaiseLowest)
2519         event.u.circulate.place = PlaceOnTop;
2520     else
2521         event.u.circulate.place = PlaceOnBottom;
2522
2523     if (RedirectSend(pParent))
2524     {
2525         event.u.u.type = CirculateRequest;
2526         if (MaybeDeliverEventsToClient(pParent, &event, 1,
2527                 SubstructureRedirectMask, client) == 1)
2528             return(Success);
2529     }
2530
2531     event.u.u.type = CirculateNotify;
2532     DeliverEvents(pWin, &event, 1, NullWindow);
2533     ReflectStackChange(pWin,
2534                        (direction == RaiseLowest) ? pFirst : NullWindow,
2535                        VTStack);
2536
2537     return(Success);
2538 }
2539
2540 static int
2541 #if NeedFunctionPrototypes
2542 CompareWIDs(
2543     WindowPtr pWin,
2544     pointer   value) /* must conform to VisitWindowProcPtr */
2545 #else
2546 CompareWIDs(pWin, value)
2547     WindowPtr pWin;
2548     pointer   value; /* must conform to VisitWindowProcPtr */
2549 #endif
2550 {
2551     Window *wid = (Window *)value;
2552
2553     if (pWin->drawable.id == *wid)
2554        return(WT_STOPWALKING);
2555     else
2556        return(WT_WALKCHILDREN);
2557 }
2558
2559 /*****
2560  *  ReparentWindow
2561  *****/
2562
2563 int
2564 ReparentWindow(pWin, pParent, x, y, client)
2565     register WindowPtr pWin, pParent;
2566     int x,y;
2567     ClientPtr client;
2568 {
2569     WindowPtr pPrev, pPriorParent;
2570     Bool WasMapped = (Bool)(pWin->mapped);
2571     xEvent event;
2572     int bw = wBorderWidth (pWin);
2573     register ScreenPtr pScreen;
2574
2575     pScreen = pWin->drawable.pScreen;
2576     if (TraverseTree(pWin, CompareWIDs, (pointer)&pParent->drawable.id) == WT_STOPWALKING)
2577         return(BadMatch);               
2578     if (!MakeWindowOptional(pWin))
2579         return(BadAlloc);
2580
2581     if (WasMapped)
2582        UnmapWindow(pWin, FALSE);
2583
2584     event.u.u.type = ReparentNotify;
2585     event.u.reparent.window = pWin->drawable.id;
2586     event.u.reparent.parent = pParent->drawable.id;
2587     event.u.reparent.x = x;
2588     event.u.reparent.y = y;
2589     event.u.reparent.override = pWin->overrideRedirect;
2590     DeliverEvents(pWin, &event, 1, pParent);
2591
2592     /* take out of sibling chain */
2593
2594     pPriorParent = pPrev = pWin->parent;
2595     if (pPrev->firstChild == pWin)
2596         pPrev->firstChild = pWin->nextSib;
2597     if (pPrev->lastChild == pWin)
2598         pPrev->lastChild = pWin->prevSib;
2599
2600     if (pWin->nextSib)
2601         pWin->nextSib->prevSib = pWin->prevSib;
2602     if (pWin->prevSib)
2603         pWin->prevSib->nextSib = pWin->nextSib;
2604
2605     /* insert at begining of pParent */
2606     pWin->parent = pParent;
2607     pPrev = RealChildHead(pParent);
2608     if (pPrev)
2609     {
2610         pWin->nextSib = pPrev->nextSib;
2611         if (pPrev->nextSib)
2612             pPrev->nextSib->prevSib = pWin;
2613         else
2614             pParent->lastChild = pWin;
2615         pPrev->nextSib = pWin;
2616         pWin->prevSib = pPrev;
2617     }
2618     else
2619     {
2620         pWin->nextSib = pParent->firstChild;
2621         pWin->prevSib = NullWindow;
2622         if (pParent->firstChild)
2623             pParent->firstChild->prevSib = pWin;
2624         else
2625             pParent->lastChild = pWin;
2626         pParent->firstChild = pWin;
2627     }
2628
2629     pWin->origin.x = x + bw;
2630     pWin->origin.y = y + bw;
2631     pWin->drawable.x = x + bw + pParent->drawable.x;
2632     pWin->drawable.y = y + bw + pParent->drawable.y;
2633
2634     /* clip to parent */
2635     SetWinSize (pWin);
2636     SetBorderSize (pWin);
2637
2638     if (pScreen->ReparentWindow)
2639         (*pScreen->ReparentWindow)(pWin, pPriorParent);
2640     (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y);
2641     ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
2642
2643     CheckWindowOptionalNeed(pWin);
2644
2645     if (WasMapped)
2646         MapWindow(pWin, client);
2647     RecalculateDeliverableEvents(pWin);
2648     return(Success);
2649 }
2650
2651 static void
2652 #if NeedFunctionPrototypes
2653 RealizeTree(WindowPtr pWin)
2654 #else
2655 RealizeTree(pWin)
2656     WindowPtr pWin;
2657 #endif
2658 {
2659     register WindowPtr pChild;
2660     RealizeWindowProcPtr Realize;
2661
2662     Realize = pWin->drawable.pScreen->RealizeWindow;
2663     pChild = pWin;
2664     while (1)
2665     {
2666         if (pChild->mapped)
2667         {
2668             pChild->realized = TRUE;
2669 #ifdef DO_SAVE_UNDERS
2670             if (pChild->saveUnder)
2671                 deltaSaveUndersViewable++;
2672 #endif
2673             pChild->viewable = (pChild->drawable.class == InputOutput);
2674             (* Realize)(pChild);
2675             if (pChild->firstChild)
2676             {
2677                 pChild = pChild->firstChild;
2678                 continue;
2679             }
2680         }
2681         while (!pChild->nextSib && (pChild != pWin))
2682             pChild = pChild->parent;
2683         if (pChild == pWin)
2684             return;
2685         pChild = pChild->nextSib;
2686     }
2687 }
2688
2689 /*****
2690  * MapWindow
2691  *    If some other client has selected SubStructureReDirect on the parent
2692  *    and override-redirect is xFalse, then a MapRequest event is generated,
2693  *    but the window remains unmapped.  Otherwise, the window is mapped and a
2694  *    MapNotify event is generated.
2695  *****/
2696
2697 int
2698 MapWindow(pWin, client)
2699     register WindowPtr pWin;
2700     ClientPtr client;
2701 {
2702     register ScreenPtr pScreen;
2703
2704     register WindowPtr pParent;
2705 #ifdef DO_SAVE_UNDERS
2706     Bool        dosave = FALSE;
2707 #endif
2708     WindowPtr  pLayerWin;
2709
2710     if (pWin->mapped)
2711         return(Success);
2712
2713 #ifdef XCSECURITY
2714     /*  don't let an untrusted client map a child-of-trusted-window, InputOnly
2715      *  window; too easy to steal device input
2716      */
2717     if ( (client->trustLevel != XSecurityClientTrusted) &&
2718          (pWin->drawable.class == InputOnly) &&
2719          (wClient(pWin->parent)->trustLevel == XSecurityClientTrusted) )
2720          return Success;
2721 #endif  
2722
2723     pScreen = pWin->drawable.pScreen;
2724     if ( (pParent = pWin->parent) )
2725     {
2726         xEvent event;
2727         Bool anyMarked;
2728 #ifdef XAPPGROUP
2729         ClientPtr win_owner = clients[CLIENT_ID(pWin->drawable.id)];
2730         ClientPtr ag_leader = XagLeader (win_owner);
2731 #endif
2732
2733         if ((!pWin->overrideRedirect) && 
2734             (RedirectSend(pParent)
2735 #ifdef XAPPGROUP
2736             || (win_owner->appgroup && ag_leader &&
2737                 XagIsControlledRoot (client, pParent))
2738 #endif
2739         ))
2740         {
2741             event.u.u.type = MapRequest;
2742             event.u.mapRequest.window = pWin->drawable.id;
2743 #ifdef XAPPGROUP
2744             /* make sure if the ag_leader maps the window it goes to the wm */
2745             if (ag_leader && ag_leader != client &&
2746                 XagIsControlledRoot (client, pParent)) {
2747                 event.u.mapRequest.parent = XagId (win_owner);
2748                 (void) TryClientEvents (ag_leader, &event, 1,
2749                                         NoEventMask, NoEventMask, NullGrab);
2750                 return Success;
2751             }
2752 #endif
2753             event.u.mapRequest.parent = pParent->drawable.id;
2754
2755             if (MaybeDeliverEventsToClient(pParent, &event, 1,
2756                 SubstructureRedirectMask, client) == 1)
2757                 return(Success);
2758         }
2759
2760         pWin->mapped = TRUE;
2761         if (SubStrSend(pWin, pParent))
2762         {
2763             event.u.u.type = MapNotify;
2764             event.u.mapNotify.window = pWin->drawable.id;
2765             event.u.mapNotify.override = pWin->overrideRedirect;
2766             DeliverEvents(pWin, &event, 1, NullWindow);
2767         }
2768
2769         if (!pParent->realized)
2770             return(Success);
2771         RealizeTree(pWin);
2772         if (pWin->viewable)
2773         {
2774             anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
2775                                                           &pLayerWin);
2776 #ifdef DO_SAVE_UNDERS
2777             if (DO_SAVE_UNDERS(pWin))
2778             {
2779                 dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib);
2780             }
2781 #endif /* DO_SAVE_UNDERS */
2782             if (anyMarked)
2783             {
2784                 (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTMap);
2785                 (*pScreen->HandleExposures)(pLayerWin->parent);
2786             }
2787 #ifdef DO_SAVE_UNDERS
2788             if (dosave)
2789                 (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib);
2790 #endif /* DO_SAVE_UNDERS */
2791         if (anyMarked && pScreen->PostValidateTree)
2792             (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTMap);
2793         }
2794         WindowsRestructured ();
2795     }
2796     else
2797     {
2798         RegionRec   temp;
2799
2800         pWin->mapped = TRUE;
2801         pWin->realized = TRUE;     /* for roots */
2802         pWin->viewable = pWin->drawable.class == InputOutput;
2803         /* We SHOULD check for an error value here XXX */
2804         (*pScreen->RealizeWindow)(pWin);
2805         if (pScreen->ClipNotify)
2806             (*pScreen->ClipNotify) (pWin, 0, 0);
2807         if (pScreen->PostValidateTree)
2808             (*pScreen->PostValidateTree)(NullWindow, pWin, VTMap);
2809         REGION_INIT(pScreen, &temp, NullBox, 0);
2810         REGION_COPY(pScreen, &temp, &pWin->clipList);
2811         (*pScreen->WindowExposures) (pWin, &temp, NullRegion);
2812         REGION_UNINIT(pScreen, &temp);
2813     }
2814
2815     return(Success);
2816 }
2817
2818
2819 /*****
2820  * MapSubwindows
2821  *    Performs a MapWindow all unmapped children of the window, in top
2822  *    to bottom stacking order.
2823  *****/
2824
2825 void
2826 MapSubwindows(pParent, client)
2827     register WindowPtr pParent;
2828     ClientPtr client;
2829 {
2830     register WindowPtr  pWin;
2831     WindowPtr           pFirstMapped = NullWindow;
2832 #ifdef DO_SAVE_UNDERS
2833     WindowPtr           pFirstSaveUndered = NullWindow;
2834 #endif
2835     register ScreenPtr  pScreen;
2836     register Mask       parentRedirect;
2837     register Mask       parentNotify;
2838     xEvent              event;
2839     Bool                anyMarked;
2840 #ifdef DO_SAVE_UNDERS
2841     Bool        dosave = FALSE;
2842 #endif
2843     WindowPtr           pLayerWin;
2844
2845     pScreen = pParent->drawable.pScreen;
2846     parentRedirect = RedirectSend(pParent);
2847     parentNotify = SubSend(pParent);
2848     anyMarked = FALSE;
2849     for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib)
2850     {
2851         if (!pWin->mapped)
2852         {
2853             if (parentRedirect && !pWin->overrideRedirect)
2854             {
2855                 event.u.u.type = MapRequest;
2856                 event.u.mapRequest.window = pWin->drawable.id;
2857                 event.u.mapRequest.parent = pParent->drawable.id;
2858     
2859                 if (MaybeDeliverEventsToClient(pParent, &event, 1,
2860                     SubstructureRedirectMask, client) == 1)
2861                     continue;
2862             }
2863     
2864             pWin->mapped = TRUE;
2865             if (parentNotify || StrSend(pWin))
2866             {
2867                 event.u.u.type = MapNotify;
2868                 event.u.mapNotify.window = pWin->drawable.id;
2869                 event.u.mapNotify.override = pWin->overrideRedirect;
2870                 DeliverEvents(pWin, &event, 1, NullWindow);
2871             }
2872     
2873             if (!pFirstMapped)
2874                 pFirstMapped = pWin;
2875             if (pParent->realized)
2876             {
2877                 RealizeTree(pWin);
2878                 if (pWin->viewable)
2879                 {
2880                     anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin,
2881                                                         (WindowPtr *)NULL);
2882 #ifdef DO_SAVE_UNDERS
2883                     if (DO_SAVE_UNDERS(pWin))
2884                     {
2885                         dosave = TRUE;
2886                     }
2887 #endif /* DO_SAVE_UNDERS */
2888                 }
2889             }
2890         }
2891     }
2892
2893     if (pFirstMapped)
2894     {
2895         pLayerWin = (*pScreen->GetLayerWindow)(pParent);
2896         if (pLayerWin->parent != pParent) {
2897             anyMarked |= (*pScreen->MarkOverlappedWindows)(pLayerWin,
2898                                                            pLayerWin,
2899                                                            (WindowPtr *)NULL);
2900             pFirstMapped = pLayerWin;
2901         }
2902         if (anyMarked)
2903         {
2904 #ifdef DO_SAVE_UNDERS
2905             if (pLayerWin->parent != pParent)
2906             {
2907                 if (dosave || (DO_SAVE_UNDERS(pLayerWin)))
2908                 {
2909                     dosave = (*pScreen->ChangeSaveUnder)(pLayerWin,
2910                                                          pLayerWin);
2911                 }
2912             }
2913             else if (dosave)
2914             {
2915                 dosave = FALSE;
2916                 for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib)
2917                 {
2918                     if (DO_SAVE_UNDERS(pWin))
2919                     {
2920                         dosave |= (*pScreen->ChangeSaveUnder)(pWin,
2921                                                               pWin->nextSib);
2922                         if (dosave && !pFirstSaveUndered)
2923                             pFirstSaveUndered = pWin;
2924                     }
2925                 }
2926             }
2927 #endif /* DO_SAVE_UNDERS */
2928             (*pScreen->ValidateTree)(pLayerWin->parent, pFirstMapped, VTMap);
2929             (*pScreen->HandleExposures)(pLayerWin->parent);
2930         }
2931 #ifdef DO_SAVE_UNDERS
2932         if (dosave)
2933             (*pScreen->PostChangeSaveUnder)(pLayerWin,
2934                                             pFirstSaveUndered->nextSib);
2935 #endif /* DO_SAVE_UNDERS */
2936         if (anyMarked && pScreen->PostValidateTree)
2937             (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstMapped,
2938                                          VTMap);
2939         WindowsRestructured ();
2940     }
2941 }
2942
2943 static void
2944 #if NeedFunctionPrototypes
2945 UnrealizeTree(
2946     WindowPtr pWin,
2947     Bool fromConfigure)
2948 #else
2949 UnrealizeTree(pWin, fromConfigure)
2950     WindowPtr pWin;
2951     Bool fromConfigure;
2952 #endif
2953 {
2954     register WindowPtr pChild;
2955     UnrealizeWindowProcPtr Unrealize;
2956     MarkUnrealizedWindowProcPtr MarkUnrealizedWindow;
2957
2958     Unrealize = pWin->drawable.pScreen->UnrealizeWindow;
2959     MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow;
2960     pChild = pWin;
2961     while (1)
2962     {
2963         if (pChild->realized)
2964         {
2965             pChild->realized = FALSE;
2966             pChild->visibility = VisibilityNotViewable;
2967             (* Unrealize)(pChild);
2968             DeleteWindowFromAnyEvents(pChild, FALSE);
2969             if (pChild->viewable)
2970             {
2971 #ifdef DO_SAVE_UNDERS
2972                 if (pChild->saveUnder)
2973                     deltaSaveUndersViewable--;
2974 #endif
2975                 pChild->viewable = FALSE;
2976                 if (pChild->backStorage)
2977                     (*pChild->drawable.pScreen->SaveDoomedAreas)(
2978                                             pChild, &pChild->clipList, 0, 0);
2979                 (* MarkUnrealizedWindow)(pChild, pWin, fromConfigure);
2980                 pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
2981             }
2982             if (pChild->firstChild)
2983             {
2984                 pChild = pChild->firstChild;
2985                 continue;
2986             }
2987         }
2988         while (!pChild->nextSib && (pChild != pWin))
2989             pChild = pChild->parent;
2990         if (pChild == pWin)
2991             return;
2992         pChild = pChild->nextSib;
2993     }
2994 }
2995
2996 /*****
2997  * UnmapWindow
2998  *    If the window is already unmapped, this request has no effect.
2999  *    Otherwise, the window is unmapped and an UnMapNotify event is
3000  *    generated.  Cannot unmap a root window.
3001  *****/
3002
3003 int
3004 UnmapWindow(pWin, fromConfigure)
3005     register WindowPtr pWin;
3006     Bool fromConfigure;
3007 {
3008     register WindowPtr pParent;
3009     xEvent event;
3010     Bool wasRealized = (Bool)pWin->realized;
3011     Bool wasViewable = (Bool)pWin->viewable;
3012     ScreenPtr pScreen = pWin->drawable.pScreen;
3013     WindowPtr pLayerWin = pWin;
3014
3015     if ((!pWin->mapped) || (!(pParent = pWin->parent)))
3016         return(Success);
3017     if (SubStrSend(pWin, pParent))
3018     {
3019         event.u.u.type = UnmapNotify;
3020         event.u.unmapNotify.window = pWin->drawable.id;
3021         event.u.unmapNotify.fromConfigure = fromConfigure;
3022         DeliverEvents(pWin, &event, 1, NullWindow);
3023     }
3024     if (wasViewable && !fromConfigure)
3025     {
3026         pWin->valdata = UnmapValData;
3027         (*pScreen->MarkOverlappedWindows)(pWin, pWin->nextSib, &pLayerWin);
3028         (*pScreen->MarkWindow)(pLayerWin->parent);
3029     }
3030     pWin->mapped = FALSE;
3031     if (wasRealized)
3032         UnrealizeTree(pWin, fromConfigure);
3033     if (wasViewable)
3034     {
3035         if (!fromConfigure)
3036         {
3037             (*pScreen->ValidateTree)(pLayerWin->parent, pWin, VTUnmap);
3038             (*pScreen->HandleExposures)(pLayerWin->parent);
3039         }
3040 #ifdef DO_SAVE_UNDERS
3041         if (DO_SAVE_UNDERS(pWin))
3042         {
3043             if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib) )
3044             {
3045                 (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib);
3046             }
3047         }
3048         pWin->DIXsaveUnder = FALSE;
3049 #endif /* DO_SAVE_UNDERS */
3050         if (!fromConfigure && pScreen->PostValidateTree)
3051             (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap);
3052     }
3053     if (wasRealized && !fromConfigure)
3054         WindowsRestructured ();
3055     return(Success);
3056 }
3057
3058 /*****
3059  * UnmapSubwindows
3060  *    Performs an UnmapWindow request with the specified mode on all mapped
3061  *    children of the window, in bottom to top stacking order.
3062  *****/
3063
3064 void
3065 UnmapSubwindows(pWin)
3066     register WindowPtr pWin;
3067 {
3068     register WindowPtr pChild, pHead;
3069     xEvent event;
3070     Bool wasRealized = (Bool)pWin->realized;
3071     Bool wasViewable = (Bool)pWin->viewable;
3072     Bool anyMarked = FALSE;
3073     Mask parentNotify;
3074     WindowPtr pLayerWin;
3075     ScreenPtr pScreen = pWin->drawable.pScreen;
3076
3077     if (!pWin->firstChild)
3078         return;
3079     parentNotify = SubSend(pWin);
3080     pHead = RealChildHead(pWin);
3081
3082     if (wasViewable)
3083         pLayerWin = (*pScreen->GetLayerWindow)(pWin);
3084
3085     for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
3086     {
3087         if (pChild->mapped)
3088         {
3089             if (parentNotify || StrSend(pChild))
3090             {
3091                 event.u.u.type = UnmapNotify;
3092                 event.u.unmapNotify.window = pChild->drawable.id;
3093                 event.u.unmapNotify.fromConfigure = xFalse;
3094                 DeliverEvents(pChild, &event, 1, NullWindow);
3095             }
3096             if (pChild->viewable)
3097             {
3098                 pChild->valdata = UnmapValData;
3099                 anyMarked = TRUE;
3100             }
3101             pChild->mapped = FALSE;
3102             if (pChild->realized)
3103                 UnrealizeTree(pChild, FALSE);
3104             if (wasViewable)
3105             {
3106 #ifdef DO_SAVE_UNDERS
3107                 pChild->DIXsaveUnder = FALSE;
3108 #endif /* DO_SAVE_UNDERS */
3109                 if (pChild->backStorage)
3110                     (*pScreen->SaveDoomedAreas)(
3111                                             pChild, &pChild->clipList, 0, 0);
3112             }
3113         }
3114     }
3115     if (wasViewable)
3116     {
3117         if (anyMarked)
3118         {
3119             if (pLayerWin->parent == pWin)
3120                 (*pScreen->MarkWindow)(pWin);
3121             else
3122             {
3123                 WindowPtr ptmp;
3124                 (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin,
3125                                                   (WindowPtr *)NULL);
3126                 (*pScreen->MarkWindow)(pLayerWin->parent);
3127                 
3128                 /* Windows between pWin and pLayerWin may not have been marked */
3129                 ptmp = pWin;
3130  
3131                 while (ptmp != pLayerWin->parent)
3132                 {
3133                     (*pScreen->MarkWindow)(ptmp);
3134                     ptmp = ptmp->parent;
3135                 }
3136                 pHead = pWin->firstChild;
3137             }
3138             (*pScreen->ValidateTree)(pLayerWin->parent, pHead, VTUnmap);
3139             (*pScreen->HandleExposures)(pLayerWin->parent);
3140         }
3141 #ifdef DO_SAVE_UNDERS
3142         if (DO_SAVE_UNDERS(pWin))
3143         {
3144             if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin))
3145                 (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin);
3146         }
3147 #endif /* DO_SAVE_UNDERS */
3148         if (anyMarked && pScreen->PostValidateTree)
3149             (*pScreen->PostValidateTree)(pLayerWin->parent, pHead, VTUnmap);
3150     }
3151     if (wasRealized)
3152         WindowsRestructured ();
3153 }
3154
3155
3156 void
3157 HandleSaveSet(client)
3158     register ClientPtr client;
3159 {
3160     register WindowPtr pParent, pWin;
3161     register int j;
3162
3163     for (j=0; j<client->numSaved; j++)
3164     {
3165         pWin = (WindowPtr)client->saveSet[j];
3166         pParent = pWin->parent;
3167         while (pParent && (wClient (pParent) == client))
3168             pParent = pParent->parent;
3169         if (pParent)
3170         {
3171             if (pParent != pWin->parent)
3172             {
3173                 ReparentWindow(pWin, pParent,
3174                                pWin->drawable.x - wBorderWidth (pWin) - pParent->drawable.x,
3175                                pWin->drawable.y - wBorderWidth (pWin) - pParent->drawable.y,
3176                                client);
3177                 if(!pWin->realized && pWin->mapped)
3178                     pWin->mapped = FALSE;
3179             }
3180             MapWindow(pWin, client);
3181         }
3182     }
3183     xfree(client->saveSet);
3184     client->numSaved = 0;
3185     client->saveSet = (pointer *)NULL;
3186 }
3187
3188 Bool
3189 VisibleBoundingBoxFromPoint(pWin, x, y, box)
3190     register WindowPtr pWin;
3191     int x, y;   /* in root */
3192     BoxPtr box;   /* "return" value */
3193 {
3194     if (!pWin->realized)
3195         return (FALSE);
3196     if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->clipList, x, y, box))
3197         return(TRUE);
3198     return(FALSE);
3199 }
3200
3201 Bool
3202 PointInWindowIsVisible(pWin, x, y)
3203     register WindowPtr pWin;
3204     int x, y;   /* in root */
3205 {
3206     BoxRec box;
3207
3208     if (!pWin->realized)
3209         return (FALSE);
3210     if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderClip,
3211                                                   x, y, &box))
3212         return(TRUE);
3213     return(FALSE);
3214 }
3215
3216
3217 RegionPtr
3218 NotClippedByChildren(pWin)
3219     register WindowPtr pWin;
3220 {
3221     register ScreenPtr pScreen;
3222     RegionPtr pReg;
3223
3224     pScreen = pWin->drawable.pScreen;
3225     pReg = REGION_CREATE(pScreen, NullBox, 1);
3226     if (pWin->parent ||
3227         screenIsSaved != SCREEN_SAVER_ON ||
3228         !HasSaverWindow (pWin->drawable.pScreen->myNum))
3229     {
3230         REGION_INTERSECT(pScreen, pReg, &pWin->borderClip, &pWin->winSize);
3231     }
3232     return(pReg);
3233 }
3234
3235
3236 void
3237 SendVisibilityNotify(pWin)
3238     WindowPtr pWin;
3239 {
3240     xEvent event;
3241     event.u.u.type = VisibilityNotify;
3242     event.u.visibility.window = pWin->drawable.id;
3243     event.u.visibility.state = pWin->visibility;
3244     DeliverEvents(pWin, &event, 1, NullWindow);
3245 }
3246
3247
3248 #define RANDOM_WIDTH 32
3249
3250 #ifndef NOLOGOHACK
3251 extern int logoScreenSaver;
3252 static void DrawLogo(
3253 #if NeedFunctionPrototypes
3254     WindowPtr /*pWin*/
3255 #endif
3256 );
3257 #endif
3258
3259 void
3260 SaveScreens(on, mode)
3261     int on;
3262     int mode;
3263 {
3264     int i;
3265     int what;
3266     int type;
3267
3268     if (on == SCREEN_SAVER_FORCER)
3269     {
3270         UpdateCurrentTimeIf();
3271         lastDeviceEventTime = currentTime;
3272         if (mode == ScreenSaverReset)
3273             what = SCREEN_SAVER_OFF;
3274         else
3275             what = SCREEN_SAVER_ON;
3276         type = what;
3277     }
3278     else
3279     {
3280         what = on;
3281         type = what;
3282         if (what == screenIsSaved)
3283             type = SCREEN_SAVER_CYCLE;
3284     }
3285     for (i = 0; i < screenInfo.numScreens; i++)
3286     {
3287         if (on == SCREEN_SAVER_FORCER)
3288            (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], on);
3289         if (savedScreenInfo[i].ExternalScreenSaver)
3290         {
3291             if ((*savedScreenInfo[i].ExternalScreenSaver)
3292                 (screenInfo.screens[i], type, on == SCREEN_SAVER_FORCER))
3293                 continue;
3294         }
3295         if (type == screenIsSaved)
3296             continue;
3297         switch (type) {
3298         case SCREEN_SAVER_OFF:
3299             if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED)
3300             {
3301                (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i],
3302                                                       what);
3303             }
3304             else if (HasSaverWindow (i))
3305             {
3306                 savedScreenInfo[i].pWindow = NullWindow;
3307                 FreeResource(savedScreenInfo[i].wid, RT_NONE);
3308             }
3309             break;
3310         case SCREEN_SAVER_CYCLE:
3311             if (savedScreenInfo[i].blanked == SCREEN_IS_TILED)
3312             {
3313                 WindowPtr pWin = savedScreenInfo[i].pWindow;
3314                 /* make it look like screen saver is off, so that
3315                  * NotClippedByChildren will compute a clip list
3316                  * for the root window, so miPaintWindow works
3317                  */
3318                 screenIsSaved = SCREEN_SAVER_OFF;
3319 #ifndef NOLOGOHACK
3320                 if (logoScreenSaver)
3321                     (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, FALSE);
3322 #endif
3323                 (*pWin->drawable.pScreen->MoveWindow)(pWin,
3324                            (short)(-(rand() % RANDOM_WIDTH)),
3325                            (short)(-(rand() % RANDOM_WIDTH)),
3326                            pWin->nextSib, VTMove);
3327 #ifndef NOLOGOHACK
3328                 if (logoScreenSaver)
3329                     DrawLogo(pWin);
3330 #endif
3331                 screenIsSaved = SCREEN_SAVER_ON;
3332             }
3333             break;
3334         case SCREEN_SAVER_ON:
3335             if (ScreenSaverBlanking != DontPreferBlanking)
3336             {
3337                 if ((* screenInfo.screens[i]->SaveScreen)
3338                    (screenInfo.screens[i], what))
3339                 {
3340                    savedScreenInfo[i].blanked = SCREEN_IS_BLANKED;
3341                    continue;
3342                 }
3343                 if ((ScreenSaverAllowExposures != DontAllowExposures) &&
3344                     TileScreenSaver(i, SCREEN_IS_BLACK))
3345                 {
3346                     savedScreenInfo[i].blanked = SCREEN_IS_BLACK;
3347                     continue;
3348                 }
3349             }
3350             if ((ScreenSaverAllowExposures != DontAllowExposures) &&
3351                 TileScreenSaver(i, SCREEN_IS_TILED))
3352             {
3353                 savedScreenInfo[i].blanked = SCREEN_IS_TILED;
3354             }
3355             else
3356                 savedScreenInfo[i].blanked = SCREEN_ISNT_SAVED;
3357             break;
3358         }
3359     }
3360     screenIsSaved = what;
3361 }
3362
3363 static Bool
3364 #if NeedFunctionPrototypes
3365 TileScreenSaver(int i, int kind)
3366 #else
3367 TileScreenSaver(i, kind)
3368     int i;
3369     int kind;
3370 #endif
3371 {
3372     int j;
3373     int result;
3374     XID attributes[3];
3375     Mask mask;
3376     WindowPtr pWin;             
3377     CursorMetricRec cm;
3378     unsigned char *srcbits, *mskbits;
3379     CursorPtr cursor;
3380     XID     cursorID;
3381     int attri;
3382
3383     mask = 0;
3384     attri = 0;
3385     switch (kind) {
3386     case SCREEN_IS_TILED:
3387         switch (WindowTable[i]->backgroundState) {
3388         case BackgroundPixel:
3389             attributes[attri++] = WindowTable[i]->background.pixel;
3390             mask |= CWBackPixel;
3391             break;
3392         case BackgroundPixmap:
3393             attributes[attri++] = None;
3394             mask |= CWBackPixmap;
3395             break;
3396         default:
3397             break;
3398         }
3399         break;
3400     case SCREEN_IS_BLACK:
3401         attributes[attri++] = WindowTable[i]->drawable.pScreen->blackPixel;
3402         mask |= CWBackPixel;
3403         break;
3404     }
3405     mask |= CWOverrideRedirect;
3406     attributes[attri++] = xTrue;
3407
3408     /*
3409      * create a blank cursor
3410      */
3411
3412     cm.width=16;
3413     cm.height=16;
3414     cm.xhot=8;
3415     cm.yhot=8;
3416     srcbits = (unsigned char *)xalloc( BitmapBytePad(32)*16);
3417     mskbits = (unsigned char *)xalloc( BitmapBytePad(32)*16);
3418     if (!srcbits || !mskbits)
3419     {
3420         xfree(srcbits);
3421         xfree(mskbits);
3422         cursor = 0;
3423     }
3424     else
3425     {
3426         for (j=0; j<BitmapBytePad(32)*16; j++)
3427             srcbits[j] = mskbits[j] = 0x0;
3428         cursor = AllocCursor(srcbits, mskbits, &cm, 0, 0, 0, 0, 0, 0);
3429         if (cursor)
3430         {
3431             cursorID = FakeClientID(0);
3432             if (AddResource (cursorID, RT_CURSOR, (pointer) cursor))
3433             {
3434                 attributes[attri] = cursorID;
3435                 mask |= CWCursor;
3436             }
3437             else
3438                 cursor = 0;
3439         }
3440         else
3441         {
3442             xfree (srcbits);
3443             xfree (mskbits);
3444         }
3445     }
3446
3447     pWin = savedScreenInfo[i].pWindow =
3448          CreateWindow(savedScreenInfo[i].wid,
3449               WindowTable[i],
3450               -RANDOM_WIDTH, -RANDOM_WIDTH,
3451               (unsigned short)screenInfo.screens[i]->width + RANDOM_WIDTH,
3452               (unsigned short)screenInfo.screens[i]->height + RANDOM_WIDTH,
3453               0, InputOutput, mask, attributes, 0, serverClient,
3454               wVisual (WindowTable[i]), &result);
3455
3456     if (cursor)
3457         FreeResource (cursorID, RT_NONE);
3458
3459     if (!pWin)
3460         return FALSE;
3461
3462     if (!AddResource(pWin->drawable.id, RT_WINDOW,
3463                      (pointer)savedScreenInfo[i].pWindow))
3464         return FALSE;
3465
3466     if (mask & CWBackPixmap)
3467     {
3468         MakeRootTile (pWin);
3469         (*pWin->drawable.pScreen->ChangeWindowAttributes)(pWin, CWBackPixmap);
3470     }
3471     MapWindow(pWin, serverClient);
3472 #ifndef NOLOGOHACK
3473     if (kind == SCREEN_IS_TILED && logoScreenSaver)
3474         DrawLogo(pWin);
3475 #endif
3476     return TRUE;
3477 }
3478
3479 /*
3480  * FindWindowWithOptional
3481  *
3482  * search ancestors of the given window for an entry containing
3483  * a WindowOpt structure.  Assumptions:  some parent will
3484  * contain the structure.
3485  */
3486
3487 WindowPtr
3488 FindWindowWithOptional (w)
3489     register WindowPtr w;
3490 {
3491     do
3492         w = w->parent;
3493     while (!w->optional);
3494     return w;
3495 }
3496
3497 /*
3498  * CheckWindowOptionalNeed
3499  *
3500  * check each optional entry in the given window to see if
3501  * the value is satisfied by the default rules.  If so,
3502  * release the optional record
3503  */
3504
3505 void
3506 CheckWindowOptionalNeed (w)
3507     register WindowPtr w;
3508 {
3509     register WindowOptPtr optional;
3510     register WindowOptPtr parentOptional;
3511
3512     if (!w->parent)
3513         return;
3514     optional = w->optional;
3515     if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate])
3516         return;
3517     if (optional->otherEventMasks != 0)
3518         return;
3519     if (optional->otherClients != NULL)
3520         return;
3521     if (optional->passiveGrabs != NULL)
3522         return;
3523     if (optional->userProps != NULL)
3524         return;
3525     if (optional->backingBitPlanes != ~0L)
3526         return;
3527     if (optional->backingPixel != 0)
3528         return;
3529 #ifdef SHAPE
3530     if (optional->boundingShape != NULL)
3531         return;
3532     if (optional->clipShape != NULL)
3533         return;
3534 #endif
3535 #ifdef XINPUT
3536     if (optional->inputMasks != NULL)
3537         return;
3538 #endif
3539     parentOptional = FindWindowWithOptional(w)->optional;
3540     if (optional->visual != parentOptional->visual)
3541         return;
3542     if (optional->cursor != None &&
3543         (optional->cursor != parentOptional->cursor ||
3544          w->parent->cursorIsNone))
3545         return;
3546     if (optional->colormap != parentOptional->colormap)
3547         return;
3548     DisposeWindowOptional (w);
3549 }
3550
3551 /*
3552  * MakeWindowOptional
3553  *
3554  * create an optional record and initialize it with the default
3555  * values.
3556  */
3557
3558 Bool
3559 MakeWindowOptional (pWin)
3560     register WindowPtr pWin;
3561 {
3562     register WindowOptPtr optional;
3563     register WindowOptPtr parentOptional;
3564
3565     if (pWin->optional)
3566         return TRUE;
3567     optional = (WindowOptPtr) xalloc (sizeof (WindowOptRec));
3568     if (!optional)
3569         return FALSE;
3570     optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate];
3571     optional->otherEventMasks = 0;
3572     optional->otherClients = NULL;
3573     optional->passiveGrabs = NULL;
3574     optional->userProps = NULL;
3575     optional->backingBitPlanes = ~0L;
3576     optional->backingPixel = 0;
3577 #ifdef SHAPE
3578     optional->boundingShape = NULL;
3579     optional->clipShape = NULL;
3580 #endif
3581 #ifdef XINPUT
3582     optional->inputMasks = NULL;
3583 #endif
3584     parentOptional = FindWindowWithOptional(pWin)->optional;
3585     optional->visual = parentOptional->visual;
3586     if (!pWin->cursorIsNone)
3587     {
3588         optional->cursor = parentOptional->cursor;
3589         optional->cursor->refcnt++;
3590     }
3591     else
3592     {
3593         optional->cursor = None;
3594     }
3595     optional->colormap = parentOptional->colormap;
3596     pWin->optional = optional;
3597     return TRUE;
3598 }
3599
3600 void
3601 DisposeWindowOptional (pWin)
3602     register WindowPtr pWin;
3603 {
3604     if (!pWin->optional)
3605         return;
3606     /*
3607      * everything is peachy.  Delete the optional record
3608      * and clean up
3609      */
3610     if (pWin->optional->cursor)
3611     {
3612         FreeCursor (pWin->optional->cursor, (Cursor)0);
3613         pWin->cursorIsNone = FALSE;
3614     }
3615     else
3616         pWin->cursorIsNone = TRUE;
3617     xfree (pWin->optional);
3618     pWin->optional = NULL;
3619 }
3620
3621 #ifndef NOLOGOHACK
3622 static void
3623 #if NeedFunctionPrototypes
3624 DrawLogo(WindowPtr pWin)
3625 #else
3626 DrawLogo(pWin)
3627     WindowPtr pWin;
3628 #endif
3629 {
3630     DrawablePtr pDraw;
3631     ScreenPtr pScreen;
3632     int x, y;
3633     unsigned int width, height, size;
3634     GC *pGC;
3635     int thin, gap, d31;
3636     DDXPointRec poly[4];
3637     ChangeGCVal fore[2], back[2];
3638     xrgb rgb[2];
3639     BITS32 fmask, bmask;
3640     ColormapPtr cmap;
3641
3642     pDraw = (DrawablePtr)pWin;
3643     pScreen = pDraw->pScreen;
3644     x = -pWin->origin.x;
3645     y = -pWin->origin.y;
3646     width = pScreen->width;
3647     height = pScreen->height;
3648     pGC = GetScratchGC(pScreen->rootDepth, pScreen);
3649     if (!pGC)
3650         return;
3651
3652     if ((rand() % 100) <= 17) /* make the probability for white fairly low */
3653         fore[0].val = pScreen->whitePixel;
3654     else
3655         fore[0].val = pScreen->blackPixel;
3656     if ((pWin->backgroundState == BackgroundPixel) &&
3657         (cmap = (ColormapPtr)LookupIDByType(wColormap (pWin), RT_COLORMAP))) {
3658         Pixel querypixels[2];
3659
3660         querypixels[0] = fore[0].val;
3661         querypixels[1] = pWin->background.pixel;
3662         QueryColors(cmap, 2, querypixels, rgb);
3663         if ((rgb[0].red == rgb[1].red) &&
3664             (rgb[0].green == rgb[1].green) &&
3665             (rgb[0].blue == rgb[1].blue)) {
3666             if (fore[0].val == pScreen->blackPixel)
3667                 fore[0].val = pScreen->whitePixel;
3668             else
3669                 fore[0].val = pScreen->blackPixel;
3670         }
3671     }
3672     fore[1].val = FillSolid;
3673     fmask = GCForeground|GCFillStyle;
3674     if (pWin->backgroundState == BackgroundPixel) {
3675         back[0].val = pWin->background.pixel;
3676         back[1].val = FillSolid;
3677         bmask = GCForeground|GCFillStyle;
3678     } else {
3679         back[0].val = 0;
3680         back[1].val = 0;
3681         dixChangeGC(NullClient, pGC, GCTileStipXOrigin|GCTileStipYOrigin,
3682                     NULL, back);
3683         back[0].val = FillTiled;
3684         back[1].ptr = pWin->background.pixmap;
3685         bmask = GCFillStyle|GCTile;
3686     }
3687
3688     /* should be the same as the reference function XmuDrawLogo() */
3689
3690     size = width;
3691     if (height < width)
3692          size = height;
3693     size = RANDOM_WIDTH + rand() % (size - RANDOM_WIDTH);
3694     size &= ~1;
3695     x += rand() % (width - size);
3696     y += rand() % (height - size);
3697
3698 /*
3699  * Draw what will be the thin strokes.
3700  *
3701  *           -----
3702  *          /    /
3703  *         /    /
3704  *        /    /
3705  *       /    /
3706  *      /____/
3707  *           d
3708  *
3709  * Point d is 9/44 (~1/5) of the way across.
3710  */
3711
3712     thin = (size / 11);
3713     if (thin < 1) thin = 1;
3714     gap = (thin+3) / 4;
3715     d31 = thin + thin + gap;
3716     poly[0].x = x + size;              poly[0].y = y;
3717     poly[1].x = x + size-d31;          poly[1].y = y;
3718     poly[2].x = x + 0;                 poly[2].y = y + size;
3719     poly[3].x = x + d31;               poly[3].y = y + size;
3720     dixChangeGC(NullClient, pGC, fmask, NULL, fore);
3721     ValidateGC(pDraw, pGC);
3722     (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly);
3723
3724 /*
3725  * Erase area not needed for lower thin stroke.
3726  *
3727  *           ------
3728  *          /     /
3729  *         /  __ /
3730  *        /  /  /
3731  *       /  /  /
3732  *      /__/__/
3733  */
3734
3735     poly[0].x = x + d31/2;                       poly[0].y = y + size;
3736     poly[1].x = x + size / 2;                    poly[1].y = y + size/2;
3737     poly[2].x = x + (size/2)+(d31-(d31/2));      poly[2].y = y + size/2;
3738     poly[3].x = x + d31;                         poly[3].y = y + size;
3739     dixChangeGC(NullClient, pGC, bmask, NULL, back);
3740     ValidateGC(pDraw, pGC);
3741     (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly);
3742
3743 /*
3744  * Erase area not needed for upper thin stroke.
3745  *
3746  *           ------
3747  *          /  /  /
3748  *         /--/  /
3749  *        /     /
3750  *       /     /
3751  *      /_____/
3752  */
3753
3754     poly[0].x = x + size - d31/2;                poly[0].y = y;
3755     poly[1].x = x + size / 2;                    poly[1].y = y + size/2;
3756     poly[2].x = x + (size/2)-(d31-(d31/2));      poly[2].y = y + size/2;
3757     poly[3].x = x + size - d31;                  poly[3].y = y;
3758     ValidateGC(pDraw, pGC);
3759     (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly);
3760
3761 /*
3762  * Draw thick stroke.
3763  * Point b is 1/4 of the way across.
3764  *
3765  *      b
3766  * -----
3767  * \    \
3768  *  \    \
3769  *   \    \
3770  *    \    \
3771  *     \____\
3772  */
3773
3774     poly[0].x = x;                     poly[0].y = y;
3775     poly[1].x = x + size/4;            poly[1].y = y;
3776     poly[2].x = x + size;              poly[2].y = y + size;
3777     poly[3].x = x + size - size/4;     poly[3].y = y + size;
3778     dixChangeGC(NullClient, pGC, fmask, NULL, fore);
3779     ValidateGC(pDraw, pGC);
3780     (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly);
3781
3782 /*
3783  * Erase to create gap.
3784  *
3785  *          /
3786  *         /
3787  *        /
3788  *       /
3789  *      /
3790  */
3791
3792     poly[0].x = x + size- thin;       poly[0].y = y;
3793     poly[1].x = x + size-( thin+gap);  poly[1].y = y;
3794     poly[2].x = x + thin;             poly[2].y = y + size;
3795     poly[3].x = x + thin + gap;       poly[3].y = y + size;
3796     dixChangeGC(NullClient, pGC, bmask, NULL, back);
3797     ValidateGC(pDraw, pGC);
3798     (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly);
3799
3800     FreeScratchGC(pGC);
3801 }
3802
3803 #endif