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