1706f2543Smrg/*
2706f2543Smrg
3706f2543SmrgCopyright (c) 2006, Red Hat, Inc.
4706f2543Smrg
5706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a
6706f2543Smrgcopy of this software and associated documentation files (the "Software"),
7706f2543Smrgto deal in the Software without restriction, including without limitation
8706f2543Smrgthe rights to use, copy, modify, merge, publish, distribute, sublicense,
9706f2543Smrgand/or sell copies of the Software, and to permit persons to whom the
10706f2543SmrgSoftware is furnished to do so, subject to the following conditions:
11706f2543Smrg
12706f2543SmrgThe above copyright notice and this permission notice (including the next
13706f2543Smrgparagraph) shall be included in all copies or substantial portions of the
14706f2543SmrgSoftware.
15706f2543Smrg
16706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19706f2543SmrgTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20706f2543SmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21706f2543SmrgFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22706f2543SmrgDEALINGS IN THE SOFTWARE.
23706f2543Smrg
24706f2543SmrgCopyright 1987, 1998  The Open Group
25706f2543Smrg
26706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its
27706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that
28706f2543Smrgthe above copyright notice appear in all copies and that both that
29706f2543Smrgcopyright notice and this permission notice appear in supporting
30706f2543Smrgdocumentation.
31706f2543Smrg
32706f2543SmrgThe above copyright notice and this permission notice shall be included
33706f2543Smrgin all copies or substantial portions of the Software.
34706f2543Smrg
35706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
36706f2543SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
37706f2543SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
38706f2543SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
39706f2543SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
40706f2543SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
41706f2543SmrgOTHER DEALINGS IN THE SOFTWARE.
42706f2543Smrg
43706f2543SmrgExcept as contained in this notice, the name of The Open Group shall
44706f2543Smrgnot be used in advertising or otherwise to promote the sale, use or
45706f2543Smrgother dealings in this Software without prior written authorization
46706f2543Smrgfrom The Open Group.
47706f2543Smrg
48706f2543Smrg
49706f2543SmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
50706f2543Smrg
51706f2543Smrg			All Rights Reserved
52706f2543Smrg
53706f2543SmrgPermission to use, copy, modify, and distribute this software and its
54706f2543Smrgdocumentation for any purpose and without fee is hereby granted,
55706f2543Smrgprovided that the above copyright notice appear in all copies and that
56706f2543Smrgboth that copyright notice and this permission notice appear in
57706f2543Smrgsupporting documentation, and that the name of Digital not be
58706f2543Smrgused in advertising or publicity pertaining to distribution of the
59706f2543Smrgsoftware without specific, written prior permission.
60706f2543Smrg
61706f2543SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
62706f2543SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
63706f2543SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
64706f2543SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
65706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
66706f2543SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
67706f2543SmrgSOFTWARE.
68706f2543Smrg
69706f2543Smrg*/
70706f2543Smrg
71706f2543Smrg/* The panoramix components contained the following notice */
72706f2543Smrg/*****************************************************************
73706f2543Smrg
74706f2543SmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
75706f2543Smrg
76706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a copy
77706f2543Smrgof this software and associated documentation files (the "Software"), to deal
78706f2543Smrgin the Software without restriction, including without limitation the rights
79706f2543Smrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
80706f2543Smrgcopies of the Software.
81706f2543Smrg
82706f2543SmrgThe above copyright notice and this permission notice shall be included in
83706f2543Smrgall copies or substantial portions of the Software.
84706f2543Smrg
85706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
88706f2543SmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
89706f2543SmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
90706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
91706f2543SmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
92706f2543Smrg
93706f2543SmrgExcept as contained in this notice, the name of Digital Equipment Corporation
94706f2543Smrgshall not be used in advertising or otherwise to promote the sale, use or other
95706f2543Smrgdealings in this Software without prior written authorization from Digital
96706f2543SmrgEquipment Corporation.
97706f2543Smrg
98706f2543Smrg******************************************************************/
99706f2543Smrg
100706f2543Smrg
101706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
102706f2543Smrg#include <dix-config.h>
103706f2543Smrg#endif
104706f2543Smrg
105706f2543Smrg#include "misc.h"
106706f2543Smrg#include "scrnintstr.h"
107706f2543Smrg#include "os.h"
108706f2543Smrg#include "regionstr.h"
109706f2543Smrg#include "validate.h"
110706f2543Smrg#include "windowstr.h"
111706f2543Smrg#include "input.h"
112706f2543Smrg#include "inputstr.h"
113706f2543Smrg#include "resource.h"
114706f2543Smrg#include "colormapst.h"
115706f2543Smrg#include "cursorstr.h"
116706f2543Smrg#include "dixstruct.h"
117706f2543Smrg#include "gcstruct.h"
118706f2543Smrg#include "servermd.h"
119706f2543Smrg#ifdef PANORAMIX
120706f2543Smrg#include "panoramiX.h"
121706f2543Smrg#include "panoramiXsrv.h"
122706f2543Smrg#endif
123706f2543Smrg#include "dixevents.h"
124706f2543Smrg#include "globals.h"
125706f2543Smrg#include "mi.h" /* miPaintWindow */
126706f2543Smrg
127706f2543Smrg#include "privates.h"
128706f2543Smrg#include "xace.h"
129706f2543Smrg
130706f2543Smrg/******
131706f2543Smrg * Window stuff for server
132706f2543Smrg *
133706f2543Smrg *    CreateRootWindow, CreateWindow, ChangeWindowAttributes,
134706f2543Smrg *    GetWindowAttributes, DeleteWindow, DestroySubWindows,
135706f2543Smrg *    HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows,
136706f2543Smrg *    UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow,
137706f2543Smrg *    ChangeWindowDeviceCursor
138706f2543Smrg ******/
139706f2543Smrg
140706f2543SmrgBool bgNoneRoot = FALSE;
141706f2543Smrg
142706f2543Smrgstatic unsigned char _back_lsb[4] = {0x88, 0x22, 0x44, 0x11};
143706f2543Smrgstatic unsigned char _back_msb[4] = {0x11, 0x44, 0x22, 0x88};
144706f2543Smrg
145706f2543Smrgstatic Bool WindowParentHasDeviceCursor(WindowPtr pWin,
146706f2543Smrg                                        DeviceIntPtr pDev,
147706f2543Smrg                                        CursorPtr pCurs);
148706f2543Smrgstatic Bool
149706f2543SmrgWindowSeekDeviceCursor(WindowPtr pWin,
150706f2543Smrg                       DeviceIntPtr pDev,
151706f2543Smrg                       DevCursNodePtr* pNode,
152706f2543Smrg                       DevCursNodePtr* pPrev);
153706f2543Smrg
154706f2543Smrgint screenIsSaved = SCREEN_SAVER_OFF;
155706f2543Smrg
156706f2543Smrgstatic Bool TileScreenSaver(ScreenPtr pScreen, int kind);
157706f2543Smrg
158706f2543Smrg#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \
159706f2543Smrg			      CWDontPropagate | CWOverrideRedirect | CWCursor )
160706f2543Smrg
161706f2543Smrg#define BOXES_OVERLAP(b1, b2) \
162706f2543Smrg      (!( ((b1)->x2 <= (b2)->x1)  || \
163706f2543Smrg	( ((b1)->x1 >= (b2)->x2)) || \
164706f2543Smrg	( ((b1)->y2 <= (b2)->y1)) || \
165706f2543Smrg	( ((b1)->y1 >= (b2)->y2)) ) )
166706f2543Smrg
167706f2543Smrg#define RedirectSend(pWin) \
168706f2543Smrg    ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask)
169706f2543Smrg
170706f2543Smrg#define SubSend(pWin) \
171706f2543Smrg    ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask)
172706f2543Smrg
173706f2543Smrg#define StrSend(pWin) \
174706f2543Smrg    ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask)
175706f2543Smrg
176706f2543Smrg#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent))
177706f2543Smrg
178706f2543Smrg#ifdef DEBUG
179706f2543Smrg/******
180706f2543Smrg * PrintWindowTree
181706f2543Smrg *    For debugging only
182706f2543Smrg ******/
183706f2543Smrg
184706f2543Smrgstatic void
185706f2543SmrgPrintChildren(WindowPtr p1, int indent)
186706f2543Smrg{
187706f2543Smrg    WindowPtr p2;
188706f2543Smrg    int i;
189706f2543Smrg
190706f2543Smrg    while (p1)
191706f2543Smrg    {
192706f2543Smrg	p2 = p1->firstChild;
193706f2543Smrg        ErrorF("[dix] ");
194706f2543Smrg	for (i=0; i<indent; i++) ErrorF(" ");
195706f2543Smrg	ErrorF("%lx\n", p1->drawable.id);
196706f2543Smrg	RegionPrint(&p1->clipList);
197706f2543Smrg	PrintChildren(p2, indent+4);
198706f2543Smrg	p1 = p1->nextSib;
199706f2543Smrg    }
200706f2543Smrg}
201706f2543Smrg
202706f2543Smrgstatic void
203706f2543SmrgPrintWindowTree(void)
204706f2543Smrg{
205706f2543Smrg    int i;
206706f2543Smrg    WindowPtr pWin, p1;
207706f2543Smrg
208706f2543Smrg    for (i=0; i<screenInfo.numScreens; i++)
209706f2543Smrg    {
210706f2543Smrg	ErrorF("[dix] WINDOW %d\n", i);
211706f2543Smrg	pWin = screenInfo.screens[i]->root;
212706f2543Smrg	RegionPrint(&pWin->clipList);
213706f2543Smrg	p1 = pWin->firstChild;
214706f2543Smrg	PrintChildren(p1, 4);
215706f2543Smrg    }
216706f2543Smrg}
217706f2543Smrg#endif
218706f2543Smrg
219706f2543Smrgint
220706f2543SmrgTraverseTree(WindowPtr pWin, VisitWindowProcPtr func, pointer data)
221706f2543Smrg{
222706f2543Smrg    int result;
223706f2543Smrg    WindowPtr pChild;
224706f2543Smrg
225706f2543Smrg    if (!(pChild = pWin))
226706f2543Smrg       return WT_NOMATCH;
227706f2543Smrg    while (1)
228706f2543Smrg    {
229706f2543Smrg	result = (* func)(pChild, data);
230706f2543Smrg	if (result == WT_STOPWALKING)
231706f2543Smrg	    return WT_STOPWALKING;
232706f2543Smrg	if ((result == WT_WALKCHILDREN) && pChild->firstChild)
233706f2543Smrg	{
234706f2543Smrg	    pChild = pChild->firstChild;
235706f2543Smrg	    continue;
236706f2543Smrg	}
237706f2543Smrg	while (!pChild->nextSib && (pChild != pWin))
238706f2543Smrg	    pChild = pChild->parent;
239706f2543Smrg	if (pChild == pWin)
240706f2543Smrg	    break;
241706f2543Smrg	pChild = pChild->nextSib;
242706f2543Smrg    }
243706f2543Smrg    return WT_NOMATCH;
244706f2543Smrg}
245706f2543Smrg
246706f2543Smrg/*****
247706f2543Smrg * WalkTree
248706f2543Smrg *   Walk the window tree, for SCREEN, preforming FUNC(pWin, data) on
249706f2543Smrg *   each window.  If FUNC returns WT_WALKCHILDREN, traverse the children,
250706f2543Smrg *   if it returns WT_DONTWALKCHILDREN, dont.  If it returns WT_STOPWALKING
251706f2543Smrg *   exit WalkTree.  Does depth-first traverse.
252706f2543Smrg *****/
253706f2543Smrg
254706f2543Smrgint
255706f2543SmrgWalkTree(ScreenPtr pScreen, VisitWindowProcPtr func, pointer data)
256706f2543Smrg{
257706f2543Smrg    return(TraverseTree(pScreen->root, func, data));
258706f2543Smrg}
259706f2543Smrg
260706f2543Smrg/* hack for forcing backing store on all windows */
261706f2543Smrgint	defaultBackingStore = NotUseful;
262706f2543Smrg/* hack to force no backing store */
263706f2543SmrgBool	disableBackingStore = FALSE;
264706f2543SmrgBool	enableBackingStore = FALSE;
265706f2543Smrg
266706f2543Smrgstatic void
267706f2543SmrgSetWindowToDefaults(WindowPtr pWin)
268706f2543Smrg{
269706f2543Smrg    pWin->prevSib = NullWindow;
270706f2543Smrg    pWin->firstChild = NullWindow;
271706f2543Smrg    pWin->lastChild = NullWindow;
272706f2543Smrg
273706f2543Smrg    pWin->valdata = (ValidatePtr)NULL;
274706f2543Smrg    pWin->optional = (WindowOptPtr)NULL;
275706f2543Smrg    pWin->cursorIsNone = TRUE;
276706f2543Smrg
277706f2543Smrg    pWin->backingStore = NotUseful;
278706f2543Smrg    pWin->DIXsaveUnder = FALSE;
279706f2543Smrg    pWin->backStorage = (pointer) NULL;
280706f2543Smrg
281706f2543Smrg    pWin->mapped = FALSE;	    /* off */
282706f2543Smrg    pWin->realized = FALSE;	/* off */
283706f2543Smrg    pWin->viewable = FALSE;
284706f2543Smrg    pWin->visibility = VisibilityNotViewable;
285706f2543Smrg    pWin->overrideRedirect = FALSE;
286706f2543Smrg    pWin->saveUnder = FALSE;
287706f2543Smrg
288706f2543Smrg    pWin->bitGravity = ForgetGravity;
289706f2543Smrg    pWin->winGravity = NorthWestGravity;
290706f2543Smrg
291706f2543Smrg    pWin->eventMask = 0;
292706f2543Smrg    pWin->deliverableEvents = 0;
293706f2543Smrg    pWin->dontPropagate = 0;
294706f2543Smrg    pWin->forcedBS = FALSE;
295706f2543Smrg    pWin->redirectDraw = RedirectDrawNone;
296706f2543Smrg    pWin->forcedBG = FALSE;
297706f2543Smrg
298706f2543Smrg#ifdef ROOTLESS
299706f2543Smrg    pWin->rootlessUnhittable = FALSE;
300706f2543Smrg#endif
301706f2543Smrg
302706f2543Smrg#ifdef COMPOSITE
303706f2543Smrg    pWin->damagedDescendants = FALSE;
304706f2543Smrg#endif
305706f2543Smrg}
306706f2543Smrg
307706f2543Smrgstatic void
308706f2543SmrgMakeRootTile(WindowPtr pWin)
309706f2543Smrg{
310706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
311706f2543Smrg    GCPtr pGC;
312706f2543Smrg    unsigned char back[128];
313706f2543Smrg    int len = BitmapBytePad(sizeof(long));
314706f2543Smrg    unsigned char *from, *to;
315706f2543Smrg    int i, j;
316706f2543Smrg
317706f2543Smrg    pWin->background.pixmap = (*pScreen->CreatePixmap)(pScreen, 4, 4,
318706f2543Smrg						    pScreen->rootDepth, 0);
319706f2543Smrg
320706f2543Smrg    pWin->backgroundState = BackgroundPixmap;
321706f2543Smrg    pGC = GetScratchGC(pScreen->rootDepth, pScreen);
322706f2543Smrg    if (!pWin->background.pixmap || !pGC)
323706f2543Smrg	FatalError("could not create root tile");
324706f2543Smrg
325706f2543Smrg    {
326706f2543Smrg	ChangeGCVal attributes[2];
327706f2543Smrg
328706f2543Smrg	attributes[0].val = pScreen->whitePixel;
329706f2543Smrg	attributes[1].val = pScreen->blackPixel;
330706f2543Smrg
331706f2543Smrg	(void)ChangeGC(NullClient, pGC, GCForeground | GCBackground, attributes);
332706f2543Smrg    }
333706f2543Smrg
334706f2543Smrg   ValidateGC((DrawablePtr)pWin->background.pixmap, pGC);
335706f2543Smrg
336706f2543Smrg   from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb;
337706f2543Smrg   to = back;
338706f2543Smrg
339706f2543Smrg   for (i = 4; i > 0; i--, from++)
340706f2543Smrg	for (j = len; j > 0; j--)
341706f2543Smrg	    *to++ = *from;
342706f2543Smrg
343706f2543Smrg   (*pGC->ops->PutImage)((DrawablePtr)pWin->background.pixmap, pGC, 1,
344706f2543Smrg		    0, 0, len, 4, 0, XYBitmap, (char *)back);
345706f2543Smrg
346706f2543Smrg   FreeScratchGC(pGC);
347706f2543Smrg
348706f2543Smrg}
349706f2543Smrg
350706f2543Smrg/*****
351706f2543Smrg * CreateRootWindow
352706f2543Smrg *    Makes a window at initialization time for specified screen
353706f2543Smrg *****/
354706f2543Smrg
355706f2543SmrgBool
356706f2543SmrgCreateRootWindow(ScreenPtr pScreen)
357706f2543Smrg{
358706f2543Smrg    WindowPtr	pWin;
359706f2543Smrg    BoxRec	box;
360706f2543Smrg    PixmapFormatRec *format;
361706f2543Smrg
362706f2543Smrg    pWin = dixAllocateObjectWithPrivates(WindowRec, PRIVATE_WINDOW);
363706f2543Smrg    if (!pWin)
364706f2543Smrg	return FALSE;
365706f2543Smrg
366706f2543Smrg    pScreen->screensaver.pWindow = NULL;
367706f2543Smrg    pScreen->screensaver.wid = FakeClientID(0);
368706f2543Smrg    pScreen->screensaver.ExternalScreenSaver = NULL;
369706f2543Smrg    screenIsSaved = SCREEN_SAVER_OFF;
370706f2543Smrg
371706f2543Smrg    pScreen->root = pWin;
372706f2543Smrg
373706f2543Smrg    pWin->drawable.pScreen = pScreen;
374706f2543Smrg    pWin->drawable.type = DRAWABLE_WINDOW;
375706f2543Smrg
376706f2543Smrg    pWin->drawable.depth = pScreen->rootDepth;
377706f2543Smrg    for (format = screenInfo.formats;
378706f2543Smrg	 format->depth != pScreen->rootDepth;
379706f2543Smrg	 format++)
380706f2543Smrg	;
381706f2543Smrg    pWin->drawable.bitsPerPixel = format->bitsPerPixel;
382706f2543Smrg
383706f2543Smrg    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
384706f2543Smrg
385706f2543Smrg    pWin->parent = NullWindow;
386706f2543Smrg    SetWindowToDefaults(pWin);
387706f2543Smrg
388706f2543Smrg    pWin->optional = malloc(sizeof (WindowOptRec));
389706f2543Smrg    if (!pWin->optional)
390706f2543Smrg        return FALSE;
391706f2543Smrg
392706f2543Smrg    pWin->optional->dontPropagateMask = 0;
393706f2543Smrg    pWin->optional->otherEventMasks = 0;
394706f2543Smrg    pWin->optional->otherClients = NULL;
395706f2543Smrg    pWin->optional->passiveGrabs = NULL;
396706f2543Smrg    pWin->optional->userProps = NULL;
397706f2543Smrg    pWin->optional->backingBitPlanes = ~0L;
398706f2543Smrg    pWin->optional->backingPixel = 0;
399706f2543Smrg    pWin->optional->boundingShape = NULL;
400706f2543Smrg    pWin->optional->clipShape = NULL;
401706f2543Smrg    pWin->optional->inputShape = NULL;
402706f2543Smrg    pWin->optional->inputMasks = NULL;
403706f2543Smrg    pWin->optional->deviceCursors = NULL;
404706f2543Smrg    pWin->optional->colormap = pScreen->defColormap;
405706f2543Smrg    pWin->optional->visual = pScreen->rootVisual;
406706f2543Smrg
407706f2543Smrg    pWin->nextSib = NullWindow;
408706f2543Smrg
409706f2543Smrg    pWin->drawable.id = FakeClientID(0);
410706f2543Smrg
411706f2543Smrg    pWin->origin.x = pWin->origin.y = 0;
412706f2543Smrg    pWin->drawable.height = pScreen->height;
413706f2543Smrg    pWin->drawable.width = pScreen->width;
414706f2543Smrg    pWin->drawable.x = pWin->drawable.y = 0;
415706f2543Smrg
416706f2543Smrg    box.x1 = 0;
417706f2543Smrg    box.y1 = 0;
418706f2543Smrg    box.x2 = pScreen->width;
419706f2543Smrg    box.y2 = pScreen->height;
420706f2543Smrg    RegionInit(&pWin->clipList, &box, 1);
421706f2543Smrg    RegionInit(&pWin->winSize, &box, 1);
422706f2543Smrg    RegionInit(&pWin->borderSize, &box, 1);
423706f2543Smrg    RegionInit(&pWin->borderClip, &box, 1);
424706f2543Smrg
425706f2543Smrg    pWin->drawable.class = InputOutput;
426706f2543Smrg    pWin->optional->visual = pScreen->rootVisual;
427706f2543Smrg
428706f2543Smrg    pWin->backgroundState = BackgroundPixel;
429706f2543Smrg    pWin->background.pixel = pScreen->whitePixel;
430706f2543Smrg
431706f2543Smrg    pWin->borderIsPixel = TRUE;
432706f2543Smrg    pWin->border.pixel = pScreen->blackPixel;
433706f2543Smrg    pWin->borderWidth = 0;
434706f2543Smrg
435706f2543Smrg    /*  security creation/labeling check
436706f2543Smrg     */
437706f2543Smrg    if (XaceHook(XACE_RESOURCE_ACCESS, serverClient, pWin->drawable.id,
438706f2543Smrg		 RT_WINDOW, pWin, RT_NONE, NULL, DixCreateAccess))
439706f2543Smrg	return FALSE;
440706f2543Smrg
441706f2543Smrg    if (!AddResource(pWin->drawable.id, RT_WINDOW, (pointer)pWin))
442706f2543Smrg	return FALSE;
443706f2543Smrg
444706f2543Smrg    if (disableBackingStore)
445706f2543Smrg	pScreen->backingStoreSupport = NotUseful;
446706f2543Smrg    if (enableBackingStore)
447706f2543Smrg	pScreen->backingStoreSupport = Always;
448706f2543Smrg
449706f2543Smrg    pScreen->saveUnderSupport = NotUseful;
450706f2543Smrg
451706f2543Smrg    return TRUE;
452706f2543Smrg}
453706f2543Smrg
454706f2543Smrgvoid
455706f2543SmrgInitRootWindow(WindowPtr pWin)
456706f2543Smrg{
457706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
458706f2543Smrg    int backFlag = CWBorderPixel | CWCursor | CWBackingStore;
459706f2543Smrg
460706f2543Smrg    if (!(*pScreen->CreateWindow)(pWin))
461706f2543Smrg	return; /* XXX */
462706f2543Smrg    (*pScreen->PositionWindow)(pWin, 0, 0);
463706f2543Smrg
464706f2543Smrg    pWin->cursorIsNone = FALSE;
465706f2543Smrg    pWin->optional->cursor = rootCursor;
466706f2543Smrg    rootCursor->refcnt++;
467706f2543Smrg
468706f2543Smrg
469706f2543Smrg    if (party_like_its_1989) {
470706f2543Smrg        MakeRootTile(pWin);
471706f2543Smrg        backFlag |= CWBackPixmap;
472706f2543Smrg    } else if (pScreen->canDoBGNoneRoot && bgNoneRoot) {
473706f2543Smrg        pWin->backgroundState = XaceBackgroundNoneState(pWin);
474706f2543Smrg        pWin->background.pixel = pScreen->whitePixel;
475706f2543Smrg        backFlag |= CWBackPixmap;
476706f2543Smrg    } else {
477706f2543Smrg        pWin->backgroundState = BackgroundPixel;
478706f2543Smrg	if (whiteRoot)
479706f2543Smrg            pWin->background.pixel = pScreen->whitePixel;
480706f2543Smrg        else
481706f2543Smrg            pWin->background.pixel = pScreen->blackPixel;
482706f2543Smrg        backFlag |= CWBackPixel;
483706f2543Smrg    }
484706f2543Smrg
485706f2543Smrg    pWin->backingStore = defaultBackingStore;
486706f2543Smrg    pWin->forcedBS = (defaultBackingStore != NotUseful);
487706f2543Smrg    /* We SHOULD check for an error value here XXX */
488706f2543Smrg    (*pScreen->ChangeWindowAttributes)(pWin, backFlag);
489706f2543Smrg
490706f2543Smrg    MapWindow(pWin, serverClient);
491706f2543Smrg}
492706f2543Smrg
493706f2543Smrg/* Set the region to the intersection of the rectangle and the
494706f2543Smrg * window's winSize.  The window is typically the parent of the
495706f2543Smrg * window from which the region came.
496706f2543Smrg */
497706f2543Smrg
498706f2543Smrgstatic void
499706f2543SmrgClippedRegionFromBox(WindowPtr pWin, RegionPtr Rgn,
500706f2543Smrg                     int x, int y,
501706f2543Smrg                     int w, int h)
502706f2543Smrg{
503706f2543Smrg    BoxRec box = *RegionExtents(&pWin->winSize);
504706f2543Smrg
505706f2543Smrg    /* we do these calculations to avoid overflows */
506706f2543Smrg    if (x > box.x1)
507706f2543Smrg	box.x1 = x;
508706f2543Smrg    if (y > box.y1)
509706f2543Smrg	box.y1 = y;
510706f2543Smrg    x += w;
511706f2543Smrg    if (x < box.x2)
512706f2543Smrg	box.x2 = x;
513706f2543Smrg    y += h;
514706f2543Smrg    if (y < box.y2)
515706f2543Smrg	box.y2 = y;
516706f2543Smrg    if (box.x1 > box.x2)
517706f2543Smrg	box.x2 = box.x1;
518706f2543Smrg    if (box.y1 > box.y2)
519706f2543Smrg	box.y2 = box.y1;
520706f2543Smrg    RegionReset(Rgn, &box);
521706f2543Smrg    RegionIntersect(Rgn, Rgn, &pWin->winSize);
522706f2543Smrg}
523706f2543Smrg
524706f2543Smrgstatic RealChildHeadProc realChildHeadProc = NULL;
525706f2543Smrg
526706f2543Smrgvoid
527706f2543SmrgRegisterRealChildHeadProc (RealChildHeadProc proc)
528706f2543Smrg{
529706f2543Smrg    realChildHeadProc = proc;
530706f2543Smrg}
531706f2543Smrg
532706f2543Smrg
533706f2543SmrgWindowPtr
534706f2543SmrgRealChildHead(WindowPtr pWin)
535706f2543Smrg{
536706f2543Smrg    if (realChildHeadProc) {
537706f2543Smrg	return realChildHeadProc (pWin);
538706f2543Smrg    }
539706f2543Smrg
540706f2543Smrg    if (!pWin->parent &&
541706f2543Smrg	(screenIsSaved == SCREEN_SAVER_ON) &&
542706f2543Smrg	(HasSaverWindow (pWin->drawable.pScreen)))
543706f2543Smrg	return pWin->firstChild;
544706f2543Smrg    else
545706f2543Smrg	return NullWindow;
546706f2543Smrg}
547706f2543Smrg
548706f2543Smrg/*****
549706f2543Smrg * CreateWindow
550706f2543Smrg *    Makes a window in response to client request
551706f2543Smrg *****/
552706f2543Smrg
553706f2543SmrgWindowPtr
554706f2543SmrgCreateWindow(Window wid, WindowPtr pParent, int x, int y, unsigned w,
555706f2543Smrg             unsigned h, unsigned bw, unsigned class, Mask vmask, XID *vlist,
556706f2543Smrg             int depth, ClientPtr client, VisualID visual, int *error)
557706f2543Smrg{
558706f2543Smrg    WindowPtr pWin;
559706f2543Smrg    WindowPtr pHead;
560706f2543Smrg    ScreenPtr pScreen;
561706f2543Smrg    xEvent event;
562706f2543Smrg    int idepth, ivisual;
563706f2543Smrg    Bool fOK;
564706f2543Smrg    DepthPtr pDepth;
565706f2543Smrg    PixmapFormatRec *format;
566706f2543Smrg    WindowOptPtr ancwopt;
567706f2543Smrg
568706f2543Smrg    if (class == CopyFromParent)
569706f2543Smrg	class = pParent->drawable.class;
570706f2543Smrg
571706f2543Smrg    if ((class != InputOutput) && (class != InputOnly))
572706f2543Smrg    {
573706f2543Smrg	*error = BadValue;
574706f2543Smrg	client->errorValue = class;
575706f2543Smrg	return NullWindow;
576706f2543Smrg    }
577706f2543Smrg
578706f2543Smrg    if ((class != InputOnly) && (pParent->drawable.class == InputOnly))
579706f2543Smrg    {
580706f2543Smrg	*error = BadMatch;
581706f2543Smrg	return NullWindow;
582706f2543Smrg    }
583706f2543Smrg
584706f2543Smrg    if ((class == InputOnly) && ((bw != 0) || (depth != 0)))
585706f2543Smrg    {
586706f2543Smrg	*error = BadMatch;
587706f2543Smrg	return NullWindow;
588706f2543Smrg    }
589706f2543Smrg
590706f2543Smrg    pScreen = pParent->drawable.pScreen;
591706f2543Smrg    if ((class == InputOutput) && (depth == 0))
592706f2543Smrg	 depth = pParent->drawable.depth;
593706f2543Smrg    ancwopt = pParent->optional;
594706f2543Smrg    if (!ancwopt)
595706f2543Smrg	ancwopt = FindWindowWithOptional(pParent)->optional;
596706f2543Smrg    if (visual == CopyFromParent) {
597706f2543Smrg	visual = ancwopt->visual;
598706f2543Smrg    }
599706f2543Smrg
600706f2543Smrg    /* Find out if the depth and visual are acceptable for this Screen */
601706f2543Smrg    if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth))
602706f2543Smrg    {
603706f2543Smrg	fOK = FALSE;
604706f2543Smrg	for(idepth = 0; idepth < pScreen->numDepths; idepth++)
605706f2543Smrg	{
606706f2543Smrg	    pDepth = (DepthPtr) &pScreen->allowedDepths[idepth];
607706f2543Smrg	    if ((depth == pDepth->depth) || (depth == 0))
608706f2543Smrg	    {
609706f2543Smrg		for (ivisual = 0; ivisual < pDepth->numVids; ivisual++)
610706f2543Smrg		{
611706f2543Smrg		    if (visual == pDepth->vids[ivisual])
612706f2543Smrg		    {
613706f2543Smrg			fOK = TRUE;
614706f2543Smrg			break;
615706f2543Smrg		    }
616706f2543Smrg		}
617706f2543Smrg	    }
618706f2543Smrg	}
619706f2543Smrg	if (fOK == FALSE)
620706f2543Smrg	{
621706f2543Smrg	    *error = BadMatch;
622706f2543Smrg	    return NullWindow;
623706f2543Smrg	}
624706f2543Smrg    }
625706f2543Smrg
626706f2543Smrg    if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) &&
627706f2543Smrg	(class != InputOnly) &&
628706f2543Smrg	(depth != pParent->drawable.depth))
629706f2543Smrg    {
630706f2543Smrg	*error = BadMatch;
631706f2543Smrg	return NullWindow;
632706f2543Smrg    }
633706f2543Smrg
634706f2543Smrg    if (((vmask & CWColormap) == 0) &&
635706f2543Smrg	(class != InputOnly) &&
636706f2543Smrg	((visual != ancwopt->visual) || (ancwopt->colormap == None)))
637706f2543Smrg    {
638706f2543Smrg	*error = BadMatch;
639706f2543Smrg	return NullWindow;
640706f2543Smrg    }
641706f2543Smrg
642706f2543Smrg    pWin = dixAllocateObjectWithPrivates(WindowRec, PRIVATE_WINDOW);
643706f2543Smrg    if (!pWin)
644706f2543Smrg    {
645706f2543Smrg	*error = BadAlloc;
646706f2543Smrg	return NullWindow;
647706f2543Smrg    }
648706f2543Smrg    pWin->drawable = pParent->drawable;
649706f2543Smrg    pWin->drawable.depth = depth;
650706f2543Smrg    if (depth == pParent->drawable.depth)
651706f2543Smrg	pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel;
652706f2543Smrg    else
653706f2543Smrg    {
654706f2543Smrg	for (format = screenInfo.formats; format->depth != depth; format++)
655706f2543Smrg	    ;
656706f2543Smrg	pWin->drawable.bitsPerPixel = format->bitsPerPixel;
657706f2543Smrg    }
658706f2543Smrg    if (class == InputOnly)
659706f2543Smrg	pWin->drawable.type = (short) UNDRAWABLE_WINDOW;
660706f2543Smrg    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
661706f2543Smrg
662706f2543Smrg    pWin->drawable.id = wid;
663706f2543Smrg    pWin->drawable.class = class;
664706f2543Smrg
665706f2543Smrg    pWin->parent = pParent;
666706f2543Smrg    SetWindowToDefaults(pWin);
667706f2543Smrg
668706f2543Smrg    if (visual != ancwopt->visual)
669706f2543Smrg    {
670706f2543Smrg	if (!MakeWindowOptional (pWin))
671706f2543Smrg	{
672706f2543Smrg	    dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
673706f2543Smrg	    *error = BadAlloc;
674706f2543Smrg	    return NullWindow;
675706f2543Smrg	}
676706f2543Smrg	pWin->optional->visual = visual;
677706f2543Smrg	pWin->optional->colormap = None;
678706f2543Smrg    }
679706f2543Smrg
680706f2543Smrg    pWin->borderWidth = bw;
681706f2543Smrg
682706f2543Smrg    /*  security creation/labeling check
683706f2543Smrg     */
684706f2543Smrg    *error = XaceHook(XACE_RESOURCE_ACCESS, client, wid, RT_WINDOW, pWin,
685706f2543Smrg		RT_WINDOW, pWin->parent, DixCreateAccess|DixSetAttrAccess);
686706f2543Smrg    if (*error != Success) {
687706f2543Smrg	dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
688706f2543Smrg	return NullWindow;
689706f2543Smrg    }
690706f2543Smrg
691706f2543Smrg    pWin->backgroundState = XaceBackgroundNoneState(pWin);
692706f2543Smrg    pWin->background.pixel = pScreen->whitePixel;
693706f2543Smrg
694706f2543Smrg    pWin->borderIsPixel = pParent->borderIsPixel;
695706f2543Smrg    pWin->border = pParent->border;
696706f2543Smrg    if (pWin->borderIsPixel == FALSE)
697706f2543Smrg	pWin->border.pixmap->refcnt++;
698706f2543Smrg
699706f2543Smrg    pWin->origin.x = x + (int)bw;
700706f2543Smrg    pWin->origin.y = y + (int)bw;
701706f2543Smrg    pWin->drawable.width = w;
702706f2543Smrg    pWin->drawable.height = h;
703706f2543Smrg    pWin->drawable.x = pParent->drawable.x + x + (int)bw;
704706f2543Smrg    pWin->drawable.y = pParent->drawable.y + y + (int)bw;
705706f2543Smrg
706706f2543Smrg	/* set up clip list correctly for unobscured WindowPtr */
707706f2543Smrg    RegionNull(&pWin->clipList);
708706f2543Smrg    RegionNull(&pWin->borderClip);
709706f2543Smrg    RegionNull(&pWin->winSize);
710706f2543Smrg    RegionNull(&pWin->borderSize);
711706f2543Smrg
712706f2543Smrg    pHead = RealChildHead(pParent);
713706f2543Smrg    if (pHead)
714706f2543Smrg    {
715706f2543Smrg	pWin->nextSib = pHead->nextSib;
716706f2543Smrg	if (pHead->nextSib)
717706f2543Smrg	    pHead->nextSib->prevSib = pWin;
718706f2543Smrg	else
719706f2543Smrg	    pParent->lastChild = pWin;
720706f2543Smrg	pHead->nextSib = pWin;
721706f2543Smrg	pWin->prevSib = pHead;
722706f2543Smrg    }
723706f2543Smrg    else
724706f2543Smrg    {
725706f2543Smrg	pWin->nextSib = pParent->firstChild;
726706f2543Smrg	if (pParent->firstChild)
727706f2543Smrg	    pParent->firstChild->prevSib = pWin;
728706f2543Smrg	else
729706f2543Smrg	    pParent->lastChild = pWin;
730706f2543Smrg	pParent->firstChild = pWin;
731706f2543Smrg    }
732706f2543Smrg
733706f2543Smrg    SetWinSize (pWin);
734706f2543Smrg    SetBorderSize (pWin);
735706f2543Smrg
736706f2543Smrg    /* We SHOULD check for an error value here XXX */
737706f2543Smrg    if (!(*pScreen->CreateWindow)(pWin))
738706f2543Smrg    {
739706f2543Smrg	*error = BadAlloc;
740706f2543Smrg	DeleteWindow(pWin, None);
741706f2543Smrg	return NullWindow;
742706f2543Smrg    }
743706f2543Smrg    /* We SHOULD check for an error value here XXX */
744706f2543Smrg    (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y);
745706f2543Smrg
746706f2543Smrg    if (!(vmask & CWEventMask))
747706f2543Smrg	RecalculateDeliverableEvents(pWin);
748706f2543Smrg
749706f2543Smrg    if (vmask)
750706f2543Smrg	*error = ChangeWindowAttributes(pWin, vmask, vlist, wClient (pWin));
751706f2543Smrg    else
752706f2543Smrg	*error = Success;
753706f2543Smrg
754706f2543Smrg    if (*error != Success)
755706f2543Smrg    {
756706f2543Smrg	DeleteWindow(pWin, None);
757706f2543Smrg	return NullWindow;
758706f2543Smrg    }
759706f2543Smrg    if (!(vmask & CWBackingStore) && (defaultBackingStore != NotUseful))
760706f2543Smrg    {
761706f2543Smrg	XID value = defaultBackingStore;
762706f2543Smrg	(void)ChangeWindowAttributes(pWin, CWBackingStore, &value, wClient (pWin));
763706f2543Smrg	pWin->forcedBS = TRUE;
764706f2543Smrg    }
765706f2543Smrg
766706f2543Smrg    if (SubSend(pParent))
767706f2543Smrg    {
768706f2543Smrg	memset(&event, 0, sizeof(xEvent));
769706f2543Smrg	event.u.u.type = CreateNotify;
770706f2543Smrg	event.u.createNotify.window = wid;
771706f2543Smrg	event.u.createNotify.parent = pParent->drawable.id;
772706f2543Smrg	event.u.createNotify.x = x;
773706f2543Smrg	event.u.createNotify.y = y;
774706f2543Smrg	event.u.createNotify.width = w;
775706f2543Smrg	event.u.createNotify.height = h;
776706f2543Smrg	event.u.createNotify.borderWidth = bw;
777706f2543Smrg	event.u.createNotify.override = pWin->overrideRedirect;
778706f2543Smrg	DeliverEvents(pParent, &event, 1, NullWindow);
779706f2543Smrg    }
780706f2543Smrg    return pWin;
781706f2543Smrg}
782706f2543Smrg
783706f2543Smrgstatic void
784706f2543SmrgDisposeWindowOptional (WindowPtr pWin)
785706f2543Smrg{
786706f2543Smrg    if (!pWin->optional)
787706f2543Smrg	return;
788706f2543Smrg    /*
789706f2543Smrg     * everything is peachy.  Delete the optional record
790706f2543Smrg     * and clean up
791706f2543Smrg     */
792706f2543Smrg    if (pWin->optional->cursor)
793706f2543Smrg    {
794706f2543Smrg	FreeCursor (pWin->optional->cursor, (Cursor)0);
795706f2543Smrg	pWin->cursorIsNone = FALSE;
796706f2543Smrg    }
797706f2543Smrg    else
798706f2543Smrg	pWin->cursorIsNone = TRUE;
799706f2543Smrg
800706f2543Smrg    if (pWin->optional->deviceCursors)
801706f2543Smrg    {
802706f2543Smrg        DevCursorList pList;
803706f2543Smrg        DevCursorList pPrev;
804706f2543Smrg        pList = pWin->optional->deviceCursors;
805706f2543Smrg        while(pList)
806706f2543Smrg        {
807706f2543Smrg            if (pList->cursor)
808706f2543Smrg                FreeCursor(pList->cursor, (XID)0);
809706f2543Smrg            pPrev = pList;
810706f2543Smrg            pList = pList->next;
811706f2543Smrg            free(pPrev);
812706f2543Smrg        }
813706f2543Smrg        pWin->optional->deviceCursors = NULL;
814706f2543Smrg    }
815706f2543Smrg
816706f2543Smrg    free(pWin->optional);
817706f2543Smrg    pWin->optional = NULL;
818706f2543Smrg}
819706f2543Smrg
820706f2543Smrgstatic void
821706f2543SmrgFreeWindowResources(WindowPtr pWin)
822706f2543Smrg{
823706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
824706f2543Smrg
825706f2543Smrg    DeleteWindowFromAnySaveSet(pWin);
826706f2543Smrg    DeleteWindowFromAnySelections(pWin);
827706f2543Smrg    DeleteWindowFromAnyEvents(pWin, TRUE);
828706f2543Smrg    RegionUninit(&pWin->clipList);
829706f2543Smrg    RegionUninit(&pWin->winSize);
830706f2543Smrg    RegionUninit(&pWin->borderClip);
831706f2543Smrg    RegionUninit(&pWin->borderSize);
832706f2543Smrg    if (wBoundingShape (pWin))
833706f2543Smrg	RegionDestroy(wBoundingShape (pWin));
834706f2543Smrg    if (wClipShape (pWin))
835706f2543Smrg	RegionDestroy(wClipShape (pWin));
836706f2543Smrg    if (wInputShape (pWin))
837706f2543Smrg	RegionDestroy(wInputShape (pWin));
838706f2543Smrg    if (pWin->borderIsPixel == FALSE)
839706f2543Smrg	(*pScreen->DestroyPixmap)(pWin->border.pixmap);
840706f2543Smrg    if (pWin->backgroundState == BackgroundPixmap)
841706f2543Smrg	(*pScreen->DestroyPixmap)(pWin->background.pixmap);
842706f2543Smrg
843706f2543Smrg    DeleteAllWindowProperties(pWin);
844706f2543Smrg    /* We SHOULD check for an error value here XXX */
845706f2543Smrg    (*pScreen->DestroyWindow)(pWin);
846706f2543Smrg    DisposeWindowOptional (pWin);
847706f2543Smrg}
848706f2543Smrg
849706f2543Smrgstatic void
850706f2543SmrgCrushTree(WindowPtr pWin)
851706f2543Smrg{
852706f2543Smrg    WindowPtr pChild, pSib, pParent;
853706f2543Smrg    UnrealizeWindowProcPtr UnrealizeWindow;
854706f2543Smrg    xEvent event;
855706f2543Smrg
856706f2543Smrg    if (!(pChild = pWin->firstChild))
857706f2543Smrg	return;
858706f2543Smrg    UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow;
859706f2543Smrg    while (1)
860706f2543Smrg    {
861706f2543Smrg	if (pChild->firstChild)
862706f2543Smrg	{
863706f2543Smrg	    pChild = pChild->firstChild;
864706f2543Smrg	    continue;
865706f2543Smrg	}
866706f2543Smrg	while (1)
867706f2543Smrg	{
868706f2543Smrg	    pParent = pChild->parent;
869706f2543Smrg	    if (SubStrSend(pChild, pParent))
870706f2543Smrg	    {
871706f2543Smrg		memset(&event, 0, sizeof(xEvent));
872706f2543Smrg		event.u.u.type = DestroyNotify;
873706f2543Smrg		event.u.destroyNotify.window = pChild->drawable.id;
874706f2543Smrg		DeliverEvents(pChild, &event, 1, NullWindow);
875706f2543Smrg	    }
876706f2543Smrg	    FreeResource(pChild->drawable.id, RT_WINDOW);
877706f2543Smrg	    pSib = pChild->nextSib;
878706f2543Smrg	    pChild->viewable = FALSE;
879706f2543Smrg	    if (pChild->realized)
880706f2543Smrg	    {
881706f2543Smrg		pChild->realized = FALSE;
882706f2543Smrg		(*UnrealizeWindow)(pChild);
883706f2543Smrg	    }
884706f2543Smrg	    FreeWindowResources(pChild);
885706f2543Smrg	    dixFreeObjectWithPrivates(pChild, PRIVATE_WINDOW);
886706f2543Smrg	    if ( (pChild = pSib) )
887706f2543Smrg		break;
888706f2543Smrg	    pChild = pParent;
889706f2543Smrg	    pChild->firstChild = NullWindow;
890706f2543Smrg	    pChild->lastChild = NullWindow;
891706f2543Smrg	    if (pChild == pWin)
892706f2543Smrg		return;
893706f2543Smrg	}
894706f2543Smrg    }
895706f2543Smrg}
896706f2543Smrg
897706f2543Smrg/*****
898706f2543Smrg *  DeleteWindow
899706f2543Smrg *	 Deletes child of window then window itself
900706f2543Smrg *	 If wid is None, don't send any events
901706f2543Smrg *****/
902706f2543Smrg
903706f2543Smrgint
904706f2543SmrgDeleteWindow(pointer value, XID wid)
905706f2543Smrg {
906706f2543Smrg    WindowPtr pParent;
907706f2543Smrg    WindowPtr pWin = (WindowPtr)value;
908706f2543Smrg    xEvent event;
909706f2543Smrg
910706f2543Smrg    UnmapWindow(pWin, FALSE);
911706f2543Smrg
912706f2543Smrg    CrushTree(pWin);
913706f2543Smrg
914706f2543Smrg    pParent = pWin->parent;
915706f2543Smrg    if (wid && pParent && SubStrSend(pWin, pParent))
916706f2543Smrg    {
917706f2543Smrg	memset(&event, 0, sizeof(xEvent));
918706f2543Smrg	event.u.u.type = DestroyNotify;
919706f2543Smrg	event.u.destroyNotify.window = pWin->drawable.id;
920706f2543Smrg	DeliverEvents(pWin, &event, 1, NullWindow);
921706f2543Smrg    }
922706f2543Smrg
923706f2543Smrg    FreeWindowResources(pWin);
924706f2543Smrg    if (pParent)
925706f2543Smrg    {
926706f2543Smrg	if (pParent->firstChild == pWin)
927706f2543Smrg	    pParent->firstChild = pWin->nextSib;
928706f2543Smrg	if (pParent->lastChild == pWin)
929706f2543Smrg	    pParent->lastChild = pWin->prevSib;
930706f2543Smrg	if (pWin->nextSib)
931706f2543Smrg	    pWin->nextSib->prevSib = pWin->prevSib;
932706f2543Smrg	if (pWin->prevSib)
933706f2543Smrg	    pWin->prevSib->nextSib = pWin->nextSib;
934706f2543Smrg    }
935706f2543Smrg    else
936706f2543Smrg	pWin->drawable.pScreen->root = NULL;
937706f2543Smrg    dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
938706f2543Smrg    return Success;
939706f2543Smrg}
940706f2543Smrg
941706f2543Smrgint
942706f2543SmrgDestroySubwindows(WindowPtr pWin, ClientPtr client)
943706f2543Smrg{
944706f2543Smrg    /* XXX
945706f2543Smrg     * The protocol is quite clear that each window should be
946706f2543Smrg     * destroyed in turn, however, unmapping all of the first
947706f2543Smrg     * eliminates most of the calls to ValidateTree.  So,
948706f2543Smrg     * this implementation is incorrect in that all of the
949706f2543Smrg     * UnmapNotifies occur before all of the DestroyNotifies.
950706f2543Smrg     * If you care, simply delete the call to UnmapSubwindows.
951706f2543Smrg     */
952706f2543Smrg    UnmapSubwindows(pWin);
953706f2543Smrg    while (pWin->lastChild) {
954706f2543Smrg	int rc = XaceHook(XACE_RESOURCE_ACCESS, client,
955706f2543Smrg			  pWin->lastChild->drawable.id, RT_WINDOW,
956706f2543Smrg			  pWin->lastChild, RT_NONE, NULL, DixDestroyAccess);
957706f2543Smrg	if (rc != Success)
958706f2543Smrg	    return rc;
959706f2543Smrg	FreeResource(pWin->lastChild->drawable.id, RT_NONE);
960706f2543Smrg    }
961706f2543Smrg    return Success;
962706f2543Smrg}
963706f2543Smrg
964706f2543Smrgstatic void
965706f2543SmrgSetRootWindowBackground(WindowPtr pWin, ScreenPtr pScreen, Mask *index2)
966706f2543Smrg{
967706f2543Smrg    /* following the protocol: "Changing the background of a root window to
968706f2543Smrg     * None or ParentRelative restores the default background pixmap" */
969706f2543Smrg    if (bgNoneRoot) {
970706f2543Smrg	pWin->backgroundState = XaceBackgroundNoneState(pWin);
971706f2543Smrg	pWin->background.pixel = pScreen->whitePixel;
972706f2543Smrg    }
973706f2543Smrg    else if (party_like_its_1989)
974706f2543Smrg	MakeRootTile(pWin);
975706f2543Smrg    else {
976706f2543Smrg        pWin->backgroundState = BackgroundPixel;
977706f2543Smrg	if (whiteRoot)
978706f2543Smrg	    pWin->background.pixel = pScreen->whitePixel;
979706f2543Smrg	else
980706f2543Smrg	    pWin->background.pixel = pScreen->blackPixel;
981706f2543Smrg	*index2 = CWBackPixel;
982706f2543Smrg    }
983706f2543Smrg}
984706f2543Smrg
985706f2543Smrg/*****
986706f2543Smrg *  ChangeWindowAttributes
987706f2543Smrg *
988706f2543Smrg *  The value-mask specifies which attributes are to be changed; the
989706f2543Smrg *  value-list contains one value for each one bit in the mask, from least
990706f2543Smrg *  to most significant bit in the mask.
991706f2543Smrg *****/
992706f2543Smrg
993706f2543Smrgint
994706f2543SmrgChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client)
995706f2543Smrg{
996706f2543Smrg    XID *pVlist;
997706f2543Smrg    PixmapPtr pPixmap;
998706f2543Smrg    Pixmap pixID;
999706f2543Smrg    CursorPtr pCursor, pOldCursor;
1000706f2543Smrg    Cursor cursorID;
1001706f2543Smrg    WindowPtr pChild;
1002706f2543Smrg    Colormap cmap;
1003706f2543Smrg    ColormapPtr	pCmap;
1004706f2543Smrg    xEvent xE;
1005706f2543Smrg    int error, rc;
1006706f2543Smrg    ScreenPtr pScreen;
1007706f2543Smrg    Mask index2, tmask, vmaskCopy = 0;
1008706f2543Smrg    unsigned int val;
1009706f2543Smrg    Bool checkOptional = FALSE, borderRelative = FALSE;
1010706f2543Smrg
1011706f2543Smrg    if ((pWin->drawable.class == InputOnly) && (vmask & (~INPUTONLY_LEGAL_MASK)))
1012706f2543Smrg	return BadMatch;
1013706f2543Smrg
1014706f2543Smrg    error = Success;
1015706f2543Smrg    pScreen = pWin->drawable.pScreen;
1016706f2543Smrg    pVlist = vlist;
1017706f2543Smrg    tmask = vmask;
1018706f2543Smrg    while (tmask)
1019706f2543Smrg    {
1020706f2543Smrg	index2 = (Mask) lowbit (tmask);
1021706f2543Smrg	tmask &= ~index2;
1022706f2543Smrg	switch (index2)
1023706f2543Smrg	{
1024706f2543Smrg	  case CWBackPixmap:
1025706f2543Smrg	    pixID = (Pixmap )*pVlist;
1026706f2543Smrg	    pVlist++;
1027706f2543Smrg	    if (pWin->backgroundState == ParentRelative)
1028706f2543Smrg		borderRelative = TRUE;
1029706f2543Smrg	    if (pixID == None)
1030706f2543Smrg	    {
1031706f2543Smrg		if (pWin->backgroundState == BackgroundPixmap)
1032706f2543Smrg		    (*pScreen->DestroyPixmap)(pWin->background.pixmap);
1033706f2543Smrg		if (!pWin->parent)
1034706f2543Smrg		    SetRootWindowBackground(pWin, pScreen, &index2);
1035706f2543Smrg		else {
1036706f2543Smrg		    pWin->backgroundState = XaceBackgroundNoneState(pWin);
1037706f2543Smrg		    pWin->background.pixel = pScreen->whitePixel;
1038706f2543Smrg		}
1039706f2543Smrg	    }
1040706f2543Smrg	    else if (pixID == ParentRelative)
1041706f2543Smrg	    {
1042706f2543Smrg		if (pWin->parent &&
1043706f2543Smrg		    pWin->drawable.depth != pWin->parent->drawable.depth)
1044706f2543Smrg		{
1045706f2543Smrg		    error = BadMatch;
1046706f2543Smrg		    goto PatchUp;
1047706f2543Smrg		}
1048706f2543Smrg		if (pWin->backgroundState == BackgroundPixmap)
1049706f2543Smrg		    (*pScreen->DestroyPixmap)(pWin->background.pixmap);
1050706f2543Smrg		if (!pWin->parent)
1051706f2543Smrg		    SetRootWindowBackground(pWin, pScreen, &index2);
1052706f2543Smrg		else
1053706f2543Smrg		    pWin->backgroundState = ParentRelative;
1054706f2543Smrg		borderRelative = TRUE;
1055706f2543Smrg		/* Note that the parent's backgroundTile's refcnt is NOT
1056706f2543Smrg		 * incremented. */
1057706f2543Smrg	    }
1058706f2543Smrg	    else
1059706f2543Smrg	    {
1060706f2543Smrg		rc = dixLookupResourceByType((pointer *)&pPixmap, pixID, RT_PIXMAP,
1061706f2543Smrg				       client, DixReadAccess);
1062706f2543Smrg		if (rc == Success)
1063706f2543Smrg		{
1064706f2543Smrg		    if	((pPixmap->drawable.depth != pWin->drawable.depth) ||
1065706f2543Smrg			 (pPixmap->drawable.pScreen != pScreen))
1066706f2543Smrg		    {
1067706f2543Smrg			error = BadMatch;
1068706f2543Smrg			goto PatchUp;
1069706f2543Smrg		    }
1070706f2543Smrg		    if (pWin->backgroundState == BackgroundPixmap)
1071706f2543Smrg			(*pScreen->DestroyPixmap)(pWin->background.pixmap);
1072706f2543Smrg		    pWin->backgroundState = BackgroundPixmap;
1073706f2543Smrg		    pWin->background.pixmap = pPixmap;
1074706f2543Smrg		    pPixmap->refcnt++;
1075706f2543Smrg		}
1076706f2543Smrg		else
1077706f2543Smrg		{
1078706f2543Smrg		    error = rc;
1079706f2543Smrg		    client->errorValue = pixID;
1080706f2543Smrg		    goto PatchUp;
1081706f2543Smrg		}
1082706f2543Smrg	    }
1083706f2543Smrg	    break;
1084706f2543Smrg	  case CWBackPixel:
1085706f2543Smrg	    if (pWin->backgroundState == ParentRelative)
1086706f2543Smrg		borderRelative = TRUE;
1087706f2543Smrg	    if (pWin->backgroundState == BackgroundPixmap)
1088706f2543Smrg		(*pScreen->DestroyPixmap)(pWin->background.pixmap);
1089706f2543Smrg	    pWin->backgroundState = BackgroundPixel;
1090706f2543Smrg	    pWin->background.pixel = (CARD32 ) *pVlist;
1091706f2543Smrg		   /* background pixel overrides background pixmap,
1092706f2543Smrg		      so don't let the ddx layer see both bits */
1093706f2543Smrg	    vmaskCopy &= ~CWBackPixmap;
1094706f2543Smrg	    pVlist++;
1095706f2543Smrg	    break;
1096706f2543Smrg	  case CWBorderPixmap:
1097706f2543Smrg	    pixID = (Pixmap ) *pVlist;
1098706f2543Smrg	    pVlist++;
1099706f2543Smrg	    if (pixID == CopyFromParent)
1100706f2543Smrg	    {
1101706f2543Smrg		if (!pWin->parent ||
1102706f2543Smrg		    (pWin->drawable.depth != pWin->parent->drawable.depth))
1103706f2543Smrg		{
1104706f2543Smrg		    error = BadMatch;
1105706f2543Smrg		    goto PatchUp;
1106706f2543Smrg		}
1107706f2543Smrg		if (pWin->parent->borderIsPixel == TRUE) {
1108706f2543Smrg		    if (pWin->borderIsPixel == FALSE)
1109706f2543Smrg			(*pScreen->DestroyPixmap)(pWin->border.pixmap);
1110706f2543Smrg		    pWin->border = pWin->parent->border;
1111706f2543Smrg		    pWin->borderIsPixel = TRUE;
1112706f2543Smrg		    index2 = CWBorderPixel;
1113706f2543Smrg		    break;
1114706f2543Smrg		}
1115706f2543Smrg		else
1116706f2543Smrg		{
1117706f2543Smrg		    pixID = pWin->parent->border.pixmap->drawable.id;
1118706f2543Smrg		}
1119706f2543Smrg	    }
1120706f2543Smrg	    rc = dixLookupResourceByType((pointer *)&pPixmap, pixID, RT_PIXMAP,
1121706f2543Smrg				   client, DixReadAccess);
1122706f2543Smrg	    if (rc == Success)
1123706f2543Smrg	    {
1124706f2543Smrg		if ((pPixmap->drawable.depth != pWin->drawable.depth) ||
1125706f2543Smrg		    (pPixmap->drawable.pScreen != pScreen))
1126706f2543Smrg		{
1127706f2543Smrg		    error = BadMatch;
1128706f2543Smrg		    goto PatchUp;
1129706f2543Smrg		}
1130706f2543Smrg		if (pWin->borderIsPixel == FALSE)
1131706f2543Smrg		    (*pScreen->DestroyPixmap)(pWin->border.pixmap);
1132706f2543Smrg		pWin->borderIsPixel = FALSE;
1133706f2543Smrg		pWin->border.pixmap = pPixmap;
1134706f2543Smrg		pPixmap->refcnt++;
1135706f2543Smrg	    }
1136706f2543Smrg	    else
1137706f2543Smrg	    {
1138706f2543Smrg		error = rc;
1139706f2543Smrg		client->errorValue = pixID;
1140706f2543Smrg		goto PatchUp;
1141706f2543Smrg	    }
1142706f2543Smrg	    break;
1143706f2543Smrg	  case CWBorderPixel:
1144706f2543Smrg	    if (pWin->borderIsPixel == FALSE)
1145706f2543Smrg		(*pScreen->DestroyPixmap)(pWin->border.pixmap);
1146706f2543Smrg	    pWin->borderIsPixel = TRUE;
1147706f2543Smrg	    pWin->border.pixel = (CARD32) *pVlist;
1148706f2543Smrg		    /* border pixel overrides border pixmap,
1149706f2543Smrg		       so don't let the ddx layer see both bits */
1150706f2543Smrg	    vmaskCopy &= ~CWBorderPixmap;
1151706f2543Smrg	    pVlist++;
1152706f2543Smrg	    break;
1153706f2543Smrg	  case CWBitGravity:
1154706f2543Smrg	    val = (CARD8 )*pVlist;
1155706f2543Smrg	    pVlist++;
1156706f2543Smrg	    if (val > StaticGravity)
1157706f2543Smrg	    {
1158706f2543Smrg		error = BadValue;
1159706f2543Smrg		client->errorValue = val;
1160706f2543Smrg		goto PatchUp;
1161706f2543Smrg	    }
1162706f2543Smrg	    pWin->bitGravity = val;
1163706f2543Smrg	    break;
1164706f2543Smrg	  case CWWinGravity:
1165706f2543Smrg	    val = (CARD8 )*pVlist;
1166706f2543Smrg	    pVlist++;
1167706f2543Smrg	    if (val > StaticGravity)
1168706f2543Smrg	    {
1169706f2543Smrg		error = BadValue;
1170706f2543Smrg		client->errorValue = val;
1171706f2543Smrg		goto PatchUp;
1172706f2543Smrg	    }
1173706f2543Smrg	    pWin->winGravity = val;
1174706f2543Smrg	    break;
1175706f2543Smrg	  case CWBackingStore:
1176706f2543Smrg	    val = (CARD8 )*pVlist;
1177706f2543Smrg	    pVlist++;
1178706f2543Smrg	    if ((val != NotUseful) && (val != WhenMapped) && (val != Always))
1179706f2543Smrg	    {
1180706f2543Smrg		error = BadValue;
1181706f2543Smrg		client->errorValue = val;
1182706f2543Smrg		goto PatchUp;
1183706f2543Smrg	    }
1184706f2543Smrg	    pWin->backingStore = val;
1185706f2543Smrg	    pWin->forcedBS = FALSE;
1186706f2543Smrg	    break;
1187706f2543Smrg	  case CWBackingPlanes:
1188706f2543Smrg	    if (pWin->optional || ((CARD32)*pVlist != (CARD32)~0L)) {
1189706f2543Smrg		if (!pWin->optional && !MakeWindowOptional (pWin))
1190706f2543Smrg		{
1191706f2543Smrg		    error = BadAlloc;
1192706f2543Smrg		    goto PatchUp;
1193706f2543Smrg		}
1194706f2543Smrg		pWin->optional->backingBitPlanes = (CARD32) *pVlist;
1195706f2543Smrg		if ((CARD32)*pVlist == (CARD32)~0L)
1196706f2543Smrg		    checkOptional = TRUE;
1197706f2543Smrg	    }
1198706f2543Smrg	    pVlist++;
1199706f2543Smrg	    break;
1200706f2543Smrg	  case CWBackingPixel:
1201706f2543Smrg	    if (pWin->optional || (CARD32) *pVlist) {
1202706f2543Smrg		if (!pWin->optional && !MakeWindowOptional (pWin))
1203706f2543Smrg		{
1204706f2543Smrg		    error = BadAlloc;
1205706f2543Smrg		    goto PatchUp;
1206706f2543Smrg		}
1207706f2543Smrg		pWin->optional->backingPixel = (CARD32) *pVlist;
1208706f2543Smrg		if (!*pVlist)
1209706f2543Smrg		    checkOptional = TRUE;
1210706f2543Smrg	    }
1211706f2543Smrg	    pVlist++;
1212706f2543Smrg	    break;
1213706f2543Smrg	  case CWSaveUnder:
1214706f2543Smrg	    val = (BOOL) *pVlist;
1215706f2543Smrg	    pVlist++;
1216706f2543Smrg	    if ((val != xTrue) && (val != xFalse))
1217706f2543Smrg	    {
1218706f2543Smrg		error = BadValue;
1219706f2543Smrg		client->errorValue = val;
1220706f2543Smrg		goto PatchUp;
1221706f2543Smrg	    }
1222706f2543Smrg	    pWin->saveUnder = val;
1223706f2543Smrg	    break;
1224706f2543Smrg	  case CWEventMask:
1225706f2543Smrg	    rc = EventSelectForWindow(pWin, client, (Mask )*pVlist);
1226706f2543Smrg	    if (rc)
1227706f2543Smrg	    {
1228706f2543Smrg		error = rc;
1229706f2543Smrg		goto PatchUp;
1230706f2543Smrg	    }
1231706f2543Smrg	    pVlist++;
1232706f2543Smrg	    break;
1233706f2543Smrg	  case CWDontPropagate:
1234706f2543Smrg	    rc = EventSuppressForWindow(pWin, client, (Mask )*pVlist,
1235706f2543Smrg					    &checkOptional);
1236706f2543Smrg	    if (rc)
1237706f2543Smrg	    {
1238706f2543Smrg		error = rc;
1239706f2543Smrg		goto PatchUp;
1240706f2543Smrg	    }
1241706f2543Smrg	    pVlist++;
1242706f2543Smrg	    break;
1243706f2543Smrg	  case CWOverrideRedirect:
1244706f2543Smrg	    val = (BOOL ) *pVlist;
1245706f2543Smrg	    pVlist++;
1246706f2543Smrg	    if ((val != xTrue) && (val != xFalse))
1247706f2543Smrg	    {
1248706f2543Smrg		error = BadValue;
1249706f2543Smrg		client->errorValue = val;
1250706f2543Smrg		goto PatchUp;
1251706f2543Smrg	    }
1252706f2543Smrg	    if (val == xTrue) {
1253706f2543Smrg		rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
1254706f2543Smrg			      RT_WINDOW, pWin, RT_NONE, NULL, DixGrabAccess);
1255706f2543Smrg		if (rc != Success) {
1256706f2543Smrg		    error = rc;
1257706f2543Smrg		    client->errorValue = pWin->drawable.id;
1258706f2543Smrg		    goto PatchUp;
1259706f2543Smrg		}
1260706f2543Smrg	    }
1261706f2543Smrg	    pWin->overrideRedirect = val;
1262706f2543Smrg	    break;
1263706f2543Smrg	  case CWColormap:
1264706f2543Smrg	    cmap = (Colormap) *pVlist;
1265706f2543Smrg	    pVlist++;
1266706f2543Smrg	    if (cmap == CopyFromParent)
1267706f2543Smrg	    {
1268706f2543Smrg		if (pWin->parent &&
1269706f2543Smrg		    (!pWin->optional ||
1270706f2543Smrg		     pWin->optional->visual == wVisual (pWin->parent)))
1271706f2543Smrg		{
1272706f2543Smrg		    cmap = wColormap (pWin->parent);
1273706f2543Smrg		}
1274706f2543Smrg		else
1275706f2543Smrg		    cmap = None;
1276706f2543Smrg	    }
1277706f2543Smrg	    if (cmap == None)
1278706f2543Smrg	    {
1279706f2543Smrg		error = BadMatch;
1280706f2543Smrg		goto PatchUp;
1281706f2543Smrg	    }
1282706f2543Smrg	    rc = dixLookupResourceByType((pointer *)&pCmap, cmap, RT_COLORMAP,
1283706f2543Smrg				   client, DixUseAccess);
1284706f2543Smrg	    if (rc != Success)
1285706f2543Smrg	    {
1286706f2543Smrg		error = rc;
1287706f2543Smrg		client->errorValue = cmap;
1288706f2543Smrg		goto PatchUp;
1289706f2543Smrg	    }
1290706f2543Smrg	    if (pCmap->pVisual->vid != wVisual (pWin) ||
1291706f2543Smrg		pCmap->pScreen != pScreen)
1292706f2543Smrg	    {
1293706f2543Smrg		error = BadMatch;
1294706f2543Smrg		goto PatchUp;
1295706f2543Smrg	    }
1296706f2543Smrg	    if (cmap != wColormap (pWin))
1297706f2543Smrg	    {
1298706f2543Smrg		if (!pWin->optional)
1299706f2543Smrg		{
1300706f2543Smrg		    if (!MakeWindowOptional (pWin))
1301706f2543Smrg		    {
1302706f2543Smrg			error = BadAlloc;
1303706f2543Smrg			goto PatchUp;
1304706f2543Smrg		    }
1305706f2543Smrg		}
1306706f2543Smrg		else if (pWin->parent && cmap == wColormap (pWin->parent))
1307706f2543Smrg		    checkOptional = TRUE;
1308706f2543Smrg
1309706f2543Smrg		/*
1310706f2543Smrg		 * propagate the original colormap to any children
1311706f2543Smrg		 * inheriting it
1312706f2543Smrg		 */
1313706f2543Smrg
1314706f2543Smrg		for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib)
1315706f2543Smrg		{
1316706f2543Smrg		    if (!pChild->optional && !MakeWindowOptional (pChild))
1317706f2543Smrg		    {
1318706f2543Smrg			error = BadAlloc;
1319706f2543Smrg			goto PatchUp;
1320706f2543Smrg		    }
1321706f2543Smrg		}
1322706f2543Smrg
1323706f2543Smrg		pWin->optional->colormap = cmap;
1324706f2543Smrg
1325706f2543Smrg		/*
1326706f2543Smrg		 * check on any children now matching the new colormap
1327706f2543Smrg		 */
1328706f2543Smrg
1329706f2543Smrg		for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib)
1330706f2543Smrg		{
1331706f2543Smrg		    if (pChild->optional->colormap == cmap)
1332706f2543Smrg			CheckWindowOptionalNeed (pChild);
1333706f2543Smrg		}
1334706f2543Smrg
1335706f2543Smrg		xE.u.u.type = ColormapNotify;
1336706f2543Smrg		xE.u.colormap.window = pWin->drawable.id;
1337706f2543Smrg		xE.u.colormap.colormap = cmap;
1338706f2543Smrg		xE.u.colormap.new = xTrue;
1339706f2543Smrg		xE.u.colormap.state = IsMapInstalled(cmap, pWin);
1340706f2543Smrg		DeliverEvents(pWin, &xE, 1, NullWindow);
1341706f2543Smrg	    }
1342706f2543Smrg	    break;
1343706f2543Smrg	  case CWCursor:
1344706f2543Smrg	    cursorID = (Cursor ) *pVlist;
1345706f2543Smrg	    pVlist++;
1346706f2543Smrg	    /*
1347706f2543Smrg	     * install the new
1348706f2543Smrg	     */
1349706f2543Smrg	    if ( cursorID == None)
1350706f2543Smrg	    {
1351706f2543Smrg		if (pWin == pWin->drawable.pScreen->root)
1352706f2543Smrg		    pCursor = rootCursor;
1353706f2543Smrg		else
1354706f2543Smrg		    pCursor = (CursorPtr) None;
1355706f2543Smrg	    }
1356706f2543Smrg	    else
1357706f2543Smrg	    {
1358706f2543Smrg		rc = dixLookupResourceByType((pointer *)&pCursor, cursorID,
1359706f2543Smrg				       RT_CURSOR, client, DixUseAccess);
1360706f2543Smrg		if (rc != Success)
1361706f2543Smrg		{
1362706f2543Smrg		    error = rc;
1363706f2543Smrg		    client->errorValue = cursorID;
1364706f2543Smrg		    goto PatchUp;
1365706f2543Smrg		}
1366706f2543Smrg	    }
1367706f2543Smrg
1368706f2543Smrg	    if (pCursor != wCursor (pWin))
1369706f2543Smrg	    {
1370706f2543Smrg		/*
1371706f2543Smrg		 * patch up child windows so they don't lose cursors.
1372706f2543Smrg		 */
1373706f2543Smrg
1374706f2543Smrg		for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib)
1375706f2543Smrg		{
1376706f2543Smrg		    if (!pChild->optional && !pChild->cursorIsNone &&
1377706f2543Smrg			!MakeWindowOptional (pChild))
1378706f2543Smrg		    {
1379706f2543Smrg			error = BadAlloc;
1380706f2543Smrg			goto PatchUp;
1381706f2543Smrg		    }
1382706f2543Smrg		}
1383706f2543Smrg
1384706f2543Smrg		pOldCursor = 0;
1385706f2543Smrg		if (pCursor == (CursorPtr) None)
1386706f2543Smrg		{
1387706f2543Smrg		    pWin->cursorIsNone = TRUE;
1388706f2543Smrg		    if (pWin->optional)
1389706f2543Smrg		    {
1390706f2543Smrg			pOldCursor = pWin->optional->cursor;
1391706f2543Smrg			pWin->optional->cursor = (CursorPtr) None;
1392706f2543Smrg			checkOptional = TRUE;
1393706f2543Smrg		    }
1394706f2543Smrg		} else {
1395706f2543Smrg		    if (!pWin->optional)
1396706f2543Smrg		    {
1397706f2543Smrg			if (!MakeWindowOptional (pWin))
1398706f2543Smrg			{
1399706f2543Smrg			    error = BadAlloc;
1400706f2543Smrg			    goto PatchUp;
1401706f2543Smrg			}
1402706f2543Smrg		    }
1403706f2543Smrg		    else if (pWin->parent && pCursor == wCursor (pWin->parent))
1404706f2543Smrg			checkOptional = TRUE;
1405706f2543Smrg		    pOldCursor = pWin->optional->cursor;
1406706f2543Smrg		    pWin->optional->cursor = pCursor;
1407706f2543Smrg		    pCursor->refcnt++;
1408706f2543Smrg		    pWin->cursorIsNone = FALSE;
1409706f2543Smrg		    /*
1410706f2543Smrg		     * check on any children now matching the new cursor
1411706f2543Smrg		     */
1412706f2543Smrg
1413706f2543Smrg		    for (pChild=pWin->firstChild; pChild; pChild=pChild->nextSib)
1414706f2543Smrg		    {
1415706f2543Smrg			if (pChild->optional &&
1416706f2543Smrg			    (pChild->optional->cursor == pCursor))
1417706f2543Smrg			    CheckWindowOptionalNeed (pChild);
1418706f2543Smrg		    }
1419706f2543Smrg		}
1420706f2543Smrg
1421706f2543Smrg		if (pWin->realized)
1422706f2543Smrg		    WindowHasNewCursor( pWin);
1423706f2543Smrg
1424706f2543Smrg		/* Can't free cursor until here - old cursor
1425706f2543Smrg		 * is needed in WindowHasNewCursor
1426706f2543Smrg		 */
1427706f2543Smrg		if (pOldCursor)
1428706f2543Smrg		    FreeCursor (pOldCursor, (Cursor)0);
1429706f2543Smrg	    }
1430706f2543Smrg	    break;
1431706f2543Smrg	 default:
1432706f2543Smrg	    error = BadValue;
1433706f2543Smrg	    client->errorValue = vmask;
1434706f2543Smrg	    goto PatchUp;
1435706f2543Smrg      }
1436706f2543Smrg      vmaskCopy |= index2;
1437706f2543Smrg    }
1438706f2543SmrgPatchUp:
1439706f2543Smrg    if (checkOptional)
1440706f2543Smrg	CheckWindowOptionalNeed (pWin);
1441706f2543Smrg
1442706f2543Smrg	/* We SHOULD check for an error value here XXX */
1443706f2543Smrg    (*pScreen->ChangeWindowAttributes)(pWin, vmaskCopy);
1444706f2543Smrg
1445706f2543Smrg    /*
1446706f2543Smrg	If the border contents have changed, redraw the border.
1447706f2543Smrg	Note that this has to be done AFTER pScreen->ChangeWindowAttributes
1448706f2543Smrg	for the tile to be rotated, and the correct function selected.
1449706f2543Smrg    */
1450706f2543Smrg    if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative)
1451706f2543Smrg	&& pWin->viewable && HasBorder (pWin))
1452706f2543Smrg    {
1453706f2543Smrg	RegionRec exposed;
1454706f2543Smrg
1455706f2543Smrg	RegionNull(&exposed);
1456706f2543Smrg	RegionSubtract(&exposed, &pWin->borderClip, &pWin->winSize);
1457706f2543Smrg	miPaintWindow(pWin, &exposed, PW_BORDER);
1458706f2543Smrg	RegionUninit(&exposed);
1459706f2543Smrg    }
1460706f2543Smrg    return error;
1461706f2543Smrg}
1462706f2543Smrg
1463706f2543Smrg
1464706f2543Smrg/*****
1465706f2543Smrg * GetWindowAttributes
1466706f2543Smrg *    Notice that this is different than ChangeWindowAttributes
1467706f2543Smrg *****/
1468706f2543Smrg
1469706f2543Smrgvoid
1470706f2543SmrgGetWindowAttributes(WindowPtr pWin, ClientPtr client, xGetWindowAttributesReply *wa)
1471706f2543Smrg{
1472706f2543Smrg    wa->type = X_Reply;
1473706f2543Smrg    wa->bitGravity = pWin->bitGravity;
1474706f2543Smrg    wa->winGravity = pWin->winGravity;
1475706f2543Smrg    if (pWin->forcedBS && pWin->backingStore != Always)
1476706f2543Smrg	wa->backingStore = NotUseful;
1477706f2543Smrg    else
1478706f2543Smrg	wa->backingStore = pWin->backingStore;
1479706f2543Smrg    wa->length = bytes_to_int32(sizeof(xGetWindowAttributesReply) -
1480706f2543Smrg		 sizeof(xGenericReply));
1481706f2543Smrg    wa->sequenceNumber = client->sequence;
1482706f2543Smrg    wa->backingBitPlanes =  wBackingBitPlanes (pWin);
1483706f2543Smrg    wa->backingPixel =  wBackingPixel (pWin);
1484706f2543Smrg    wa->saveUnder = (BOOL)pWin->saveUnder;
1485706f2543Smrg    wa->override = pWin->overrideRedirect;
1486706f2543Smrg    if (!pWin->mapped)
1487706f2543Smrg	wa->mapState = IsUnmapped;
1488706f2543Smrg    else if (pWin->realized)
1489706f2543Smrg	wa->mapState = IsViewable;
1490706f2543Smrg    else
1491706f2543Smrg	wa->mapState = IsUnviewable;
1492706f2543Smrg
1493706f2543Smrg    wa->colormap =  wColormap (pWin);
1494706f2543Smrg    wa->mapInstalled = (wa->colormap == None) ? xFalse
1495706f2543Smrg				: IsMapInstalled(wa->colormap, pWin);
1496706f2543Smrg
1497706f2543Smrg    wa->yourEventMask = EventMaskForClient(pWin, client);
1498706f2543Smrg    wa->allEventMasks = pWin->eventMask | wOtherEventMasks (pWin);
1499706f2543Smrg    wa->doNotPropagateMask = wDontPropagateMask (pWin);
1500706f2543Smrg    wa->class = pWin->drawable.class;
1501706f2543Smrg    wa->visualID = wVisual (pWin);
1502706f2543Smrg}
1503706f2543Smrg
1504706f2543Smrg
1505706f2543SmrgWindowPtr
1506706f2543SmrgMoveWindowInStack(WindowPtr pWin, WindowPtr pNextSib)
1507706f2543Smrg{
1508706f2543Smrg    WindowPtr pParent = pWin->parent;
1509706f2543Smrg    WindowPtr pFirstChange = pWin; /* highest window where list changes */
1510706f2543Smrg
1511706f2543Smrg    if (pWin->nextSib != pNextSib)
1512706f2543Smrg    {
1513706f2543Smrg	WindowPtr pOldNextSib = pWin->nextSib;
1514706f2543Smrg
1515706f2543Smrg	if (!pNextSib)	      /* move to bottom */
1516706f2543Smrg	{
1517706f2543Smrg	    if (pParent->firstChild == pWin)
1518706f2543Smrg		pParent->firstChild = pWin->nextSib;
1519706f2543Smrg	    /* if (pWin->nextSib) */	 /* is always True: pNextSib == NULL
1520706f2543Smrg					  * and pWin->nextSib != pNextSib
1521706f2543Smrg					  * therefore pWin->nextSib != NULL */
1522706f2543Smrg	    pFirstChange = pWin->nextSib;
1523706f2543Smrg	    pWin->nextSib->prevSib = pWin->prevSib;
1524706f2543Smrg	    if (pWin->prevSib)
1525706f2543Smrg		pWin->prevSib->nextSib = pWin->nextSib;
1526706f2543Smrg	    pParent->lastChild->nextSib = pWin;
1527706f2543Smrg	    pWin->prevSib = pParent->lastChild;
1528706f2543Smrg	    pWin->nextSib = NullWindow;
1529706f2543Smrg	    pParent->lastChild = pWin;
1530706f2543Smrg	}
1531706f2543Smrg	else if (pParent->firstChild == pNextSib) /* move to top */
1532706f2543Smrg	{
1533706f2543Smrg	    pFirstChange = pWin;
1534706f2543Smrg	    if (pParent->lastChild == pWin)
1535706f2543Smrg	       pParent->lastChild = pWin->prevSib;
1536706f2543Smrg	    if (pWin->nextSib)
1537706f2543Smrg		pWin->nextSib->prevSib = pWin->prevSib;
1538706f2543Smrg	    if (pWin->prevSib)
1539706f2543Smrg		pWin->prevSib->nextSib = pWin->nextSib;
1540706f2543Smrg	    pWin->nextSib = pParent->firstChild;
1541706f2543Smrg	    pWin->prevSib = (WindowPtr ) NULL;
1542706f2543Smrg	    pNextSib->prevSib = pWin;
1543706f2543Smrg	    pParent->firstChild = pWin;
1544706f2543Smrg	}
1545706f2543Smrg	else			/* move in middle of list */
1546706f2543Smrg	{
1547706f2543Smrg	    WindowPtr pOldNext = pWin->nextSib;
1548706f2543Smrg
1549706f2543Smrg	    pFirstChange = NullWindow;
1550706f2543Smrg	    if (pParent->firstChild == pWin)
1551706f2543Smrg		pFirstChange = pParent->firstChild = pWin->nextSib;
1552706f2543Smrg	    if (pParent->lastChild == pWin) {
1553706f2543Smrg	       pFirstChange = pWin;
1554706f2543Smrg	       pParent->lastChild = pWin->prevSib;
1555706f2543Smrg	    }
1556706f2543Smrg	    if (pWin->nextSib)
1557706f2543Smrg		pWin->nextSib->prevSib = pWin->prevSib;
1558706f2543Smrg	    if (pWin->prevSib)
1559706f2543Smrg		pWin->prevSib->nextSib = pWin->nextSib;
1560706f2543Smrg	    pWin->nextSib = pNextSib;
1561706f2543Smrg	    pWin->prevSib = pNextSib->prevSib;
1562706f2543Smrg	    if (pNextSib->prevSib)
1563706f2543Smrg		pNextSib->prevSib->nextSib = pWin;
1564706f2543Smrg	    pNextSib->prevSib = pWin;
1565706f2543Smrg	    if (!pFirstChange) {		     /* do we know it yet? */
1566706f2543Smrg		pFirstChange = pParent->firstChild;  /* no, search from top */
1567706f2543Smrg		while ((pFirstChange != pWin) && (pFirstChange != pOldNext))
1568706f2543Smrg		     pFirstChange = pFirstChange->nextSib;
1569706f2543Smrg	    }
1570706f2543Smrg	}
1571706f2543Smrg	if(pWin->drawable.pScreen->RestackWindow)
1572706f2543Smrg	    (*pWin->drawable.pScreen->RestackWindow)(pWin, pOldNextSib);
1573706f2543Smrg    }
1574706f2543Smrg
1575706f2543Smrg#ifdef ROOTLESS
1576706f2543Smrg    /*
1577706f2543Smrg     * In rootless mode we can't optimize away window restacks.
1578706f2543Smrg     * There may be non-X windows around, so even if the window
1579706f2543Smrg     * is in the correct position from X's point of view,
1580706f2543Smrg     * the underlying window system may want to reorder it.
1581706f2543Smrg     */
1582706f2543Smrg    else if (pWin->drawable.pScreen->RestackWindow)
1583706f2543Smrg        (*pWin->drawable.pScreen->RestackWindow)(pWin, pWin->nextSib);
1584706f2543Smrg#endif
1585706f2543Smrg
1586706f2543Smrg    return pFirstChange;
1587706f2543Smrg}
1588706f2543Smrg
1589706f2543Smrgvoid
1590706f2543SmrgSetWinSize (WindowPtr pWin)
1591706f2543Smrg{
1592706f2543Smrg#ifdef COMPOSITE
1593706f2543Smrg    if (pWin->redirectDraw != RedirectDrawNone)
1594706f2543Smrg    {
1595706f2543Smrg	BoxRec	box;
1596706f2543Smrg
1597706f2543Smrg	/*
1598706f2543Smrg	 * Redirected clients get clip list equal to their
1599706f2543Smrg	 * own geometry, not clipped to their parent
1600706f2543Smrg	 */
1601706f2543Smrg	box.x1 = pWin->drawable.x;
1602706f2543Smrg	box.y1 = pWin->drawable.y;
1603706f2543Smrg	box.x2 = pWin->drawable.x + pWin->drawable.width;
1604706f2543Smrg	box.y2 = pWin->drawable.y + pWin->drawable.height;
1605706f2543Smrg	RegionReset(&pWin->winSize, &box);
1606706f2543Smrg    }
1607706f2543Smrg    else
1608706f2543Smrg#endif
1609706f2543Smrg    ClippedRegionFromBox(pWin->parent, &pWin->winSize,
1610706f2543Smrg			 pWin->drawable.x, pWin->drawable.y,
1611706f2543Smrg			 (int)pWin->drawable.width,
1612706f2543Smrg			 (int)pWin->drawable.height);
1613706f2543Smrg    if (wBoundingShape (pWin) || wClipShape (pWin)) {
1614706f2543Smrg	RegionTranslate(&pWin->winSize, - pWin->drawable.x,
1615706f2543Smrg			 - pWin->drawable.y);
1616706f2543Smrg	if (wBoundingShape (pWin))
1617706f2543Smrg	    RegionIntersect(&pWin->winSize, &pWin->winSize,
1618706f2543Smrg			     wBoundingShape (pWin));
1619706f2543Smrg	if (wClipShape (pWin))
1620706f2543Smrg	    RegionIntersect(&pWin->winSize, &pWin->winSize,
1621706f2543Smrg			     wClipShape (pWin));
1622706f2543Smrg	RegionTranslate(&pWin->winSize, pWin->drawable.x,
1623706f2543Smrg			 pWin->drawable.y);
1624706f2543Smrg    }
1625706f2543Smrg}
1626706f2543Smrg
1627706f2543Smrgvoid
1628706f2543SmrgSetBorderSize (WindowPtr pWin)
1629706f2543Smrg{
1630706f2543Smrg    int	bw;
1631706f2543Smrg
1632706f2543Smrg    if (HasBorder (pWin)) {
1633706f2543Smrg	bw = wBorderWidth (pWin);
1634706f2543Smrg#ifdef COMPOSITE
1635706f2543Smrg	if (pWin->redirectDraw != RedirectDrawNone)
1636706f2543Smrg	{
1637706f2543Smrg	    BoxRec	box;
1638706f2543Smrg
1639706f2543Smrg	    /*
1640706f2543Smrg	     * Redirected clients get clip list equal to their
1641706f2543Smrg	     * own geometry, not clipped to their parent
1642706f2543Smrg	     */
1643706f2543Smrg	    box.x1 = pWin->drawable.x - bw;
1644706f2543Smrg	    box.y1 = pWin->drawable.y - bw;
1645706f2543Smrg	    box.x2 = pWin->drawable.x + pWin->drawable.width + bw;
1646706f2543Smrg	    box.y2 = pWin->drawable.y + pWin->drawable.height + bw;
1647706f2543Smrg	    RegionReset(&pWin->borderSize, &box);
1648706f2543Smrg	}
1649706f2543Smrg	else
1650706f2543Smrg#endif
1651706f2543Smrg	ClippedRegionFromBox(pWin->parent, &pWin->borderSize,
1652706f2543Smrg		pWin->drawable.x - bw, pWin->drawable.y - bw,
1653706f2543Smrg		(int)(pWin->drawable.width + (bw<<1)),
1654706f2543Smrg		(int)(pWin->drawable.height + (bw<<1)));
1655706f2543Smrg	if (wBoundingShape (pWin)) {
1656706f2543Smrg	    RegionTranslate(&pWin->borderSize, - pWin->drawable.x,
1657706f2543Smrg			     - pWin->drawable.y);
1658706f2543Smrg	    RegionIntersect(&pWin->borderSize, &pWin->borderSize,
1659706f2543Smrg			     wBoundingShape (pWin));
1660706f2543Smrg	    RegionTranslate(&pWin->borderSize, pWin->drawable.x,
1661706f2543Smrg			     pWin->drawable.y);
1662706f2543Smrg	    RegionUnion(&pWin->borderSize, &pWin->borderSize,
1663706f2543Smrg			 &pWin->winSize);
1664706f2543Smrg	}
1665706f2543Smrg    } else {
1666706f2543Smrg	RegionCopy(&pWin->borderSize, &pWin->winSize);
1667706f2543Smrg    }
1668706f2543Smrg}
1669706f2543Smrg
1670706f2543Smrg/**
1671706f2543Smrg *
1672706f2543Smrg *  \param x,y          new window position
1673706f2543Smrg *  \param oldx,oldy    old window position
1674706f2543Smrg *  \param destx,desty  position relative to gravity
1675706f2543Smrg */
1676706f2543Smrg
1677706f2543Smrgvoid
1678706f2543SmrgGravityTranslate (int x, int y, int oldx, int oldy,
1679706f2543Smrg                  int dw, int dh, unsigned gravity,
1680706f2543Smrg                  int *destx, int *desty)
1681706f2543Smrg{
1682706f2543Smrg    switch (gravity) {
1683706f2543Smrg    case NorthGravity:
1684706f2543Smrg	*destx = x + dw / 2;
1685706f2543Smrg	*desty = y;
1686706f2543Smrg	break;
1687706f2543Smrg    case NorthEastGravity:
1688706f2543Smrg	*destx = x + dw;
1689706f2543Smrg	*desty = y;
1690706f2543Smrg	break;
1691706f2543Smrg    case WestGravity:
1692706f2543Smrg	*destx = x;
1693706f2543Smrg	*desty = y + dh / 2;
1694706f2543Smrg	break;
1695706f2543Smrg    case CenterGravity:
1696706f2543Smrg	*destx = x + dw / 2;
1697706f2543Smrg	*desty = y + dh / 2;
1698706f2543Smrg	break;
1699706f2543Smrg    case EastGravity:
1700706f2543Smrg	*destx = x + dw;
1701706f2543Smrg	*desty = y + dh / 2;
1702706f2543Smrg	break;
1703706f2543Smrg    case SouthWestGravity:
1704706f2543Smrg	*destx = x;
1705706f2543Smrg	*desty = y + dh;
1706706f2543Smrg	break;
1707706f2543Smrg    case SouthGravity:
1708706f2543Smrg	*destx = x + dw / 2;
1709706f2543Smrg	*desty = y + dh;
1710706f2543Smrg	break;
1711706f2543Smrg    case SouthEastGravity:
1712706f2543Smrg	*destx = x + dw;
1713706f2543Smrg	*desty = y + dh;
1714706f2543Smrg	break;
1715706f2543Smrg    case StaticGravity:
1716706f2543Smrg	*destx = oldx;
1717706f2543Smrg	*desty = oldy;
1718706f2543Smrg	break;
1719706f2543Smrg    default:
1720706f2543Smrg	*destx = x;
1721706f2543Smrg	*desty = y;
1722706f2543Smrg	break;
1723706f2543Smrg    }
1724706f2543Smrg}
1725706f2543Smrg
1726706f2543Smrg/* XXX need to retile border on each window with ParentRelative origin */
1727706f2543Smrgvoid
1728706f2543SmrgResizeChildrenWinSize(WindowPtr pWin, int dx, int dy, int dw, int dh)
1729706f2543Smrg{
1730706f2543Smrg    ScreenPtr pScreen;
1731706f2543Smrg    WindowPtr pSib, pChild;
1732706f2543Smrg    Bool resized = (dw || dh);
1733706f2543Smrg
1734706f2543Smrg    pScreen = pWin->drawable.pScreen;
1735706f2543Smrg
1736706f2543Smrg    for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib)
1737706f2543Smrg    {
1738706f2543Smrg	if (resized && (pSib->winGravity > NorthWestGravity))
1739706f2543Smrg	{
1740706f2543Smrg	    int cwsx, cwsy;
1741706f2543Smrg
1742706f2543Smrg	    cwsx = pSib->origin.x;
1743706f2543Smrg	    cwsy = pSib->origin.y;
1744706f2543Smrg	    GravityTranslate (cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh,
1745706f2543Smrg			pSib->winGravity, &cwsx, &cwsy);
1746706f2543Smrg	    if (cwsx != pSib->origin.x || cwsy != pSib->origin.y)
1747706f2543Smrg	    {
1748706f2543Smrg		xEvent event;
1749706f2543Smrg
1750706f2543Smrg		event.u.u.type = GravityNotify;
1751706f2543Smrg		event.u.gravity.window = pSib->drawable.id;
1752706f2543Smrg		event.u.gravity.x = cwsx - wBorderWidth (pSib);
1753706f2543Smrg		event.u.gravity.y = cwsy - wBorderWidth (pSib);
1754706f2543Smrg		DeliverEvents (pSib, &event, 1, NullWindow);
1755706f2543Smrg		pSib->origin.x = cwsx;
1756706f2543Smrg		pSib->origin.y = cwsy;
1757706f2543Smrg	    }
1758706f2543Smrg	}
1759706f2543Smrg	pSib->drawable.x = pWin->drawable.x + pSib->origin.x;
1760706f2543Smrg	pSib->drawable.y = pWin->drawable.y + pSib->origin.y;
1761706f2543Smrg	SetWinSize (pSib);
1762706f2543Smrg	SetBorderSize (pSib);
1763706f2543Smrg	(*pScreen->PositionWindow)(pSib, pSib->drawable.x, pSib->drawable.y);
1764706f2543Smrg
1765706f2543Smrg	if ( (pChild = pSib->firstChild) )
1766706f2543Smrg	{
1767706f2543Smrg	    while (1)
1768706f2543Smrg	    {
1769706f2543Smrg		pChild->drawable.x = pChild->parent->drawable.x +
1770706f2543Smrg				     pChild->origin.x;
1771706f2543Smrg		pChild->drawable.y = pChild->parent->drawable.y +
1772706f2543Smrg				     pChild->origin.y;
1773706f2543Smrg		SetWinSize (pChild);
1774706f2543Smrg		SetBorderSize (pChild);
1775706f2543Smrg		(*pScreen->PositionWindow)(pChild,
1776706f2543Smrg				    pChild->drawable.x, pChild->drawable.y);
1777706f2543Smrg		if (pChild->firstChild)
1778706f2543Smrg		{
1779706f2543Smrg		    pChild = pChild->firstChild;
1780706f2543Smrg		    continue;
1781706f2543Smrg		}
1782706f2543Smrg		while (!pChild->nextSib && (pChild != pSib))
1783706f2543Smrg		    pChild = pChild->parent;
1784706f2543Smrg		if (pChild == pSib)
1785706f2543Smrg		    break;
1786706f2543Smrg		pChild = pChild->nextSib;
1787706f2543Smrg	    }
1788706f2543Smrg	}
1789706f2543Smrg    }
1790706f2543Smrg}
1791706f2543Smrg
1792706f2543Smrg#define GET_INT16(m, f) \
1793706f2543Smrg	if (m & mask) \
1794706f2543Smrg	  { \
1795706f2543Smrg	     f = (INT16) *pVlist;\
1796706f2543Smrg	    pVlist++; \
1797706f2543Smrg	 }
1798706f2543Smrg#define GET_CARD16(m, f) \
1799706f2543Smrg	if (m & mask) \
1800706f2543Smrg	 { \
1801706f2543Smrg	    f = (CARD16) *pVlist;\
1802706f2543Smrg	    pVlist++;\
1803706f2543Smrg	 }
1804706f2543Smrg
1805706f2543Smrg#define GET_CARD8(m, f) \
1806706f2543Smrg	if (m & mask) \
1807706f2543Smrg	 { \
1808706f2543Smrg	    f = (CARD8) *pVlist;\
1809706f2543Smrg	    pVlist++;\
1810706f2543Smrg	 }
1811706f2543Smrg
1812706f2543Smrg#define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight))
1813706f2543Smrg
1814706f2543Smrg#define IllegalInputOnlyConfigureMask (CWBorderWidth)
1815706f2543Smrg
1816706f2543Smrg/*
1817706f2543Smrg * IsSiblingAboveMe
1818706f2543Smrg *     returns Above if pSib above pMe in stack or Below otherwise
1819706f2543Smrg */
1820706f2543Smrg
1821706f2543Smrgstatic int
1822706f2543SmrgIsSiblingAboveMe(
1823706f2543Smrg    WindowPtr pMe,
1824706f2543Smrg    WindowPtr pSib)
1825706f2543Smrg{
1826706f2543Smrg    WindowPtr pWin;
1827706f2543Smrg
1828706f2543Smrg    pWin = pMe->parent->firstChild;
1829706f2543Smrg    while (pWin)
1830706f2543Smrg    {
1831706f2543Smrg	if (pWin == pSib)
1832706f2543Smrg	    return Above;
1833706f2543Smrg	else if (pWin == pMe)
1834706f2543Smrg	    return Below;
1835706f2543Smrg	pWin = pWin->nextSib;
1836706f2543Smrg    }
1837706f2543Smrg    return Below;
1838706f2543Smrg}
1839706f2543Smrg
1840706f2543Smrgstatic BoxPtr
1841706f2543SmrgWindowExtents(
1842706f2543Smrg    WindowPtr pWin,
1843706f2543Smrg    BoxPtr pBox)
1844706f2543Smrg{
1845706f2543Smrg    pBox->x1 = pWin->drawable.x - wBorderWidth (pWin);
1846706f2543Smrg    pBox->y1 = pWin->drawable.y - wBorderWidth (pWin);
1847706f2543Smrg    pBox->x2 = pWin->drawable.x + (int)pWin->drawable.width
1848706f2543Smrg	       + wBorderWidth (pWin);
1849706f2543Smrg    pBox->y2 = pWin->drawable.y + (int)pWin->drawable.height
1850706f2543Smrg	       + wBorderWidth (pWin);
1851706f2543Smrg    return pBox;
1852706f2543Smrg}
1853706f2543Smrg
1854706f2543Smrg#define IS_SHAPED(pWin)	(wBoundingShape (pWin) != (RegionPtr) NULL)
1855706f2543Smrg
1856706f2543Smrgstatic RegionPtr
1857706f2543SmrgMakeBoundingRegion (
1858706f2543Smrg    WindowPtr	pWin,
1859706f2543Smrg    BoxPtr	pBox)
1860706f2543Smrg{
1861706f2543Smrg    RegionPtr	pRgn = RegionCreate(pBox, 1);
1862706f2543Smrg    if (wBoundingShape (pWin)) {
1863706f2543Smrg	RegionTranslate(pRgn, -pWin->origin.x, -pWin->origin.y);
1864706f2543Smrg	RegionIntersect(pRgn, pRgn, wBoundingShape (pWin));
1865706f2543Smrg	RegionTranslate(pRgn, pWin->origin.x, pWin->origin.y);
1866706f2543Smrg    }
1867706f2543Smrg    return pRgn;
1868706f2543Smrg}
1869706f2543Smrg
1870706f2543Smrgstatic Bool
1871706f2543SmrgShapeOverlap (
1872706f2543Smrg    WindowPtr	pWin,
1873706f2543Smrg    BoxPtr	pWinBox,
1874706f2543Smrg    WindowPtr	pSib,
1875706f2543Smrg    BoxPtr	pSibBox)
1876706f2543Smrg{
1877706f2543Smrg    RegionPtr	pWinRgn, pSibRgn;
1878706f2543Smrg    Bool	ret;
1879706f2543Smrg
1880706f2543Smrg    if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib))
1881706f2543Smrg	return TRUE;
1882706f2543Smrg    pWinRgn = MakeBoundingRegion (pWin, pWinBox);
1883706f2543Smrg    pSibRgn = MakeBoundingRegion (pSib, pSibBox);
1884706f2543Smrg    RegionIntersect(pWinRgn, pWinRgn, pSibRgn);
1885706f2543Smrg    ret = RegionNotEmpty(pWinRgn);
1886706f2543Smrg    RegionDestroy(pWinRgn);
1887706f2543Smrg    RegionDestroy(pSibRgn);
1888706f2543Smrg    return ret;
1889706f2543Smrg}
1890706f2543Smrg
1891706f2543Smrgstatic Bool
1892706f2543SmrgAnyWindowOverlapsMe(
1893706f2543Smrg    WindowPtr pWin,
1894706f2543Smrg    WindowPtr pHead,
1895706f2543Smrg    BoxPtr box)
1896706f2543Smrg{
1897706f2543Smrg    WindowPtr pSib;
1898706f2543Smrg    BoxRec sboxrec;
1899706f2543Smrg    BoxPtr sbox;
1900706f2543Smrg
1901706f2543Smrg    for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib)
1902706f2543Smrg    {
1903706f2543Smrg	if (pSib->mapped)
1904706f2543Smrg	{
1905706f2543Smrg	    sbox = WindowExtents(pSib, &sboxrec);
1906706f2543Smrg	    if (BOXES_OVERLAP(sbox, box)
1907706f2543Smrg	    && ShapeOverlap (pWin, box, pSib, sbox)
1908706f2543Smrg	    )
1909706f2543Smrg		return TRUE;
1910706f2543Smrg	}
1911706f2543Smrg    }
1912706f2543Smrg    return FALSE;
1913706f2543Smrg}
1914706f2543Smrg
1915706f2543Smrgstatic Bool
1916706f2543SmrgIOverlapAnyWindow(
1917706f2543Smrg    WindowPtr pWin,
1918706f2543Smrg    BoxPtr box)
1919706f2543Smrg{
1920706f2543Smrg    WindowPtr pSib;
1921706f2543Smrg    BoxRec sboxrec;
1922706f2543Smrg    BoxPtr sbox;
1923706f2543Smrg
1924706f2543Smrg    for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib)
1925706f2543Smrg    {
1926706f2543Smrg	if (pSib->mapped)
1927706f2543Smrg	{
1928706f2543Smrg	    sbox = WindowExtents(pSib, &sboxrec);
1929706f2543Smrg	    if (BOXES_OVERLAP(sbox, box)
1930706f2543Smrg	    && ShapeOverlap (pWin, box, pSib, sbox)
1931706f2543Smrg	    )
1932706f2543Smrg		return TRUE;
1933706f2543Smrg	}
1934706f2543Smrg    }
1935706f2543Smrg    return FALSE;
1936706f2543Smrg}
1937706f2543Smrg
1938706f2543Smrg/*
1939706f2543Smrg *   WhereDoIGoInTheStack()
1940706f2543Smrg *	  Given pWin and pSib and the relationshipe smode, return
1941706f2543Smrg *	  the window that pWin should go ABOVE.
1942706f2543Smrg *	  If a pSib is specified:
1943706f2543Smrg *	      Above:  pWin is placed just above pSib
1944706f2543Smrg *	      Below:  pWin is placed just below pSib
1945706f2543Smrg *	      TopIf:  if pSib occludes pWin, then pWin is placed
1946706f2543Smrg *		      at the top of the stack
1947706f2543Smrg *	      BottomIf:	 if pWin occludes pSib, then pWin is
1948706f2543Smrg *			 placed at the bottom of the stack
1949706f2543Smrg *	      Opposite: if pSib occludes pWin, then pWin is placed at the
1950706f2543Smrg *			top of the stack, else if pWin occludes pSib, then
1951706f2543Smrg *			pWin is placed at the bottom of the stack
1952706f2543Smrg *
1953706f2543Smrg *	  If pSib is NULL:
1954706f2543Smrg *	      Above:  pWin is placed at the top of the stack
1955706f2543Smrg *	      Below:  pWin is placed at the bottom of the stack
1956706f2543Smrg *	      TopIf:  if any sibling occludes pWin, then pWin is placed at
1957706f2543Smrg *		      the top of the stack
1958706f2543Smrg *	      BottomIf: if pWin occludes any sibline, then pWin is placed at
1959706f2543Smrg *			the bottom of the stack
1960706f2543Smrg *	      Opposite: if any sibling occludes pWin, then pWin is placed at
1961706f2543Smrg *			the top of the stack, else if pWin occludes any
1962706f2543Smrg *			sibling, then pWin is placed at the bottom of the stack
1963706f2543Smrg *
1964706f2543Smrg */
1965706f2543Smrg
1966706f2543Smrgstatic WindowPtr
1967706f2543SmrgWhereDoIGoInTheStack(
1968706f2543Smrg    WindowPtr pWin,
1969706f2543Smrg    WindowPtr pSib,
1970706f2543Smrg    short x,
1971706f2543Smrg    short y,
1972706f2543Smrg    unsigned short w,
1973706f2543Smrg    unsigned short h,
1974706f2543Smrg    int smode)
1975706f2543Smrg{
1976706f2543Smrg    BoxRec box;
1977706f2543Smrg    WindowPtr pHead, pFirst;
1978706f2543Smrg
1979706f2543Smrg    if ((pWin == pWin->parent->firstChild) &&
1980706f2543Smrg	(pWin == pWin->parent->lastChild))
1981706f2543Smrg	return((WindowPtr ) NULL);
1982706f2543Smrg    pHead = RealChildHead(pWin->parent);
1983706f2543Smrg    pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild;
1984706f2543Smrg    box.x1 = x;
1985706f2543Smrg    box.y1 = y;
1986706f2543Smrg    box.x2 = x + (int)w;
1987706f2543Smrg    box.y2 = y + (int)h;
1988706f2543Smrg    switch (smode)
1989706f2543Smrg    {
1990706f2543Smrg      case Above:
1991706f2543Smrg	if (pSib)
1992706f2543Smrg	   return pSib;
1993706f2543Smrg	else if (pWin == pFirst)
1994706f2543Smrg	    return pWin->nextSib;
1995706f2543Smrg	else
1996706f2543Smrg	    return pFirst;
1997706f2543Smrg      case Below:
1998706f2543Smrg	if (pSib)
1999706f2543Smrg	    if (pSib->nextSib != pWin)
2000706f2543Smrg		return pSib->nextSib;
2001706f2543Smrg	    else
2002706f2543Smrg		return pWin->nextSib;
2003706f2543Smrg	else
2004706f2543Smrg	    return NullWindow;
2005706f2543Smrg      case TopIf:
2006706f2543Smrg	if ((!pWin->mapped || (pSib && !pSib->mapped)))
2007706f2543Smrg	    return pWin->nextSib;
2008706f2543Smrg	else if (pSib)
2009706f2543Smrg	{
2010706f2543Smrg	    if ((IsSiblingAboveMe(pWin, pSib) == Above) &&
2011706f2543Smrg		(RegionContainsRect(&pSib->borderSize, &box) != rgnOUT))
2012706f2543Smrg		return pFirst;
2013706f2543Smrg	    else
2014706f2543Smrg		return pWin->nextSib;
2015706f2543Smrg	}
2016706f2543Smrg	else if (AnyWindowOverlapsMe(pWin, pHead, &box))
2017706f2543Smrg	    return pFirst;
2018706f2543Smrg	else
2019706f2543Smrg	    return pWin->nextSib;
2020706f2543Smrg      case BottomIf:
2021706f2543Smrg	if ((!pWin->mapped || (pSib && !pSib->mapped)))
2022706f2543Smrg	    return pWin->nextSib;
2023706f2543Smrg	else if (pSib)
2024706f2543Smrg	{
2025706f2543Smrg	    if ((IsSiblingAboveMe(pWin, pSib) == Below) &&
2026706f2543Smrg		(RegionContainsRect(&pSib->borderSize, &box) != rgnOUT))
2027706f2543Smrg		return NullWindow;
2028706f2543Smrg	    else
2029706f2543Smrg		return pWin->nextSib;
2030706f2543Smrg	}
2031706f2543Smrg	else if (IOverlapAnyWindow(pWin, &box))
2032706f2543Smrg	    return NullWindow;
2033706f2543Smrg	else
2034706f2543Smrg	    return pWin->nextSib;
2035706f2543Smrg      case Opposite:
2036706f2543Smrg	if ((!pWin->mapped || (pSib && !pSib->mapped)))
2037706f2543Smrg	    return pWin->nextSib;
2038706f2543Smrg	else if (pSib)
2039706f2543Smrg	{
2040706f2543Smrg	    if (RegionContainsRect(&pSib->borderSize, &box) != rgnOUT)
2041706f2543Smrg	    {
2042706f2543Smrg		if (IsSiblingAboveMe(pWin, pSib) == Above)
2043706f2543Smrg		    return pFirst;
2044706f2543Smrg		else
2045706f2543Smrg		    return NullWindow;
2046706f2543Smrg	    }
2047706f2543Smrg	    else
2048706f2543Smrg		return pWin->nextSib;
2049706f2543Smrg	}
2050706f2543Smrg	else if (AnyWindowOverlapsMe(pWin, pHead, &box))
2051706f2543Smrg	{
2052706f2543Smrg	    /* If I'm occluded, I can't possibly be the first child
2053706f2543Smrg	     * if (pWin == pWin->parent->firstChild)
2054706f2543Smrg	     *	  return pWin->nextSib;
2055706f2543Smrg	     */
2056706f2543Smrg	    return pFirst;
2057706f2543Smrg	}
2058706f2543Smrg	else if (IOverlapAnyWindow(pWin, &box))
2059706f2543Smrg	    return NullWindow;
2060706f2543Smrg	else
2061706f2543Smrg	    return pWin->nextSib;
2062706f2543Smrg      default:
2063706f2543Smrg      {
2064706f2543Smrg	/* should never happen; make something up. */
2065706f2543Smrg	return pWin->nextSib;
2066706f2543Smrg      }
2067706f2543Smrg    }
2068706f2543Smrg}
2069706f2543Smrg
2070706f2543Smrgstatic void
2071706f2543SmrgReflectStackChange(
2072706f2543Smrg    WindowPtr pWin,
2073706f2543Smrg    WindowPtr pSib,
2074706f2543Smrg    VTKind  kind)
2075706f2543Smrg{
2076706f2543Smrg/* Note that pSib might be NULL */
2077706f2543Smrg
2078706f2543Smrg    Bool WasViewable = (Bool)pWin->viewable;
2079706f2543Smrg    Bool anyMarked;
2080706f2543Smrg    WindowPtr pFirstChange;
2081706f2543Smrg    WindowPtr  pLayerWin;
2082706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
2083706f2543Smrg
2084706f2543Smrg    /* if this is a root window, can't be restacked */
2085706f2543Smrg    if (!pWin->parent)
2086706f2543Smrg	return;
2087706f2543Smrg
2088706f2543Smrg    pFirstChange = MoveWindowInStack(pWin, pSib);
2089706f2543Smrg
2090706f2543Smrg    if (WasViewable)
2091706f2543Smrg    {
2092706f2543Smrg	anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange,
2093706f2543Smrg						      &pLayerWin);
2094706f2543Smrg	if (pLayerWin != pWin) pFirstChange = pLayerWin;
2095706f2543Smrg	if (anyMarked)
2096706f2543Smrg	{
2097706f2543Smrg	    (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, kind);
2098706f2543Smrg	    (*pScreen->HandleExposures)(pLayerWin->parent);
2099706f2543Smrg	}
2100706f2543Smrg	if (anyMarked && pWin->drawable.pScreen->PostValidateTree)
2101706f2543Smrg	    (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, kind);
2102706f2543Smrg    }
2103706f2543Smrg    if (pWin->realized)
2104706f2543Smrg	WindowsRestructured ();
2105706f2543Smrg}
2106706f2543Smrg
2107706f2543Smrg/*****
2108706f2543Smrg * ConfigureWindow
2109706f2543Smrg *****/
2110706f2543Smrg
2111706f2543Smrgint
2112706f2543SmrgConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client)
2113706f2543Smrg{
2114706f2543Smrg#define RESTACK_WIN    0
2115706f2543Smrg#define MOVE_WIN       1
2116706f2543Smrg#define RESIZE_WIN     2
2117706f2543Smrg#define REBORDER_WIN   3
2118706f2543Smrg    WindowPtr pSib = NullWindow;
2119706f2543Smrg    WindowPtr pParent = pWin->parent;
2120706f2543Smrg    Window sibwid = 0;
2121706f2543Smrg    Mask index2, tmask;
2122706f2543Smrg    XID *pVlist;
2123706f2543Smrg    short x,   y, beforeX, beforeY;
2124706f2543Smrg    unsigned short w = pWin->drawable.width,
2125706f2543Smrg		   h = pWin->drawable.height,
2126706f2543Smrg		   bw = pWin->borderWidth;
2127706f2543Smrg    int rc, action, smode = Above;
2128706f2543Smrg    xEvent event;
2129706f2543Smrg
2130706f2543Smrg    if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask))
2131706f2543Smrg	return BadMatch;
2132706f2543Smrg
2133706f2543Smrg    if ((mask & CWSibling) && !(mask & CWStackMode))
2134706f2543Smrg	return BadMatch;
2135706f2543Smrg
2136706f2543Smrg    pVlist = vlist;
2137706f2543Smrg
2138706f2543Smrg    if (pParent)
2139706f2543Smrg    {
2140706f2543Smrg	x = pWin->drawable.x - pParent->drawable.x - (int)bw;
2141706f2543Smrg	y = pWin->drawable.y - pParent->drawable.y - (int)bw;
2142706f2543Smrg    }
2143706f2543Smrg    else
2144706f2543Smrg    {
2145706f2543Smrg	x = pWin->drawable.x;
2146706f2543Smrg	y = pWin->drawable.y;
2147706f2543Smrg    }
2148706f2543Smrg    beforeX = x;
2149706f2543Smrg    beforeY = y;
2150706f2543Smrg    action = RESTACK_WIN;
2151706f2543Smrg    if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth))))
2152706f2543Smrg    {
2153706f2543Smrg	GET_INT16(CWX, x);
2154706f2543Smrg	GET_INT16(CWY, y);
2155706f2543Smrg	action = MOVE_WIN;
2156706f2543Smrg    }
2157706f2543Smrg	/* or should be resized */
2158706f2543Smrg    else if (mask & (CWX |  CWY | CWWidth | CWHeight))
2159706f2543Smrg    {
2160706f2543Smrg	GET_INT16(CWX, x);
2161706f2543Smrg	GET_INT16(CWY, y);
2162706f2543Smrg	GET_CARD16(CWWidth, w);
2163706f2543Smrg	GET_CARD16 (CWHeight, h);
2164706f2543Smrg	if (!w || !h)
2165706f2543Smrg	{
2166706f2543Smrg	    client->errorValue = 0;
2167706f2543Smrg	    return BadValue;
2168706f2543Smrg	}
2169706f2543Smrg	action = RESIZE_WIN;
2170706f2543Smrg    }
2171706f2543Smrg    tmask = mask & ~ChangeMask;
2172706f2543Smrg    while (tmask)
2173706f2543Smrg    {
2174706f2543Smrg	index2 = (Mask)lowbit (tmask);
2175706f2543Smrg	tmask &= ~index2;
2176706f2543Smrg	switch (index2)
2177706f2543Smrg	{
2178706f2543Smrg	  case CWBorderWidth:
2179706f2543Smrg	    GET_CARD16(CWBorderWidth, bw);
2180706f2543Smrg	    break;
2181706f2543Smrg	  case CWSibling:
2182706f2543Smrg	    sibwid = (Window ) *pVlist;
2183706f2543Smrg	    pVlist++;
2184706f2543Smrg	    rc = dixLookupWindow(&pSib, sibwid, client, DixGetAttrAccess);
2185706f2543Smrg	    if (rc != Success)
2186706f2543Smrg	    {
2187706f2543Smrg		client->errorValue = sibwid;
2188706f2543Smrg		return rc;
2189706f2543Smrg	    }
2190706f2543Smrg	    if (pSib->parent != pParent)
2191706f2543Smrg		return BadMatch;
2192706f2543Smrg	    if (pSib == pWin)
2193706f2543Smrg		return BadMatch;
2194706f2543Smrg	    break;
2195706f2543Smrg	  case CWStackMode:
2196706f2543Smrg	    GET_CARD8(CWStackMode, smode);
2197706f2543Smrg	    if ((smode != TopIf) && (smode != BottomIf) &&
2198706f2543Smrg		(smode != Opposite) && (smode != Above) && (smode != Below))
2199706f2543Smrg	    {
2200706f2543Smrg		client->errorValue = smode;
2201706f2543Smrg		return BadValue;
2202706f2543Smrg	    }
2203706f2543Smrg	    break;
2204706f2543Smrg	  default:
2205706f2543Smrg	    client->errorValue = mask;
2206706f2543Smrg	    return BadValue;
2207706f2543Smrg	}
2208706f2543Smrg    }
2209706f2543Smrg	/* root really can't be reconfigured, so just return */
2210706f2543Smrg    if (!pParent)
2211706f2543Smrg	return Success;
2212706f2543Smrg
2213706f2543Smrg	/* Figure out if the window should be moved.  Doesnt
2214706f2543Smrg	   make the changes to the window if event sent */
2215706f2543Smrg
2216706f2543Smrg    if (mask & CWStackMode)
2217706f2543Smrg	pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x,
2218706f2543Smrg				    pParent->drawable.y + y,
2219706f2543Smrg				    w + (bw << 1), h + (bw << 1), smode);
2220706f2543Smrg    else
2221706f2543Smrg	pSib = pWin->nextSib;
2222706f2543Smrg
2223706f2543Smrg
2224706f2543Smrg    if ((!pWin->overrideRedirect) &&
2225706f2543Smrg	(RedirectSend(pParent)
2226706f2543Smrg	))
2227706f2543Smrg    {
2228706f2543Smrg	memset(&event, 0, sizeof(xEvent));
2229706f2543Smrg	event.u.u.type = ConfigureRequest;
2230706f2543Smrg	event.u.configureRequest.window = pWin->drawable.id;
2231706f2543Smrg	if (mask & CWSibling)
2232706f2543Smrg	   event.u.configureRequest.sibling = sibwid;
2233706f2543Smrg	else
2234706f2543Smrg	    event.u.configureRequest.sibling = None;
2235706f2543Smrg	if (mask & CWStackMode)
2236706f2543Smrg	   event.u.u.detail = smode;
2237706f2543Smrg	else
2238706f2543Smrg	    event.u.u.detail = Above;
2239706f2543Smrg	event.u.configureRequest.x = x;
2240706f2543Smrg	event.u.configureRequest.y = y;
2241706f2543Smrg#ifdef PANORAMIX
2242706f2543Smrg	if(!noPanoramiXExtension && (!pParent || !pParent->parent)) {
2243706f2543Smrg            event.u.configureRequest.x += screenInfo.screens[0]->x;
2244706f2543Smrg            event.u.configureRequest.y += screenInfo.screens[0]->y;
2245706f2543Smrg	}
2246706f2543Smrg#endif
2247706f2543Smrg	event.u.configureRequest.width = w;
2248706f2543Smrg	event.u.configureRequest.height = h;
2249706f2543Smrg	event.u.configureRequest.borderWidth = bw;
2250706f2543Smrg	event.u.configureRequest.valueMask = mask;
2251706f2543Smrg	event.u.configureRequest.parent = pParent->drawable.id;
2252706f2543Smrg	if (MaybeDeliverEventsToClient(pParent, &event, 1,
2253706f2543Smrg		SubstructureRedirectMask, client) == 1)
2254706f2543Smrg	    return Success;
2255706f2543Smrg    }
2256706f2543Smrg    if (action == RESIZE_WIN)
2257706f2543Smrg    {
2258706f2543Smrg	Bool size_change = (w != pWin->drawable.width)
2259706f2543Smrg			|| (h != pWin->drawable.height);
2260706f2543Smrg	if (size_change && ((pWin->eventMask|wOtherEventMasks(pWin)) & ResizeRedirectMask))
2261706f2543Smrg	{
2262706f2543Smrg	    xEvent eventT;
2263706f2543Smrg	    memset(&eventT, 0, sizeof(xEvent));
2264706f2543Smrg	    eventT.u.u.type = ResizeRequest;
2265706f2543Smrg	    eventT.u.resizeRequest.window = pWin->drawable.id;
2266706f2543Smrg	    eventT.u.resizeRequest.width = w;
2267706f2543Smrg	    eventT.u.resizeRequest.height = h;
2268706f2543Smrg	    if (MaybeDeliverEventsToClient(pWin, &eventT, 1,
2269706f2543Smrg				       ResizeRedirectMask, client) == 1)
2270706f2543Smrg	    {
2271706f2543Smrg		/* if event is delivered, leave the actual size alone. */
2272706f2543Smrg		w = pWin->drawable.width;
2273706f2543Smrg		h = pWin->drawable.height;
2274706f2543Smrg		size_change = FALSE;
2275706f2543Smrg	    }
2276706f2543Smrg	}
2277706f2543Smrg	if (!size_change)
2278706f2543Smrg	{
2279706f2543Smrg	    if (mask & (CWX | CWY))
2280706f2543Smrg		action = MOVE_WIN;
2281706f2543Smrg	    else if (mask & (CWStackMode | CWBorderWidth))
2282706f2543Smrg		action = RESTACK_WIN;
2283706f2543Smrg	    else   /* really nothing to do */
2284706f2543Smrg		return(Success) ;
2285706f2543Smrg	}
2286706f2543Smrg    }
2287706f2543Smrg
2288706f2543Smrg    if (action == RESIZE_WIN)
2289706f2543Smrg	    /* we've already checked whether there's really a size change */
2290706f2543Smrg	    goto ActuallyDoSomething;
2291706f2543Smrg    if ((mask & CWX) && (x != beforeX))
2292706f2543Smrg	    goto ActuallyDoSomething;
2293706f2543Smrg    if ((mask & CWY) && (y != beforeY))
2294706f2543Smrg	    goto ActuallyDoSomething;
2295706f2543Smrg    if ((mask & CWBorderWidth) && (bw != wBorderWidth (pWin)))
2296706f2543Smrg	    goto ActuallyDoSomething;
2297706f2543Smrg    if (mask & CWStackMode)
2298706f2543Smrg    {
2299706f2543Smrg#ifndef ROOTLESS
2300706f2543Smrg        /* See above for why we always reorder in rootless mode. */
2301706f2543Smrg	if (pWin->nextSib != pSib)
2302706f2543Smrg#endif
2303706f2543Smrg	    goto ActuallyDoSomething;
2304706f2543Smrg    }
2305706f2543Smrg    return Success;
2306706f2543Smrg
2307706f2543SmrgActuallyDoSomething:
2308706f2543Smrg    if (pWin->drawable.pScreen->ConfigNotify)
2309706f2543Smrg    {
2310706f2543Smrg	int ret;
2311706f2543Smrg	ret = (*pWin->drawable.pScreen->ConfigNotify)(pWin, x, y, w, h, bw, pSib);
2312706f2543Smrg	if (ret) {
2313706f2543Smrg	    client->errorValue = 0;
2314706f2543Smrg	    return ret;
2315706f2543Smrg	}
2316706f2543Smrg    }
2317706f2543Smrg
2318706f2543Smrg    if (SubStrSend(pWin, pParent))
2319706f2543Smrg    {
2320706f2543Smrg	memset(&event, 0, sizeof(xEvent));
2321706f2543Smrg	event.u.u.type = ConfigureNotify;
2322706f2543Smrg	event.u.configureNotify.window = pWin->drawable.id;
2323706f2543Smrg	if (pSib)
2324706f2543Smrg	    event.u.configureNotify.aboveSibling = pSib->drawable.id;
2325706f2543Smrg	else
2326706f2543Smrg	    event.u.configureNotify.aboveSibling = None;
2327706f2543Smrg	event.u.configureNotify.x = x;
2328706f2543Smrg	event.u.configureNotify.y = y;
2329706f2543Smrg#ifdef PANORAMIX
2330706f2543Smrg	if(!noPanoramiXExtension && (!pParent || !pParent->parent)) {
2331706f2543Smrg	    event.u.configureNotify.x += screenInfo.screens[0]->x;
2332706f2543Smrg	    event.u.configureNotify.y += screenInfo.screens[0]->y;
2333706f2543Smrg	}
2334706f2543Smrg#endif
2335706f2543Smrg	event.u.configureNotify.width = w;
2336706f2543Smrg	event.u.configureNotify.height = h;
2337706f2543Smrg	event.u.configureNotify.borderWidth = bw;
2338706f2543Smrg	event.u.configureNotify.override = pWin->overrideRedirect;
2339706f2543Smrg	DeliverEvents(pWin, &event, 1, NullWindow);
2340706f2543Smrg    }
2341706f2543Smrg    if (mask & CWBorderWidth)
2342706f2543Smrg    {
2343706f2543Smrg	if (action == RESTACK_WIN)
2344706f2543Smrg	{
2345706f2543Smrg	    action = MOVE_WIN;
2346706f2543Smrg	    pWin->borderWidth = bw;
2347706f2543Smrg	}
2348706f2543Smrg	else if ((action == MOVE_WIN) &&
2349706f2543Smrg		 (beforeX + wBorderWidth (pWin) == x + (int)bw) &&
2350706f2543Smrg		 (beforeY + wBorderWidth (pWin) == y + (int)bw))
2351706f2543Smrg	{
2352706f2543Smrg	    action = REBORDER_WIN;
2353706f2543Smrg	    (*pWin->drawable.pScreen->ChangeBorderWidth)(pWin, bw);
2354706f2543Smrg	}
2355706f2543Smrg	else
2356706f2543Smrg	    pWin->borderWidth = bw;
2357706f2543Smrg    }
2358706f2543Smrg    if (action == MOVE_WIN)
2359706f2543Smrg	(*pWin->drawable.pScreen->MoveWindow)(pWin, x, y, pSib,
2360706f2543Smrg		   (mask & CWBorderWidth) ? VTOther : VTMove);
2361706f2543Smrg    else if (action == RESIZE_WIN)
2362706f2543Smrg	(*pWin->drawable.pScreen->ResizeWindow)(pWin, x, y, w, h, pSib);
2363706f2543Smrg    else if (mask & CWStackMode)
2364706f2543Smrg	ReflectStackChange(pWin, pSib, VTOther);
2365706f2543Smrg
2366706f2543Smrg    if (action != RESTACK_WIN)
2367706f2543Smrg	CheckCursorConfinement(pWin);
2368706f2543Smrg    return Success;
2369706f2543Smrg#undef RESTACK_WIN
2370706f2543Smrg#undef MOVE_WIN
2371706f2543Smrg#undef RESIZE_WIN
2372706f2543Smrg#undef REBORDER_WIN
2373706f2543Smrg}
2374706f2543Smrg
2375706f2543Smrg
2376706f2543Smrg/******
2377706f2543Smrg *
2378706f2543Smrg * CirculateWindow
2379706f2543Smrg *    For RaiseLowest, raises the lowest mapped child (if any) that is
2380706f2543Smrg *    obscured by another child to the top of the stack.  For LowerHighest,
2381706f2543Smrg *    lowers the highest mapped child (if any) that is obscuring another
2382706f2543Smrg *    child to the bottom of the stack.	 Exposure processing is performed
2383706f2543Smrg *
2384706f2543Smrg ******/
2385706f2543Smrg
2386706f2543Smrgint
2387706f2543SmrgCirculateWindow(WindowPtr pParent, int direction, ClientPtr client)
2388706f2543Smrg{
2389706f2543Smrg    WindowPtr pWin, pHead, pFirst;
2390706f2543Smrg    xEvent event;
2391706f2543Smrg    BoxRec box;
2392706f2543Smrg
2393706f2543Smrg    pHead = RealChildHead(pParent);
2394706f2543Smrg    pFirst = pHead ? pHead->nextSib : pParent->firstChild;
2395706f2543Smrg    if (direction == RaiseLowest)
2396706f2543Smrg    {
2397706f2543Smrg	for (pWin = pParent->lastChild;
2398706f2543Smrg	     (pWin != pHead) &&
2399706f2543Smrg	     !(pWin->mapped &&
2400706f2543Smrg	       AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box)));
2401706f2543Smrg	     pWin = pWin->prevSib) ;
2402706f2543Smrg	if (pWin == pHead)
2403706f2543Smrg	    return Success;
2404706f2543Smrg    }
2405706f2543Smrg    else
2406706f2543Smrg    {
2407706f2543Smrg	for (pWin = pFirst;
2408706f2543Smrg	     pWin &&
2409706f2543Smrg	     !(pWin->mapped &&
2410706f2543Smrg	       IOverlapAnyWindow(pWin, WindowExtents(pWin, &box)));
2411706f2543Smrg	     pWin = pWin->nextSib) ;
2412706f2543Smrg	if (!pWin)
2413706f2543Smrg	    return Success;
2414706f2543Smrg    }
2415706f2543Smrg
2416706f2543Smrg    event.u.circulate.window = pWin->drawable.id;
2417706f2543Smrg    event.u.circulate.parent = pParent->drawable.id;
2418706f2543Smrg    event.u.circulate.event = pParent->drawable.id;
2419706f2543Smrg    if (direction == RaiseLowest)
2420706f2543Smrg	event.u.circulate.place = PlaceOnTop;
2421706f2543Smrg    else
2422706f2543Smrg	event.u.circulate.place = PlaceOnBottom;
2423706f2543Smrg
2424706f2543Smrg    if (RedirectSend(pParent))
2425706f2543Smrg    {
2426706f2543Smrg	event.u.u.type = CirculateRequest;
2427706f2543Smrg	if (MaybeDeliverEventsToClient(pParent, &event, 1,
2428706f2543Smrg		SubstructureRedirectMask, client) == 1)
2429706f2543Smrg	    return Success;
2430706f2543Smrg    }
2431706f2543Smrg
2432706f2543Smrg    event.u.u.type = CirculateNotify;
2433706f2543Smrg    DeliverEvents(pWin, &event, 1, NullWindow);
2434706f2543Smrg    ReflectStackChange(pWin,
2435706f2543Smrg		       (direction == RaiseLowest) ? pFirst : NullWindow,
2436706f2543Smrg		       VTStack);
2437706f2543Smrg
2438706f2543Smrg    return Success;
2439706f2543Smrg}
2440706f2543Smrg
2441706f2543Smrgstatic int
2442706f2543SmrgCompareWIDs(
2443706f2543Smrg    WindowPtr pWin,
2444706f2543Smrg    pointer   value) /* must conform to VisitWindowProcPtr */
2445706f2543Smrg{
2446706f2543Smrg    Window *wid = (Window *)value;
2447706f2543Smrg
2448706f2543Smrg    if (pWin->drawable.id == *wid)
2449706f2543Smrg       return WT_STOPWALKING;
2450706f2543Smrg    else
2451706f2543Smrg       return WT_WALKCHILDREN;
2452706f2543Smrg}
2453706f2543Smrg
2454706f2543Smrg/*****
2455706f2543Smrg *  ReparentWindow
2456706f2543Smrg *****/
2457706f2543Smrg
2458706f2543Smrgint
2459706f2543SmrgReparentWindow(WindowPtr pWin, WindowPtr pParent,
2460706f2543Smrg               int x, int y, ClientPtr client)
2461706f2543Smrg{
2462706f2543Smrg    WindowPtr pPrev, pPriorParent;
2463706f2543Smrg    Bool WasMapped = (Bool)(pWin->mapped);
2464706f2543Smrg    xEvent event;
2465706f2543Smrg    int bw = wBorderWidth (pWin);
2466706f2543Smrg    ScreenPtr pScreen;
2467706f2543Smrg
2468706f2543Smrg    pScreen = pWin->drawable.pScreen;
2469706f2543Smrg    if (TraverseTree(pWin, CompareWIDs, (pointer)&pParent->drawable.id) == WT_STOPWALKING)
2470706f2543Smrg	return BadMatch;
2471706f2543Smrg    if (!MakeWindowOptional(pWin))
2472706f2543Smrg	return BadAlloc;
2473706f2543Smrg
2474706f2543Smrg    if (WasMapped)
2475706f2543Smrg       UnmapWindow(pWin, FALSE);
2476706f2543Smrg
2477706f2543Smrg    memset(&event, 0, sizeof(xEvent));
2478706f2543Smrg    event.u.u.type = ReparentNotify;
2479706f2543Smrg    event.u.reparent.window = pWin->drawable.id;
2480706f2543Smrg    event.u.reparent.parent = pParent->drawable.id;
2481706f2543Smrg    event.u.reparent.x = x;
2482706f2543Smrg    event.u.reparent.y = y;
2483706f2543Smrg#ifdef PANORAMIX
2484706f2543Smrg    if(!noPanoramiXExtension && !pParent->parent) {
2485706f2543Smrg	event.u.reparent.x += screenInfo.screens[0]->x;
2486706f2543Smrg	event.u.reparent.y += screenInfo.screens[0]->y;
2487706f2543Smrg    }
2488706f2543Smrg#endif
2489706f2543Smrg    event.u.reparent.override = pWin->overrideRedirect;
2490706f2543Smrg    DeliverEvents(pWin, &event, 1, pParent);
2491706f2543Smrg
2492706f2543Smrg    /* take out of sibling chain */
2493706f2543Smrg
2494706f2543Smrg    pPriorParent = pPrev = pWin->parent;
2495706f2543Smrg    if (pPrev->firstChild == pWin)
2496706f2543Smrg	pPrev->firstChild = pWin->nextSib;
2497706f2543Smrg    if (pPrev->lastChild == pWin)
2498706f2543Smrg	pPrev->lastChild = pWin->prevSib;
2499706f2543Smrg
2500706f2543Smrg    if (pWin->nextSib)
2501706f2543Smrg	pWin->nextSib->prevSib = pWin->prevSib;
2502706f2543Smrg    if (pWin->prevSib)
2503706f2543Smrg	pWin->prevSib->nextSib = pWin->nextSib;
2504706f2543Smrg
2505706f2543Smrg    /* insert at begining of pParent */
2506706f2543Smrg    pWin->parent = pParent;
2507706f2543Smrg    pPrev = RealChildHead(pParent);
2508706f2543Smrg    if (pPrev)
2509706f2543Smrg    {
2510706f2543Smrg	pWin->nextSib = pPrev->nextSib;
2511706f2543Smrg	if (pPrev->nextSib)
2512706f2543Smrg	    pPrev->nextSib->prevSib = pWin;
2513706f2543Smrg	else
2514706f2543Smrg	    pParent->lastChild = pWin;
2515706f2543Smrg	pPrev->nextSib = pWin;
2516706f2543Smrg	pWin->prevSib = pPrev;
2517706f2543Smrg    }
2518706f2543Smrg    else
2519706f2543Smrg    {
2520706f2543Smrg	pWin->nextSib = pParent->firstChild;
2521706f2543Smrg	pWin->prevSib = NullWindow;
2522706f2543Smrg	if (pParent->firstChild)
2523706f2543Smrg	    pParent->firstChild->prevSib = pWin;
2524706f2543Smrg	else
2525706f2543Smrg	    pParent->lastChild = pWin;
2526706f2543Smrg	pParent->firstChild = pWin;
2527706f2543Smrg    }
2528706f2543Smrg
2529706f2543Smrg    pWin->origin.x = x + bw;
2530706f2543Smrg    pWin->origin.y = y + bw;
2531706f2543Smrg    pWin->drawable.x = x + bw + pParent->drawable.x;
2532706f2543Smrg    pWin->drawable.y = y + bw + pParent->drawable.y;
2533706f2543Smrg
2534706f2543Smrg    /* clip to parent */
2535706f2543Smrg    SetWinSize (pWin);
2536706f2543Smrg    SetBorderSize (pWin);
2537706f2543Smrg
2538706f2543Smrg    if (pScreen->ReparentWindow)
2539706f2543Smrg	(*pScreen->ReparentWindow)(pWin, pPriorParent);
2540706f2543Smrg    (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y);
2541706f2543Smrg    ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
2542706f2543Smrg
2543706f2543Smrg    CheckWindowOptionalNeed(pWin);
2544706f2543Smrg
2545706f2543Smrg    if (WasMapped)
2546706f2543Smrg	MapWindow(pWin, client);
2547706f2543Smrg    RecalculateDeliverableEvents(pWin);
2548706f2543Smrg    return Success;
2549706f2543Smrg}
2550706f2543Smrg
2551706f2543Smrgstatic void
2552706f2543SmrgRealizeTree(WindowPtr pWin)
2553706f2543Smrg{
2554706f2543Smrg    WindowPtr pChild;
2555706f2543Smrg    RealizeWindowProcPtr Realize;
2556706f2543Smrg
2557706f2543Smrg    Realize = pWin->drawable.pScreen->RealizeWindow;
2558706f2543Smrg    pChild = pWin;
2559706f2543Smrg    while (1)
2560706f2543Smrg    {
2561706f2543Smrg	if (pChild->mapped)
2562706f2543Smrg	{
2563706f2543Smrg	    pChild->realized = TRUE;
2564706f2543Smrg	    pChild->viewable = (pChild->drawable.class == InputOutput);
2565706f2543Smrg	    (* Realize)(pChild);
2566706f2543Smrg	    if (pChild->firstChild)
2567706f2543Smrg	    {
2568706f2543Smrg		pChild = pChild->firstChild;
2569706f2543Smrg		continue;
2570706f2543Smrg	    }
2571706f2543Smrg	}
2572706f2543Smrg	while (!pChild->nextSib && (pChild != pWin))
2573706f2543Smrg	    pChild = pChild->parent;
2574706f2543Smrg	if (pChild == pWin)
2575706f2543Smrg	    return;
2576706f2543Smrg	pChild = pChild->nextSib;
2577706f2543Smrg    }
2578706f2543Smrg}
2579706f2543Smrg
2580706f2543Smrgstatic WindowPtr windowDisableMapUnmapEvents;
2581706f2543Smrg
2582706f2543Smrgvoid
2583706f2543SmrgDisableMapUnmapEvents(WindowPtr pWin)
2584706f2543Smrg{
2585706f2543Smrg    assert (windowDisableMapUnmapEvents == NULL);
2586706f2543Smrg
2587706f2543Smrg    windowDisableMapUnmapEvents = pWin;
2588706f2543Smrg}
2589706f2543Smrg
2590706f2543Smrgvoid
2591706f2543SmrgEnableMapUnmapEvents(WindowPtr pWin)
2592706f2543Smrg{
2593706f2543Smrg    assert (windowDisableMapUnmapEvents != NULL);
2594706f2543Smrg
2595706f2543Smrg    windowDisableMapUnmapEvents = NULL;
2596706f2543Smrg}
2597706f2543Smrg
2598706f2543Smrgstatic Bool
2599706f2543SmrgMapUnmapEventsEnabled(WindowPtr pWin)
2600706f2543Smrg{
2601706f2543Smrg    return pWin != windowDisableMapUnmapEvents;
2602706f2543Smrg}
2603706f2543Smrg
2604706f2543Smrg/*****
2605706f2543Smrg * MapWindow
2606706f2543Smrg *    If some other client has selected SubStructureReDirect on the parent
2607706f2543Smrg *    and override-redirect is xFalse, then a MapRequest event is generated,
2608706f2543Smrg *    but the window remains unmapped.	Otherwise, the window is mapped and a
2609706f2543Smrg *    MapNotify event is generated.
2610706f2543Smrg *****/
2611706f2543Smrg
2612706f2543Smrgint
2613706f2543SmrgMapWindow(WindowPtr pWin, ClientPtr client)
2614706f2543Smrg{
2615706f2543Smrg    ScreenPtr pScreen;
2616706f2543Smrg
2617706f2543Smrg    WindowPtr pParent;
2618706f2543Smrg    WindowPtr  pLayerWin;
2619706f2543Smrg
2620706f2543Smrg    if (pWin->mapped)
2621706f2543Smrg	return Success;
2622706f2543Smrg
2623706f2543Smrg    /*  general check for permission to map window */
2624706f2543Smrg    if (XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id, RT_WINDOW,
2625706f2543Smrg		 pWin, RT_NONE, NULL, DixShowAccess) != Success)
2626706f2543Smrg	return Success;
2627706f2543Smrg
2628706f2543Smrg    pScreen = pWin->drawable.pScreen;
2629706f2543Smrg    if ( (pParent = pWin->parent) )
2630706f2543Smrg    {
2631706f2543Smrg	xEvent event;
2632706f2543Smrg	Bool anyMarked;
2633706f2543Smrg
2634706f2543Smrg	if ((!pWin->overrideRedirect) &&
2635706f2543Smrg	    (RedirectSend(pParent)
2636706f2543Smrg	))
2637706f2543Smrg	{
2638706f2543Smrg	    memset(&event, 0, sizeof(xEvent));
2639706f2543Smrg	    event.u.u.type = MapRequest;
2640706f2543Smrg	    event.u.mapRequest.window = pWin->drawable.id;
2641706f2543Smrg	    event.u.mapRequest.parent = pParent->drawable.id;
2642706f2543Smrg
2643706f2543Smrg	    if (MaybeDeliverEventsToClient(pParent, &event, 1,
2644706f2543Smrg		SubstructureRedirectMask, client) == 1)
2645706f2543Smrg		return Success;
2646706f2543Smrg	}
2647706f2543Smrg
2648706f2543Smrg	pWin->mapped = TRUE;
2649706f2543Smrg	if (SubStrSend(pWin, pParent) && MapUnmapEventsEnabled(pWin))
2650706f2543Smrg	{
2651706f2543Smrg	    memset(&event, 0, sizeof(xEvent));
2652706f2543Smrg	    event.u.u.type = MapNotify;
2653706f2543Smrg	    event.u.mapNotify.window = pWin->drawable.id;
2654706f2543Smrg	    event.u.mapNotify.override = pWin->overrideRedirect;
2655706f2543Smrg	    DeliverEvents(pWin, &event, 1, NullWindow);
2656706f2543Smrg	}
2657706f2543Smrg
2658706f2543Smrg	if (!pParent->realized)
2659706f2543Smrg	    return Success;
2660706f2543Smrg	RealizeTree(pWin);
2661706f2543Smrg	if (pWin->viewable)
2662706f2543Smrg	{
2663706f2543Smrg	    anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
2664706f2543Smrg							  &pLayerWin);
2665706f2543Smrg	    if (anyMarked)
2666706f2543Smrg	    {
2667706f2543Smrg		(*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTMap);
2668706f2543Smrg		(*pScreen->HandleExposures)(pLayerWin->parent);
2669706f2543Smrg	    }
2670706f2543Smrg	if (anyMarked && pScreen->PostValidateTree)
2671706f2543Smrg	    (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTMap);
2672706f2543Smrg	}
2673706f2543Smrg	WindowsRestructured ();
2674706f2543Smrg    }
2675706f2543Smrg    else
2676706f2543Smrg    {
2677706f2543Smrg	RegionRec   temp;
2678706f2543Smrg
2679706f2543Smrg	pWin->mapped = TRUE;
2680706f2543Smrg	pWin->realized = TRUE;	   /* for roots */
2681706f2543Smrg	pWin->viewable = pWin->drawable.class == InputOutput;
2682706f2543Smrg	/* We SHOULD check for an error value here XXX */
2683706f2543Smrg	(*pScreen->RealizeWindow)(pWin);
2684706f2543Smrg	if (pScreen->ClipNotify)
2685706f2543Smrg	    (*pScreen->ClipNotify) (pWin, 0, 0);
2686706f2543Smrg	if (pScreen->PostValidateTree)
2687706f2543Smrg	    (*pScreen->PostValidateTree)(NullWindow, pWin, VTMap);
2688706f2543Smrg	RegionNull(&temp);
2689706f2543Smrg	RegionCopy(&temp, &pWin->clipList);
2690706f2543Smrg	(*pScreen->WindowExposures) (pWin, &temp, NullRegion);
2691706f2543Smrg	RegionUninit(&temp);
2692706f2543Smrg    }
2693706f2543Smrg
2694706f2543Smrg    return Success;
2695706f2543Smrg}
2696706f2543Smrg
2697706f2543Smrg
2698706f2543Smrg/*****
2699706f2543Smrg * MapSubwindows
2700706f2543Smrg *    Performs a MapWindow all unmapped children of the window, in top
2701706f2543Smrg *    to bottom stacking order.
2702706f2543Smrg *****/
2703706f2543Smrg
2704706f2543Smrgvoid
2705706f2543SmrgMapSubwindows(WindowPtr pParent, ClientPtr client)
2706706f2543Smrg{
2707706f2543Smrg    WindowPtr	pWin;
2708706f2543Smrg    WindowPtr	pFirstMapped = NullWindow;
2709706f2543Smrg    ScreenPtr	pScreen;
2710706f2543Smrg    Mask	parentRedirect;
2711706f2543Smrg    Mask	parentNotify;
2712706f2543Smrg    xEvent	event;
2713706f2543Smrg    Bool	anyMarked;
2714706f2543Smrg    WindowPtr		pLayerWin;
2715706f2543Smrg
2716706f2543Smrg    pScreen = pParent->drawable.pScreen;
2717706f2543Smrg    parentRedirect = RedirectSend(pParent);
2718706f2543Smrg    parentNotify = SubSend(pParent);
2719706f2543Smrg    anyMarked = FALSE;
2720706f2543Smrg    for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib)
2721706f2543Smrg    {
2722706f2543Smrg	if (!pWin->mapped)
2723706f2543Smrg	{
2724706f2543Smrg	    if (parentRedirect && !pWin->overrideRedirect)
2725706f2543Smrg	    {
2726706f2543Smrg		memset(&event, 0, sizeof(xEvent));
2727706f2543Smrg		event.u.u.type = MapRequest;
2728706f2543Smrg		event.u.mapRequest.window = pWin->drawable.id;
2729706f2543Smrg		event.u.mapRequest.parent = pParent->drawable.id;
2730706f2543Smrg
2731706f2543Smrg		if (MaybeDeliverEventsToClient(pParent, &event, 1,
2732706f2543Smrg		    SubstructureRedirectMask, client) == 1)
2733706f2543Smrg		    continue;
2734706f2543Smrg	    }
2735706f2543Smrg
2736706f2543Smrg	    pWin->mapped = TRUE;
2737706f2543Smrg	    if (parentNotify || StrSend(pWin))
2738706f2543Smrg	    {
2739706f2543Smrg		memset(&event, 0, sizeof(xEvent));
2740706f2543Smrg		event.u.u.type = MapNotify;
2741706f2543Smrg		event.u.mapNotify.window = pWin->drawable.id;
2742706f2543Smrg		event.u.mapNotify.override = pWin->overrideRedirect;
2743706f2543Smrg		DeliverEvents(pWin, &event, 1, NullWindow);
2744706f2543Smrg	    }
2745706f2543Smrg
2746706f2543Smrg	    if (!pFirstMapped)
2747706f2543Smrg		pFirstMapped = pWin;
2748706f2543Smrg	    if (pParent->realized)
2749706f2543Smrg	    {
2750706f2543Smrg		RealizeTree(pWin);
2751706f2543Smrg		if (pWin->viewable)
2752706f2543Smrg		{
2753706f2543Smrg		    anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin,
2754706f2543Smrg							(WindowPtr *)NULL);
2755706f2543Smrg		}
2756706f2543Smrg	    }
2757706f2543Smrg	}
2758706f2543Smrg    }
2759706f2543Smrg
2760706f2543Smrg    if (pFirstMapped)
2761706f2543Smrg    {
2762706f2543Smrg	pLayerWin = (*pScreen->GetLayerWindow)(pParent);
2763706f2543Smrg	if (pLayerWin->parent != pParent) {
2764706f2543Smrg	    anyMarked |= (*pScreen->MarkOverlappedWindows)(pLayerWin,
2765706f2543Smrg							   pLayerWin,
2766706f2543Smrg							   (WindowPtr *)NULL);
2767706f2543Smrg	    pFirstMapped = pLayerWin;
2768706f2543Smrg	}
2769706f2543Smrg        if (anyMarked)
2770706f2543Smrg        {
2771706f2543Smrg	    (*pScreen->ValidateTree)(pLayerWin->parent, pFirstMapped, VTMap);
2772706f2543Smrg	    (*pScreen->HandleExposures)(pLayerWin->parent);
2773706f2543Smrg	}
2774706f2543Smrg        if (anyMarked && pScreen->PostValidateTree)
2775706f2543Smrg	    (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstMapped,
2776706f2543Smrg					 VTMap);
2777706f2543Smrg        WindowsRestructured ();
2778706f2543Smrg    }
2779706f2543Smrg}
2780706f2543Smrg
2781706f2543Smrgstatic void
2782706f2543SmrgUnrealizeTree(
2783706f2543Smrg    WindowPtr pWin,
2784706f2543Smrg    Bool fromConfigure)
2785706f2543Smrg{
2786706f2543Smrg    WindowPtr pChild;
2787706f2543Smrg    UnrealizeWindowProcPtr Unrealize;
2788706f2543Smrg    MarkUnrealizedWindowProcPtr MarkUnrealizedWindow;
2789706f2543Smrg
2790706f2543Smrg    Unrealize = pWin->drawable.pScreen->UnrealizeWindow;
2791706f2543Smrg    MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow;
2792706f2543Smrg    pChild = pWin;
2793706f2543Smrg    while (1)
2794706f2543Smrg    {
2795706f2543Smrg	if (pChild->realized)
2796706f2543Smrg	{
2797706f2543Smrg	    pChild->realized = FALSE;
2798706f2543Smrg	    pChild->visibility = VisibilityNotViewable;
2799706f2543Smrg#ifdef PANORAMIX
2800706f2543Smrg	    if(!noPanoramiXExtension && !pChild->drawable.pScreen->myNum) {
2801706f2543Smrg		PanoramiXRes *win;
2802706f2543Smrg		int rc = dixLookupResourceByType((pointer *)&win,
2803706f2543Smrg					     pChild->drawable.id, XRT_WINDOW,
2804706f2543Smrg					     serverClient, DixWriteAccess);
2805706f2543Smrg		if (rc == Success)
2806706f2543Smrg		   win->u.win.visibility = VisibilityNotViewable;
2807706f2543Smrg	    }
2808706f2543Smrg#endif
2809706f2543Smrg	    (* Unrealize)(pChild);
2810706f2543Smrg	    if (MapUnmapEventsEnabled(pWin))
2811706f2543Smrg		DeleteWindowFromAnyEvents(pChild, FALSE);
2812706f2543Smrg	    if (pChild->viewable)
2813706f2543Smrg	    {
2814706f2543Smrg		pChild->viewable = FALSE;
2815706f2543Smrg		(* MarkUnrealizedWindow)(pChild, pWin, fromConfigure);
2816706f2543Smrg		pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
2817706f2543Smrg	    }
2818706f2543Smrg	    if (pChild->firstChild)
2819706f2543Smrg	    {
2820706f2543Smrg		pChild = pChild->firstChild;
2821706f2543Smrg		continue;
2822706f2543Smrg	    }
2823706f2543Smrg	}
2824706f2543Smrg	while (!pChild->nextSib && (pChild != pWin))
2825706f2543Smrg	    pChild = pChild->parent;
2826706f2543Smrg	if (pChild == pWin)
2827706f2543Smrg	    return;
2828706f2543Smrg	pChild = pChild->nextSib;
2829706f2543Smrg    }
2830706f2543Smrg}
2831706f2543Smrg
2832706f2543Smrg/*****
2833706f2543Smrg * UnmapWindow
2834706f2543Smrg *    If the window is already unmapped, this request has no effect.
2835706f2543Smrg *    Otherwise, the window is unmapped and an UnMapNotify event is
2836706f2543Smrg *    generated.  Cannot unmap a root window.
2837706f2543Smrg *****/
2838706f2543Smrg
2839706f2543Smrgint
2840706f2543SmrgUnmapWindow(WindowPtr pWin, Bool fromConfigure)
2841706f2543Smrg{
2842706f2543Smrg    WindowPtr pParent;
2843706f2543Smrg    xEvent event;
2844706f2543Smrg    Bool wasRealized = (Bool)pWin->realized;
2845706f2543Smrg    Bool wasViewable = (Bool)pWin->viewable;
2846706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
2847706f2543Smrg    WindowPtr pLayerWin = pWin;
2848706f2543Smrg
2849706f2543Smrg    if ((!pWin->mapped) || (!(pParent = pWin->parent)))
2850706f2543Smrg	return Success;
2851706f2543Smrg    if (SubStrSend(pWin, pParent) && MapUnmapEventsEnabled(pWin))
2852706f2543Smrg    {
2853706f2543Smrg	memset(&event, 0, sizeof(xEvent));
2854706f2543Smrg	event.u.u.type = UnmapNotify;
2855706f2543Smrg	event.u.unmapNotify.window = pWin->drawable.id;
2856706f2543Smrg	event.u.unmapNotify.fromConfigure = fromConfigure;
2857706f2543Smrg	DeliverEvents(pWin, &event, 1, NullWindow);
2858706f2543Smrg    }
2859706f2543Smrg    if (wasViewable && !fromConfigure)
2860706f2543Smrg    {
2861706f2543Smrg	pWin->valdata = UnmapValData;
2862706f2543Smrg	(*pScreen->MarkOverlappedWindows)(pWin, pWin->nextSib, &pLayerWin);
2863706f2543Smrg	(*pScreen->MarkWindow)(pLayerWin->parent);
2864706f2543Smrg    }
2865706f2543Smrg    pWin->mapped = FALSE;
2866706f2543Smrg    if (wasRealized)
2867706f2543Smrg	UnrealizeTree(pWin, fromConfigure);
2868706f2543Smrg    if (wasViewable)
2869706f2543Smrg    {
2870706f2543Smrg	if (!fromConfigure)
2871706f2543Smrg	{
2872706f2543Smrg	    (*pScreen->ValidateTree)(pLayerWin->parent, pWin, VTUnmap);
2873706f2543Smrg	    (*pScreen->HandleExposures)(pLayerWin->parent);
2874706f2543Smrg	}
2875706f2543Smrg	if (!fromConfigure && pScreen->PostValidateTree)
2876706f2543Smrg	    (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap);
2877706f2543Smrg    }
2878706f2543Smrg    if (wasRealized && !fromConfigure)
2879706f2543Smrg	WindowsRestructured ();
2880706f2543Smrg    return Success;
2881706f2543Smrg}
2882706f2543Smrg
2883706f2543Smrg/*****
2884706f2543Smrg * UnmapSubwindows
2885706f2543Smrg *    Performs an UnmapWindow request with the specified mode on all mapped
2886706f2543Smrg *    children of the window, in bottom to top stacking order.
2887706f2543Smrg *****/
2888706f2543Smrg
2889706f2543Smrgvoid
2890706f2543SmrgUnmapSubwindows(WindowPtr pWin)
2891706f2543Smrg{
2892706f2543Smrg    WindowPtr pChild, pHead;
2893706f2543Smrg    xEvent event;
2894706f2543Smrg    Bool wasRealized = (Bool)pWin->realized;
2895706f2543Smrg    Bool wasViewable = (Bool)pWin->viewable;
2896706f2543Smrg    Bool anyMarked = FALSE;
2897706f2543Smrg    Mask parentNotify;
2898706f2543Smrg    WindowPtr pLayerWin = NULL;
2899706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
2900706f2543Smrg
2901706f2543Smrg    if (!pWin->firstChild)
2902706f2543Smrg	return;
2903706f2543Smrg    parentNotify = SubSend(pWin);
2904706f2543Smrg    pHead = RealChildHead(pWin);
2905706f2543Smrg
2906706f2543Smrg    if (wasViewable)
2907706f2543Smrg	pLayerWin = (*pScreen->GetLayerWindow)(pWin);
2908706f2543Smrg
2909706f2543Smrg    for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
2910706f2543Smrg    {
2911706f2543Smrg	if (pChild->mapped)
2912706f2543Smrg	{
2913706f2543Smrg	    if (parentNotify || StrSend(pChild))
2914706f2543Smrg	    {
2915706f2543Smrg		event.u.u.type = UnmapNotify;
2916706f2543Smrg		event.u.unmapNotify.window = pChild->drawable.id;
2917706f2543Smrg		event.u.unmapNotify.fromConfigure = xFalse;
2918706f2543Smrg		DeliverEvents(pChild, &event, 1, NullWindow);
2919706f2543Smrg	    }
2920706f2543Smrg	    if (pChild->viewable)
2921706f2543Smrg	    {
2922706f2543Smrg		pChild->valdata = UnmapValData;
2923706f2543Smrg		anyMarked = TRUE;
2924706f2543Smrg	    }
2925706f2543Smrg	    pChild->mapped = FALSE;
2926706f2543Smrg	    if (pChild->realized)
2927706f2543Smrg		UnrealizeTree(pChild, FALSE);
2928706f2543Smrg	    if (wasViewable)
2929706f2543Smrg	    {
2930706f2543Smrg	    }
2931706f2543Smrg	}
2932706f2543Smrg    }
2933706f2543Smrg    if (wasViewable)
2934706f2543Smrg    {
2935706f2543Smrg	if (anyMarked)
2936706f2543Smrg	{
2937706f2543Smrg	    if (pLayerWin->parent == pWin)
2938706f2543Smrg		(*pScreen->MarkWindow)(pWin);
2939706f2543Smrg	    else
2940706f2543Smrg	    {
2941706f2543Smrg		WindowPtr ptmp;
2942706f2543Smrg                (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin,
2943706f2543Smrg						  (WindowPtr *)NULL);
2944706f2543Smrg		(*pScreen->MarkWindow)(pLayerWin->parent);
2945706f2543Smrg
2946706f2543Smrg		/* Windows between pWin and pLayerWin may not have been marked */
2947706f2543Smrg		ptmp = pWin;
2948706f2543Smrg
2949706f2543Smrg		while (ptmp != pLayerWin->parent)
2950706f2543Smrg		{
2951706f2543Smrg		    (*pScreen->MarkWindow)(ptmp);
2952706f2543Smrg		    ptmp = ptmp->parent;
2953706f2543Smrg		}
2954706f2543Smrg                pHead = pWin->firstChild;
2955706f2543Smrg	    }
2956706f2543Smrg	    (*pScreen->ValidateTree)(pLayerWin->parent, pHead, VTUnmap);
2957706f2543Smrg	    (*pScreen->HandleExposures)(pLayerWin->parent);
2958706f2543Smrg	}
2959706f2543Smrg	if (anyMarked && pScreen->PostValidateTree)
2960706f2543Smrg	    (*pScreen->PostValidateTree)(pLayerWin->parent, pHead, VTUnmap);
2961706f2543Smrg    }
2962706f2543Smrg    if (wasRealized)
2963706f2543Smrg	WindowsRestructured ();
2964706f2543Smrg}
2965706f2543Smrg
2966706f2543Smrg
2967706f2543Smrgvoid
2968706f2543SmrgHandleSaveSet(ClientPtr client)
2969706f2543Smrg{
2970706f2543Smrg    WindowPtr pParent, pWin;
2971706f2543Smrg    int j;
2972706f2543Smrg
2973706f2543Smrg    for (j=0; j<client->numSaved; j++)
2974706f2543Smrg    {
2975706f2543Smrg	pWin = SaveSetWindow(client->saveSet[j]);
2976706f2543Smrg#ifdef XFIXES
2977706f2543Smrg	if (SaveSetToRoot(client->saveSet[j]))
2978706f2543Smrg	    pParent = pWin->drawable.pScreen->root;
2979706f2543Smrg	else
2980706f2543Smrg#endif
2981706f2543Smrg	{
2982706f2543Smrg	    pParent = pWin->parent;
2983706f2543Smrg	    while (pParent && (wClient (pParent) == client))
2984706f2543Smrg		pParent = pParent->parent;
2985706f2543Smrg	}
2986706f2543Smrg	if (pParent)
2987706f2543Smrg	{
2988706f2543Smrg	    if (pParent != pWin->parent)
2989706f2543Smrg	    {
2990706f2543Smrg#ifdef XFIXES
2991706f2543Smrg		/* unmap first so that ReparentWindow doesn't remap */
2992706f2543Smrg		if (!SaveSetShouldMap (client->saveSet[j]))
2993706f2543Smrg		    UnmapWindow(pWin, FALSE);
2994706f2543Smrg#endif
2995706f2543Smrg		ReparentWindow(pWin, pParent,
2996706f2543Smrg			       pWin->drawable.x - wBorderWidth (pWin) - pParent->drawable.x,
2997706f2543Smrg			       pWin->drawable.y - wBorderWidth (pWin) - pParent->drawable.y,
2998706f2543Smrg			       client);
2999706f2543Smrg		if(!pWin->realized && pWin->mapped)
3000706f2543Smrg		    pWin->mapped = FALSE;
3001706f2543Smrg	    }
3002706f2543Smrg#ifdef XFIXES
3003706f2543Smrg	    if (SaveSetShouldMap (client->saveSet[j]))
3004706f2543Smrg#endif
3005706f2543Smrg		MapWindow(pWin, client);
3006706f2543Smrg	}
3007706f2543Smrg    }
3008706f2543Smrg    free(client->saveSet);
3009706f2543Smrg    client->numSaved = 0;
3010706f2543Smrg    client->saveSet = (SaveSetElt *)NULL;
3011706f2543Smrg}
3012706f2543Smrg
3013706f2543Smrg/**
3014706f2543Smrg *
3015706f2543Smrg * \param x,y  in root
3016706f2543Smrg */
3017706f2543SmrgBool
3018706f2543SmrgPointInWindowIsVisible(WindowPtr pWin, int x, int y)
3019706f2543Smrg{
3020706f2543Smrg    BoxRec box;
3021706f2543Smrg
3022706f2543Smrg    if (!pWin->realized)
3023706f2543Smrg	return FALSE;
3024706f2543Smrg    if (RegionContainsPoint(&pWin->borderClip,
3025706f2543Smrg						  x, y, &box)
3026706f2543Smrg	&& (!wInputShape(pWin) ||
3027706f2543Smrg	    RegionContainsPoint(wInputShape(pWin),
3028706f2543Smrg				x - pWin->drawable.x,
3029706f2543Smrg				y - pWin->drawable.y, &box)))
3030706f2543Smrg	return TRUE;
3031706f2543Smrg    return FALSE;
3032706f2543Smrg}
3033706f2543Smrg
3034706f2543Smrg
3035706f2543SmrgRegionPtr
3036706f2543SmrgNotClippedByChildren(WindowPtr pWin)
3037706f2543Smrg{
3038706f2543Smrg    RegionPtr pReg = RegionCreate(NullBox, 1);
3039706f2543Smrg    if (pWin->parent ||
3040706f2543Smrg	screenIsSaved != SCREEN_SAVER_ON ||
3041706f2543Smrg	!HasSaverWindow (pWin->drawable.pScreen))
3042706f2543Smrg    {
3043706f2543Smrg	RegionIntersect(pReg, &pWin->borderClip, &pWin->winSize);
3044706f2543Smrg    }
3045706f2543Smrg    return pReg;
3046706f2543Smrg}
3047706f2543Smrg
3048706f2543Smrgvoid
3049706f2543SmrgSendVisibilityNotify(WindowPtr pWin)
3050706f2543Smrg{
3051706f2543Smrg    xEvent event;
3052706f2543Smrg    unsigned int visibility = pWin->visibility;
3053706f2543Smrg
3054706f2543Smrg    if (!MapUnmapEventsEnabled(pWin))
3055706f2543Smrg        return;
3056706f2543Smrg#ifdef PANORAMIX
3057706f2543Smrg    /* This is not quite correct yet, but it's close */
3058706f2543Smrg    if(!noPanoramiXExtension) {
3059706f2543Smrg	PanoramiXRes *win;
3060706f2543Smrg	WindowPtr pWin2;
3061706f2543Smrg	int rc, i, Scrnum;
3062706f2543Smrg
3063706f2543Smrg	Scrnum = pWin->drawable.pScreen->myNum;
3064706f2543Smrg
3065706f2543Smrg	win = PanoramiXFindIDByScrnum(XRT_WINDOW, pWin->drawable.id, Scrnum);
3066706f2543Smrg
3067706f2543Smrg	if(!win || (win->u.win.visibility == visibility))
3068706f2543Smrg	    return;
3069706f2543Smrg
3070706f2543Smrg	switch(visibility) {
3071706f2543Smrg	case VisibilityUnobscured:
3072706f2543Smrg	    for(i = 0; i < PanoramiXNumScreens; i++) {
3073706f2543Smrg		if(i == Scrnum) continue;
3074706f2543Smrg
3075706f2543Smrg		rc = dixLookupWindow(&pWin2, win->info[i].id, serverClient,
3076706f2543Smrg				     DixWriteAccess);
3077706f2543Smrg
3078706f2543Smrg		if (rc == Success) {
3079706f2543Smrg		    if(pWin2->visibility == VisibilityPartiallyObscured)
3080706f2543Smrg		   	return;
3081706f2543Smrg
3082706f2543Smrg		    if(!i) pWin = pWin2;
3083706f2543Smrg		}
3084706f2543Smrg	    }
3085706f2543Smrg	    break;
3086706f2543Smrg	case VisibilityPartiallyObscured:
3087706f2543Smrg	    if(Scrnum) {
3088706f2543Smrg		rc = dixLookupWindow(&pWin2, win->info[0].id, serverClient,
3089706f2543Smrg				     DixWriteAccess);
3090706f2543Smrg		if (rc == Success) pWin = pWin2;
3091706f2543Smrg	    }
3092706f2543Smrg	    break;
3093706f2543Smrg	case VisibilityFullyObscured:
3094706f2543Smrg	    for(i = 0; i < PanoramiXNumScreens; i++) {
3095706f2543Smrg		if(i == Scrnum) continue;
3096706f2543Smrg
3097706f2543Smrg		rc = dixLookupWindow(&pWin2, win->info[i].id, serverClient,
3098706f2543Smrg				     DixWriteAccess);
3099706f2543Smrg
3100706f2543Smrg		if (rc == Success) {
3101706f2543Smrg		    if(pWin2->visibility != VisibilityFullyObscured)
3102706f2543Smrg		    	return;
3103706f2543Smrg
3104706f2543Smrg		    if(!i) pWin = pWin2;
3105706f2543Smrg		}
3106706f2543Smrg	    }
3107706f2543Smrg	    break;
3108706f2543Smrg	}
3109706f2543Smrg
3110706f2543Smrg	win->u.win.visibility = visibility;
3111706f2543Smrg    }
3112706f2543Smrg#endif
3113706f2543Smrg
3114706f2543Smrg    memset(&event, 0, sizeof(xEvent));
3115706f2543Smrg    event.u.u.type = VisibilityNotify;
3116706f2543Smrg    event.u.visibility.window = pWin->drawable.id;
3117706f2543Smrg    event.u.visibility.state = visibility;
3118706f2543Smrg    DeliverEvents(pWin, &event, 1, NullWindow);
3119706f2543Smrg}
3120706f2543Smrg
3121706f2543Smrg#define RANDOM_WIDTH 32
3122706f2543Smrgint
3123706f2543SmrgdixSaveScreens(ClientPtr client, int on, int mode)
3124706f2543Smrg{
3125706f2543Smrg    int rc, i, what, type;
3126706f2543Smrg
3127706f2543Smrg    if (on == SCREEN_SAVER_FORCER)
3128706f2543Smrg    {
3129706f2543Smrg	if (mode == ScreenSaverReset)
3130706f2543Smrg	    what = SCREEN_SAVER_OFF;
3131706f2543Smrg	else
3132706f2543Smrg	    what = SCREEN_SAVER_ON;
3133706f2543Smrg	type = what;
3134706f2543Smrg    }
3135706f2543Smrg    else
3136706f2543Smrg    {
3137706f2543Smrg	what = on;
3138706f2543Smrg	type = what;
3139706f2543Smrg	if (what == screenIsSaved)
3140706f2543Smrg	    type = SCREEN_SAVER_CYCLE;
3141706f2543Smrg    }
3142706f2543Smrg
3143706f2543Smrg    for (i = 0; i < screenInfo.numScreens; i++) {
3144706f2543Smrg	rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3145706f2543Smrg		      DixShowAccess | DixHideAccess);
3146706f2543Smrg	if (rc != Success)
3147706f2543Smrg	    return rc;
3148706f2543Smrg    }
3149706f2543Smrg    for (i = 0; i < screenInfo.numScreens; i++)
3150706f2543Smrg    {
3151706f2543Smrg	ScreenPtr pScreen = screenInfo.screens[i];
3152706f2543Smrg	if (on == SCREEN_SAVER_FORCER)
3153706f2543Smrg	   (* pScreen->SaveScreen) (pScreen, on);
3154706f2543Smrg	if (pScreen->screensaver.ExternalScreenSaver)
3155706f2543Smrg	{
3156706f2543Smrg	    if ((*pScreen->screensaver.ExternalScreenSaver)
3157706f2543Smrg		(pScreen, type, on == SCREEN_SAVER_FORCER))
3158706f2543Smrg		continue;
3159706f2543Smrg	}
3160706f2543Smrg	if (type == screenIsSaved)
3161706f2543Smrg	    continue;
3162706f2543Smrg	switch (type) {
3163706f2543Smrg	case SCREEN_SAVER_OFF:
3164706f2543Smrg	    if (pScreen->screensaver.blanked == SCREEN_IS_BLANKED)
3165706f2543Smrg	    {
3166706f2543Smrg	       (* pScreen->SaveScreen) (pScreen, what);
3167706f2543Smrg	    }
3168706f2543Smrg	    else if (HasSaverWindow (pScreen))
3169706f2543Smrg	    {
3170706f2543Smrg		pScreen->screensaver.pWindow = NullWindow;
3171706f2543Smrg		FreeResource(pScreen->screensaver.wid, RT_NONE);
3172706f2543Smrg	    }
3173706f2543Smrg	    break;
3174706f2543Smrg	case SCREEN_SAVER_CYCLE:
3175706f2543Smrg	    if (pScreen->screensaver.blanked == SCREEN_IS_TILED)
3176706f2543Smrg	    {
3177706f2543Smrg		WindowPtr pWin = pScreen->screensaver.pWindow;
3178706f2543Smrg		/* make it look like screen saver is off, so that
3179706f2543Smrg		 * NotClippedByChildren will compute a clip list
3180706f2543Smrg		 * for the root window, so miPaintWindow works
3181706f2543Smrg		 */
3182706f2543Smrg		screenIsSaved = SCREEN_SAVER_OFF;
3183706f2543Smrg		(*pWin->drawable.pScreen->MoveWindow)(pWin,
3184706f2543Smrg			   (short)(-(rand() % RANDOM_WIDTH)),
3185706f2543Smrg			   (short)(-(rand() % RANDOM_WIDTH)),
3186706f2543Smrg			   pWin->nextSib, VTMove);
3187706f2543Smrg		screenIsSaved = SCREEN_SAVER_ON;
3188706f2543Smrg	    }
3189706f2543Smrg	    /*
3190706f2543Smrg	     * Call the DDX saver in case it wants to do something
3191706f2543Smrg	     * at cycle time
3192706f2543Smrg	     */
3193706f2543Smrg	    else if (pScreen->screensaver.blanked == SCREEN_IS_BLANKED)
3194706f2543Smrg	    {
3195706f2543Smrg		(* pScreen->SaveScreen) (pScreen, type);
3196706f2543Smrg	    }
3197706f2543Smrg	    break;
3198706f2543Smrg	case SCREEN_SAVER_ON:
3199706f2543Smrg	    if (ScreenSaverBlanking != DontPreferBlanking)
3200706f2543Smrg	    {
3201706f2543Smrg		if ((* pScreen->SaveScreen) (pScreen, what))
3202706f2543Smrg		{
3203706f2543Smrg		   pScreen->screensaver.blanked = SCREEN_IS_BLANKED;
3204706f2543Smrg		   continue;
3205706f2543Smrg		}
3206706f2543Smrg		if ((ScreenSaverAllowExposures != DontAllowExposures) &&
3207706f2543Smrg		    TileScreenSaver(pScreen, SCREEN_IS_BLACK))
3208706f2543Smrg		{
3209706f2543Smrg		    pScreen->screensaver.blanked = SCREEN_IS_BLACK;
3210706f2543Smrg		    continue;
3211706f2543Smrg		}
3212706f2543Smrg	    }
3213706f2543Smrg	    if ((ScreenSaverAllowExposures != DontAllowExposures) &&
3214706f2543Smrg		TileScreenSaver(pScreen, SCREEN_IS_TILED))
3215706f2543Smrg	    {
3216706f2543Smrg		pScreen->screensaver.blanked = SCREEN_IS_TILED;
3217706f2543Smrg	    }
3218706f2543Smrg	    else
3219706f2543Smrg		pScreen->screensaver.blanked = SCREEN_ISNT_SAVED;
3220706f2543Smrg	    break;
3221706f2543Smrg	}
3222706f2543Smrg    }
3223706f2543Smrg    screenIsSaved = what;
3224706f2543Smrg    if (mode == ScreenSaverReset) {
3225706f2543Smrg	if (on == SCREEN_SAVER_FORCER) {
3226706f2543Smrg	    UpdateCurrentTimeIf();
3227706f2543Smrg	    lastDeviceEventTime = currentTime;
3228706f2543Smrg	}
3229706f2543Smrg	SetScreenSaverTimer();
3230706f2543Smrg    }
3231706f2543Smrg    return Success;
3232706f2543Smrg}
3233706f2543Smrg
3234706f2543Smrgint
3235706f2543SmrgSaveScreens(int on, int mode)
3236706f2543Smrg{
3237706f2543Smrg    return dixSaveScreens(serverClient, on, mode);
3238706f2543Smrg}
3239706f2543Smrg
3240706f2543Smrgstatic Bool
3241706f2543SmrgTileScreenSaver(ScreenPtr pScreen, int kind)
3242706f2543Smrg{
3243706f2543Smrg    int j;
3244706f2543Smrg    int result;
3245706f2543Smrg    XID attributes[3];
3246706f2543Smrg    Mask mask;
3247706f2543Smrg    WindowPtr pWin;
3248706f2543Smrg    CursorMetricRec cm;
3249706f2543Smrg    unsigned char *srcbits, *mskbits;
3250706f2543Smrg    CursorPtr cursor;
3251706f2543Smrg    XID	cursorID = 0;
3252706f2543Smrg    int	attri;
3253706f2543Smrg
3254706f2543Smrg    mask = 0;
3255706f2543Smrg    attri = 0;
3256706f2543Smrg    switch (kind) {
3257706f2543Smrg    case SCREEN_IS_TILED:
3258706f2543Smrg	switch (pScreen->root->backgroundState) {
3259706f2543Smrg	case BackgroundPixel:
3260706f2543Smrg	    attributes[attri++] = pScreen->root->background.pixel;
3261706f2543Smrg	    mask |= CWBackPixel;
3262706f2543Smrg	    break;
3263706f2543Smrg	case BackgroundPixmap:
3264706f2543Smrg	    attributes[attri++] = None;
3265706f2543Smrg	    mask |= CWBackPixmap;
3266706f2543Smrg	    break;
3267706f2543Smrg	default:
3268706f2543Smrg	    break;
3269706f2543Smrg	}
3270706f2543Smrg	break;
3271706f2543Smrg    case SCREEN_IS_BLACK:
3272706f2543Smrg	attributes[attri++] = pScreen->root->drawable.pScreen->blackPixel;
3273706f2543Smrg	mask |= CWBackPixel;
3274706f2543Smrg	break;
3275706f2543Smrg    }
3276706f2543Smrg    mask |= CWOverrideRedirect;
3277706f2543Smrg    attributes[attri++] = xTrue;
3278706f2543Smrg
3279706f2543Smrg    /*
3280706f2543Smrg     * create a blank cursor
3281706f2543Smrg     */
3282706f2543Smrg
3283706f2543Smrg    cm.width=16;
3284706f2543Smrg    cm.height=16;
3285706f2543Smrg    cm.xhot=8;
3286706f2543Smrg    cm.yhot=8;
3287706f2543Smrg    srcbits = malloc( BitmapBytePad(32)*16);
3288706f2543Smrg    mskbits = malloc( BitmapBytePad(32)*16);
3289706f2543Smrg    if (!srcbits || !mskbits)
3290706f2543Smrg    {
3291706f2543Smrg	free(srcbits);
3292706f2543Smrg	free(mskbits);
3293706f2543Smrg	cursor = 0;
3294706f2543Smrg    }
3295706f2543Smrg    else
3296706f2543Smrg    {
3297706f2543Smrg	for (j=0; j<BitmapBytePad(32)*16; j++)
3298706f2543Smrg	    srcbits[j] = mskbits[j] = 0x0;
3299706f2543Smrg	result = AllocARGBCursor(srcbits, mskbits, NULL, &cm, 0, 0, 0, 0, 0, 0,
3300706f2543Smrg				 &cursor, serverClient, (XID)0);
3301706f2543Smrg	if (cursor)
3302706f2543Smrg	{
3303706f2543Smrg	    cursorID = FakeClientID(0);
3304706f2543Smrg	    if (AddResource (cursorID, RT_CURSOR, (pointer) cursor))
3305706f2543Smrg	    {
3306706f2543Smrg		attributes[attri] = cursorID;
3307706f2543Smrg		mask |= CWCursor;
3308706f2543Smrg	    }
3309706f2543Smrg	    else
3310706f2543Smrg		cursor = 0;
3311706f2543Smrg	}
3312706f2543Smrg	else
3313706f2543Smrg	{
3314706f2543Smrg	    free(srcbits);
3315706f2543Smrg	    free(mskbits);
3316706f2543Smrg	}
3317706f2543Smrg    }
3318706f2543Smrg
3319706f2543Smrg    pWin = pScreen->screensaver.pWindow =
3320706f2543Smrg	 CreateWindow(pScreen->screensaver.wid,
3321706f2543Smrg	      pScreen->root,
3322706f2543Smrg	      -RANDOM_WIDTH, -RANDOM_WIDTH,
3323706f2543Smrg	      (unsigned short)pScreen->width + RANDOM_WIDTH,
3324706f2543Smrg	      (unsigned short)pScreen->height + RANDOM_WIDTH,
3325706f2543Smrg	      0, InputOutput, mask, attributes, 0, serverClient,
3326706f2543Smrg	      wVisual (pScreen->root), &result);
3327706f2543Smrg
3328706f2543Smrg    if (cursor)
3329706f2543Smrg	FreeResource (cursorID, RT_NONE);
3330706f2543Smrg
3331706f2543Smrg    if (!pWin)
3332706f2543Smrg	return FALSE;
3333706f2543Smrg
3334706f2543Smrg    if (!AddResource(pWin->drawable.id, RT_WINDOW,
3335706f2543Smrg		     (pointer)pScreen->screensaver.pWindow))
3336706f2543Smrg	return FALSE;
3337706f2543Smrg
3338706f2543Smrg    if (mask & CWBackPixmap)
3339706f2543Smrg    {
3340706f2543Smrg	MakeRootTile (pWin);
3341706f2543Smrg	(*pWin->drawable.pScreen->ChangeWindowAttributes)(pWin, CWBackPixmap);
3342706f2543Smrg    }
3343706f2543Smrg    MapWindow(pWin, serverClient);
3344706f2543Smrg    return TRUE;
3345706f2543Smrg}
3346706f2543Smrg
3347706f2543Smrg/*
3348706f2543Smrg * FindWindowWithOptional
3349706f2543Smrg *
3350706f2543Smrg * search ancestors of the given window for an entry containing
3351706f2543Smrg * a WindowOpt structure.  Assumptions:	 some parent will
3352706f2543Smrg * contain the structure.
3353706f2543Smrg */
3354706f2543Smrg
3355706f2543SmrgWindowPtr
3356706f2543SmrgFindWindowWithOptional (WindowPtr w)
3357706f2543Smrg{
3358706f2543Smrg    do
3359706f2543Smrg	w = w->parent;
3360706f2543Smrg    while (!w->optional);
3361706f2543Smrg    return w;
3362706f2543Smrg}
3363706f2543Smrg
3364706f2543Smrg/*
3365706f2543Smrg * CheckWindowOptionalNeed
3366706f2543Smrg *
3367706f2543Smrg * check each optional entry in the given window to see if
3368706f2543Smrg * the value is satisfied by the default rules.	 If so,
3369706f2543Smrg * release the optional record
3370706f2543Smrg */
3371706f2543Smrg
3372706f2543Smrgvoid
3373706f2543SmrgCheckWindowOptionalNeed (WindowPtr w)
3374706f2543Smrg{
3375706f2543Smrg    WindowOptPtr optional;
3376706f2543Smrg    WindowOptPtr parentOptional;
3377706f2543Smrg
3378706f2543Smrg    if (!w->parent || !w->optional)
3379706f2543Smrg	return;
3380706f2543Smrg    optional = w->optional;
3381706f2543Smrg    if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate])
3382706f2543Smrg	return;
3383706f2543Smrg    if (optional->otherEventMasks != 0)
3384706f2543Smrg	return;
3385706f2543Smrg    if (optional->otherClients != NULL)
3386706f2543Smrg	return;
3387706f2543Smrg    if (optional->passiveGrabs != NULL)
3388706f2543Smrg	return;
3389706f2543Smrg    if (optional->userProps != NULL)
3390706f2543Smrg	return;
3391706f2543Smrg    if (optional->backingBitPlanes != ~0L)
3392706f2543Smrg	return;
3393706f2543Smrg    if (optional->backingPixel != 0)
3394706f2543Smrg	return;
3395706f2543Smrg    if (optional->boundingShape != NULL)
3396706f2543Smrg	return;
3397706f2543Smrg    if (optional->clipShape != NULL)
3398706f2543Smrg	return;
3399706f2543Smrg    if (optional->inputShape != NULL)
3400706f2543Smrg	return;
3401706f2543Smrg    if (optional->inputMasks != NULL)
3402706f2543Smrg	return;
3403706f2543Smrg    if (optional->deviceCursors != NULL)
3404706f2543Smrg    {
3405706f2543Smrg        DevCursNodePtr pNode = optional->deviceCursors;
3406706f2543Smrg        while(pNode)
3407706f2543Smrg        {
3408706f2543Smrg            if (pNode->cursor != None)
3409706f2543Smrg                return;
3410706f2543Smrg            pNode = pNode->next;
3411706f2543Smrg        }
3412706f2543Smrg    }
3413706f2543Smrg
3414706f2543Smrg    parentOptional = FindWindowWithOptional(w)->optional;
3415706f2543Smrg    if (optional->visual != parentOptional->visual)
3416706f2543Smrg	return;
3417706f2543Smrg    if (optional->cursor != None &&
3418706f2543Smrg	(optional->cursor != parentOptional->cursor ||
3419706f2543Smrg	 w->parent->cursorIsNone))
3420706f2543Smrg	return;
3421706f2543Smrg    if (optional->colormap != parentOptional->colormap)
3422706f2543Smrg	return;
3423706f2543Smrg    DisposeWindowOptional (w);
3424706f2543Smrg}
3425706f2543Smrg
3426706f2543Smrg/*
3427706f2543Smrg * MakeWindowOptional
3428706f2543Smrg *
3429706f2543Smrg * create an optional record and initialize it with the default
3430706f2543Smrg * values.
3431706f2543Smrg */
3432706f2543Smrg
3433706f2543SmrgBool
3434706f2543SmrgMakeWindowOptional (WindowPtr pWin)
3435706f2543Smrg{
3436706f2543Smrg    WindowOptPtr optional;
3437706f2543Smrg    WindowOptPtr parentOptional;
3438706f2543Smrg
3439706f2543Smrg    if (pWin->optional)
3440706f2543Smrg	return TRUE;
3441706f2543Smrg    optional = malloc(sizeof (WindowOptRec));
3442706f2543Smrg    if (!optional)
3443706f2543Smrg	return FALSE;
3444706f2543Smrg    optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate];
3445706f2543Smrg    optional->otherEventMasks = 0;
3446706f2543Smrg    optional->otherClients = NULL;
3447706f2543Smrg    optional->passiveGrabs = NULL;
3448706f2543Smrg    optional->userProps = NULL;
3449706f2543Smrg    optional->backingBitPlanes = ~0L;
3450706f2543Smrg    optional->backingPixel = 0;
3451706f2543Smrg    optional->boundingShape = NULL;
3452706f2543Smrg    optional->clipShape = NULL;
3453706f2543Smrg    optional->inputShape = NULL;
3454706f2543Smrg    optional->inputMasks = NULL;
3455706f2543Smrg    optional->deviceCursors = NULL;
3456706f2543Smrg
3457706f2543Smrg    parentOptional = FindWindowWithOptional(pWin)->optional;
3458706f2543Smrg    optional->visual = parentOptional->visual;
3459706f2543Smrg    if (!pWin->cursorIsNone)
3460706f2543Smrg    {
3461706f2543Smrg	optional->cursor = parentOptional->cursor;
3462706f2543Smrg	optional->cursor->refcnt++;
3463706f2543Smrg    }
3464706f2543Smrg    else
3465706f2543Smrg    {
3466706f2543Smrg	optional->cursor = None;
3467706f2543Smrg    }
3468706f2543Smrg    optional->colormap = parentOptional->colormap;
3469706f2543Smrg    pWin->optional = optional;
3470706f2543Smrg    return TRUE;
3471706f2543Smrg}
3472706f2543Smrg
3473706f2543Smrg/*
3474706f2543Smrg * Changes the cursor struct for the given device and the given window.
3475706f2543Smrg * A cursor that does not have a device cursor set will use whatever the
3476706f2543Smrg * standard cursor is for the window. If all devices have a cursor set,
3477706f2543Smrg * changing the window cursor (e.g. using XDefineCursor()) will not have any
3478706f2543Smrg * visible effect. Only when one of the device cursors is set to None again,
3479706f2543Smrg * this device's cursor will display the changed standard cursor.
3480706f2543Smrg *
3481706f2543Smrg * CursorIsNone of the window struct is NOT modified if you set a device
3482706f2543Smrg * cursor.
3483706f2543Smrg *
3484706f2543Smrg * Assumption: If there is a node for a device in the list, the device has a
3485706f2543Smrg * cursor. If the cursor is set to None, it is inherited by the parent.
3486706f2543Smrg */
3487706f2543Smrgint
3488706f2543SmrgChangeWindowDeviceCursor(WindowPtr pWin,
3489706f2543Smrg                         DeviceIntPtr pDev,
3490706f2543Smrg                         CursorPtr pCursor)
3491706f2543Smrg{
3492706f2543Smrg    DevCursNodePtr pNode, pPrev;
3493706f2543Smrg    CursorPtr pOldCursor = NULL;
3494706f2543Smrg    ScreenPtr pScreen;
3495706f2543Smrg    WindowPtr pChild;
3496706f2543Smrg
3497706f2543Smrg    if (!pWin->optional && !MakeWindowOptional(pWin))
3498706f2543Smrg        return BadAlloc;
3499706f2543Smrg
3500706f2543Smrg    /* 1) Check if window has device cursor set
3501706f2543Smrg     *  Yes: 1.1) swap cursor with given cursor if parent does not have same
3502706f2543Smrg     *            cursor, free old cursor
3503706f2543Smrg     *       1.2) free old cursor, use parent cursor
3504706f2543Smrg     *  No: 1.1) add node to beginning of list.
3505706f2543Smrg     *      1.2) add cursor to node if parent does not have same cursor
3506706f2543Smrg     *      1.3) use parent cursor if parent does not have same cursor
3507706f2543Smrg     *  2) Patch up children if child has a devcursor
3508706f2543Smrg     *  2.1) if child has cursor None, it inherited from parent, set to old
3509706f2543Smrg     *  cursor
3510706f2543Smrg     *  2.2) if child has same cursor as new cursor, remove and set to None
3511706f2543Smrg     */
3512706f2543Smrg
3513706f2543Smrg    pScreen = pWin->drawable.pScreen;
3514706f2543Smrg
3515706f2543Smrg    if (WindowSeekDeviceCursor(pWin, pDev, &pNode, &pPrev))
3516706f2543Smrg    {
3517706f2543Smrg        /* has device cursor */
3518706f2543Smrg
3519706f2543Smrg        if (pNode->cursor == pCursor)
3520706f2543Smrg            return Success;
3521706f2543Smrg
3522706f2543Smrg        pOldCursor = pNode->cursor;
3523706f2543Smrg
3524706f2543Smrg        if (!pCursor) /* remove from list */
3525706f2543Smrg        {
3526706f2543Smrg                if(pPrev)
3527706f2543Smrg                    pPrev->next = pNode->next;
3528706f2543Smrg                else
3529706f2543Smrg                    /* first item in list */
3530706f2543Smrg                    pWin->optional->deviceCursors = pNode->next;
3531706f2543Smrg
3532706f2543Smrg            free(pNode);
3533706f2543Smrg            goto out;
3534706f2543Smrg        }
3535706f2543Smrg
3536706f2543Smrg    } else
3537706f2543Smrg    {
3538706f2543Smrg        /* no device cursor yet */
3539706f2543Smrg        DevCursNodePtr pNewNode;
3540706f2543Smrg
3541706f2543Smrg        if (!pCursor)
3542706f2543Smrg            return Success;
3543706f2543Smrg
3544706f2543Smrg        pNewNode = malloc(sizeof(DevCursNodeRec));
3545706f2543Smrg        pNewNode->dev = pDev;
3546706f2543Smrg        pNewNode->next = pWin->optional->deviceCursors;
3547706f2543Smrg        pWin->optional->deviceCursors = pNewNode;
3548706f2543Smrg        pNode = pNewNode;
3549706f2543Smrg
3550706f2543Smrg    }
3551706f2543Smrg
3552706f2543Smrg    if (pCursor && WindowParentHasDeviceCursor(pWin, pDev, pCursor))
3553706f2543Smrg        pNode->cursor = None;
3554706f2543Smrg    else
3555706f2543Smrg    {
3556706f2543Smrg        pNode->cursor = pCursor;
3557706f2543Smrg        pCursor->refcnt++;
3558706f2543Smrg    }
3559706f2543Smrg
3560706f2543Smrg    pNode = pPrev = NULL;
3561706f2543Smrg    /* fix up children */
3562706f2543Smrg    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
3563706f2543Smrg    {
3564706f2543Smrg        if (WindowSeekDeviceCursor(pChild, pDev, &pNode, &pPrev))
3565706f2543Smrg        {
3566706f2543Smrg            if (pNode->cursor == None) /* inherited from parent */
3567706f2543Smrg            {
3568706f2543Smrg                pNode->cursor = pOldCursor;
3569706f2543Smrg                pOldCursor->refcnt++;
3570706f2543Smrg            } else if (pNode->cursor == pCursor)
3571706f2543Smrg            {
3572706f2543Smrg                pNode->cursor = None;
3573706f2543Smrg                FreeCursor(pCursor, (Cursor)0); /* fix up refcnt */
3574706f2543Smrg            }
3575706f2543Smrg        }
3576706f2543Smrg    }
3577706f2543Smrg
3578706f2543Smrgout:
3579706f2543Smrg    if (pWin->realized)
3580706f2543Smrg        WindowHasNewCursor(pWin);
3581706f2543Smrg
3582706f2543Smrg    if (pOldCursor)
3583706f2543Smrg        FreeCursor(pOldCursor, (Cursor)0);
3584706f2543Smrg
3585706f2543Smrg    /* FIXME: We SHOULD check for an error value here XXX
3586706f2543Smrg       (comment taken from ChangeWindowAttributes) */
3587706f2543Smrg    (*pScreen->ChangeWindowAttributes)(pWin, CWCursor);
3588706f2543Smrg
3589706f2543Smrg    return Success;
3590706f2543Smrg}
3591706f2543Smrg
3592706f2543Smrg/* Get device cursor for given device or None if none is set */
3593706f2543SmrgCursorPtr
3594706f2543SmrgWindowGetDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev)
3595706f2543Smrg{
3596706f2543Smrg    DevCursorList pList;
3597706f2543Smrg
3598706f2543Smrg    if (!pWin->optional || !pWin->optional->deviceCursors)
3599706f2543Smrg        return NULL;
3600706f2543Smrg
3601706f2543Smrg    pList = pWin->optional->deviceCursors;
3602706f2543Smrg
3603706f2543Smrg    while(pList)
3604706f2543Smrg    {
3605706f2543Smrg        if (pList->dev == pDev)
3606706f2543Smrg        {
3607706f2543Smrg            if (pList->cursor == None) /* inherited from parent */
3608706f2543Smrg                return WindowGetDeviceCursor(pWin->parent, pDev);
3609706f2543Smrg            else
3610706f2543Smrg                return pList->cursor;
3611706f2543Smrg        }
3612706f2543Smrg        pList = pList->next;
3613706f2543Smrg    }
3614706f2543Smrg    return NULL;
3615706f2543Smrg}
3616706f2543Smrg
3617706f2543Smrg/* Searches for a DevCursorNode for the given window and device. If one is
3618706f2543Smrg * found, return True and set pNode and pPrev to the node and to the node
3619706f2543Smrg * before the node respectively. Otherwise return False.
3620706f2543Smrg * If the device is the first in list, pPrev is set to NULL.
3621706f2543Smrg */
3622706f2543Smrgstatic Bool
3623706f2543SmrgWindowSeekDeviceCursor(WindowPtr pWin,
3624706f2543Smrg                       DeviceIntPtr pDev,
3625706f2543Smrg                       DevCursNodePtr* pNode,
3626706f2543Smrg                       DevCursNodePtr* pPrev)
3627706f2543Smrg{
3628706f2543Smrg    DevCursorList pList;
3629706f2543Smrg
3630706f2543Smrg    if (!pWin->optional)
3631706f2543Smrg        return FALSE;
3632706f2543Smrg
3633706f2543Smrg    pList = pWin->optional->deviceCursors;
3634706f2543Smrg
3635706f2543Smrg    if (pList && pList->dev == pDev)
3636706f2543Smrg    {
3637706f2543Smrg        *pNode = pList;
3638706f2543Smrg        *pPrev = NULL;
3639706f2543Smrg        return TRUE;
3640706f2543Smrg    }
3641706f2543Smrg
3642706f2543Smrg    while(pList)
3643706f2543Smrg    {
3644706f2543Smrg        if (pList->next)
3645706f2543Smrg        {
3646706f2543Smrg            if (pList->next->dev == pDev)
3647706f2543Smrg            {
3648706f2543Smrg                *pNode = pList->next;
3649706f2543Smrg                *pPrev = pList;
3650706f2543Smrg                return TRUE;
3651706f2543Smrg            }
3652706f2543Smrg        }
3653706f2543Smrg        pList = pList->next;
3654706f2543Smrg    }
3655706f2543Smrg    return FALSE;
3656706f2543Smrg}
3657706f2543Smrg
3658706f2543Smrg/* Return True if a parent has the same device cursor set or False if
3659706f2543Smrg * otherwise
3660706f2543Smrg */
3661706f2543Smrgstatic Bool
3662706f2543SmrgWindowParentHasDeviceCursor(WindowPtr pWin,
3663706f2543Smrg                            DeviceIntPtr pDev,
3664706f2543Smrg                            CursorPtr pCursor)
3665706f2543Smrg{
3666706f2543Smrg    WindowPtr pParent;
3667706f2543Smrg    DevCursNodePtr pParentNode, pParentPrev;
3668706f2543Smrg
3669706f2543Smrg    pParent = pWin->parent;
3670706f2543Smrg    while(pParent)
3671706f2543Smrg    {
3672706f2543Smrg        if (WindowSeekDeviceCursor(pParent, pDev,
3673706f2543Smrg                    &pParentNode, &pParentPrev))
3674706f2543Smrg        {
3675706f2543Smrg            /* if there is a node in the list, the win has a dev cursor */
3676706f2543Smrg            if (!pParentNode->cursor) /* inherited. */
3677706f2543Smrg                pParent = pParent->parent;
3678706f2543Smrg            else if (pParentNode->cursor == pCursor) /* inherit */
3679706f2543Smrg                return TRUE;
3680706f2543Smrg            else  /* different cursor */
3681706f2543Smrg                return FALSE;
3682706f2543Smrg        }
3683706f2543Smrg        else
3684706f2543Smrg            /* parent does not have a device cursor for our device */
3685706f2543Smrg            return FALSE;
3686706f2543Smrg    }
3687706f2543Smrg    return FALSE;
3688706f2543Smrg}
3689