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