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