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