window.c revision 7e31ba66
105b261ecSmrg/*
205b261ecSmrg
305b261ecSmrgCopyright (c) 2006, Red Hat, Inc.
405b261ecSmrg
54202a189SmrgPermission is hereby granted, free of charge, to any person obtaining a
64202a189Smrgcopy of this software and associated documentation files (the "Software"),
74202a189Smrgto deal in the Software without restriction, including without limitation
84202a189Smrgthe rights to use, copy, modify, merge, publish, distribute, sublicense,
94202a189Smrgand/or sell copies of the Software, and to permit persons to whom the
104202a189SmrgSoftware is furnished to do so, subject to the following conditions:
1105b261ecSmrg
124202a189SmrgThe above copyright notice and this permission notice (including the next
134202a189Smrgparagraph) shall be included in all copies or substantial portions of the
144202a189SmrgSoftware.
1505b261ecSmrg
1605b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1705b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
184202a189SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
194202a189SmrgTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
204202a189SmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
214202a189SmrgFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
224202a189SmrgDEALINGS IN THE SOFTWARE.
2305b261ecSmrg
2405b261ecSmrgCopyright 1987, 1998  The Open Group
2505b261ecSmrg
2605b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
2705b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
2805b261ecSmrgthe above copyright notice appear in all copies and that both that
2905b261ecSmrgcopyright notice and this permission notice appear in supporting
3005b261ecSmrgdocumentation.
3105b261ecSmrg
3205b261ecSmrgThe above copyright notice and this permission notice shall be included
3305b261ecSmrgin all copies or substantial portions of the Software.
3405b261ecSmrg
3505b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
3605b261ecSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3705b261ecSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
3805b261ecSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
3905b261ecSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
4005b261ecSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
4105b261ecSmrgOTHER DEALINGS IN THE SOFTWARE.
4205b261ecSmrg
4305b261ecSmrgExcept as contained in this notice, the name of The Open Group shall
4405b261ecSmrgnot be used in advertising or otherwise to promote the sale, use or
4505b261ecSmrgother dealings in this Software without prior written authorization
4605b261ecSmrgfrom The Open Group.
4705b261ecSmrg
4805b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
4905b261ecSmrg
5005b261ecSmrg			All Rights Reserved
5105b261ecSmrg
52f7df2e56SmrgPermission to use, copy, modify, and distribute this software and its
53f7df2e56Smrgdocumentation for any purpose and without fee is hereby granted,
5405b261ecSmrgprovided that the above copyright notice appear in all copies and that
55f7df2e56Smrgboth that copyright notice and this permission notice appear in
5605b261ecSmrgsupporting documentation, and that the name of Digital not be
5705b261ecSmrgused in advertising or publicity pertaining to distribution of the
58f7df2e56Smrgsoftware without specific, written prior permission.
5905b261ecSmrg
6005b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
6105b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
6205b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
6305b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
6405b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
6505b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
6605b261ecSmrgSOFTWARE.
6705b261ecSmrg
6805b261ecSmrg*/
6905b261ecSmrg
7005b261ecSmrg/* The panoramix components contained the following notice */
7105b261ecSmrg/*****************************************************************
7205b261ecSmrg
7305b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
7405b261ecSmrg
7505b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy
7605b261ecSmrgof this software and associated documentation files (the "Software"), to deal
7705b261ecSmrgin the Software without restriction, including without limitation the rights
7805b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7905b261ecSmrgcopies of the Software.
8005b261ecSmrg
8105b261ecSmrgThe above copyright notice and this permission notice shall be included in
8205b261ecSmrgall copies or substantial portions of the Software.
8305b261ecSmrg
8405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
8605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
8705b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
8805b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
8905b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
9005b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9105b261ecSmrg
9205b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation
9305b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other
9405b261ecSmrgdealings in this Software without prior written authorization from Digital
9505b261ecSmrgEquipment Corporation.
9605b261ecSmrg
9705b261ecSmrg******************************************************************/
9805b261ecSmrg
9905b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
10005b261ecSmrg#include <dix-config.h>
10105b261ecSmrg#endif
10205b261ecSmrg
10305b261ecSmrg#include "misc.h"
10405b261ecSmrg#include "scrnintstr.h"
10505b261ecSmrg#include "os.h"
10605b261ecSmrg#include "regionstr.h"
10705b261ecSmrg#include "validate.h"
10805b261ecSmrg#include "windowstr.h"
109f7df2e56Smrg#include "propertyst.h"
11005b261ecSmrg#include "input.h"
111637ac9abSmrg#include "inputstr.h"
11205b261ecSmrg#include "resource.h"
11305b261ecSmrg#include "colormapst.h"
11405b261ecSmrg#include "cursorstr.h"
11505b261ecSmrg#include "dixstruct.h"
11605b261ecSmrg#include "gcstruct.h"
11705b261ecSmrg#include "servermd.h"
118f7df2e56Smrg#include "mivalidate.h"
11905b261ecSmrg#ifdef PANORAMIX
12005b261ecSmrg#include "panoramiX.h"
12105b261ecSmrg#include "panoramiXsrv.h"
12205b261ecSmrg#endif
12305b261ecSmrg#include "dixevents.h"
12405b261ecSmrg#include "globals.h"
125f7df2e56Smrg#include "mi.h"                 /* miPaintWindow */
126f7df2e56Smrg#ifdef COMPOSITE
127f7df2e56Smrg#include "compint.h"
128f7df2e56Smrg#endif
129f7df2e56Smrg#include "selection.h"
130f7df2e56Smrg#include "inpututils.h"
13105b261ecSmrg
132637ac9abSmrg#include "privates.h"
13305b261ecSmrg#include "xace.h"
134f7df2e56Smrg#include "exevents.h"
135f7df2e56Smrg
136f7df2e56Smrg#include <X11/Xatom.h>          /* must come after server includes */
13705b261ecSmrg
13805b261ecSmrg/******
139f7df2e56Smrg * Window stuff for server
14005b261ecSmrg *
14105b261ecSmrg *    CreateRootWindow, CreateWindow, ChangeWindowAttributes,
14205b261ecSmrg *    GetWindowAttributes, DeleteWindow, DestroySubWindows,
14305b261ecSmrg *    HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows,
14405b261ecSmrg *    UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow,
145637ac9abSmrg *    ChangeWindowDeviceCursor
14605b261ecSmrg ******/
14705b261ecSmrg
14865b04b38SmrgBool bgNoneRoot = FALSE;
14965b04b38Smrg
150f7df2e56Smrgstatic unsigned char _back_lsb[4] = { 0x88, 0x22, 0x44, 0x11 };
151f7df2e56Smrgstatic unsigned char _back_msb[4] = { 0x11, 0x44, 0x22, 0x88 };
152f7df2e56Smrg
153f7df2e56Smrgstatic Bool WindowParentHasDeviceCursor(WindowPtr pWin,
154f7df2e56Smrg                                        DeviceIntPtr pDev, CursorPtr pCurs);
155f7df2e56Smrgstatic Bool
15605b261ecSmrg
157f7df2e56SmrgWindowSeekDeviceCursor(WindowPtr pWin,
158f7df2e56Smrg                       DeviceIntPtr pDev,
159f7df2e56Smrg                       DevCursNodePtr * pNode, DevCursNodePtr * pPrev);
160637ac9abSmrg
1614202a189Smrgint screenIsSaved = SCREEN_SAVER_OFF;
16205b261ecSmrg
1634202a189Smrgstatic Bool TileScreenSaver(ScreenPtr pScreen, int kind);
16405b261ecSmrg
16505b261ecSmrg#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \
16605b261ecSmrg			      CWDontPropagate | CWOverrideRedirect | CWCursor )
16705b261ecSmrg
16805b261ecSmrg#define BOXES_OVERLAP(b1, b2) \
16905b261ecSmrg      (!( ((b1)->x2 <= (b2)->x1)  || \
17005b261ecSmrg	( ((b1)->x1 >= (b2)->x2)) || \
17105b261ecSmrg	( ((b1)->y2 <= (b2)->y1)) || \
17205b261ecSmrg	( ((b1)->y1 >= (b2)->y2)) ) )
17305b261ecSmrg
17405b261ecSmrg#define RedirectSend(pWin) \
17505b261ecSmrg    ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask)
17605b261ecSmrg
17705b261ecSmrg#define SubSend(pWin) \
17805b261ecSmrg    ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask)
17905b261ecSmrg
18005b261ecSmrg#define StrSend(pWin) \
18105b261ecSmrg    ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask)
18205b261ecSmrg
18305b261ecSmrg#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent))
18405b261ecSmrg
185f7df2e56Smrg#ifdef COMPOSITE
186f7df2e56Smrgstatic const char *overlay_win_name = "<composite overlay>";
187f7df2e56Smrg#endif
188f7df2e56Smrg
189f7df2e56Smrgstatic const char *
190f7df2e56Smrgget_window_name(WindowPtr pWin)
191f7df2e56Smrg{
192f7df2e56Smrg#define WINDOW_NAME_BUF_LEN 512
193f7df2e56Smrg    PropertyPtr prop;
194f7df2e56Smrg    static char buf[WINDOW_NAME_BUF_LEN];
195f7df2e56Smrg    int len;
196f7df2e56Smrg
197f7df2e56Smrg#ifdef COMPOSITE
198f7df2e56Smrg    CompScreenPtr comp_screen = GetCompScreen(pWin->drawable.pScreen);
199f7df2e56Smrg
200f7df2e56Smrg    if (comp_screen && pWin == comp_screen->pOverlayWin)
201f7df2e56Smrg        return overlay_win_name;
202f7df2e56Smrg#endif
203f7df2e56Smrg
204f7df2e56Smrg    for (prop = wUserProps(pWin); prop; prop = prop->next) {
205f7df2e56Smrg        if (prop->propertyName == XA_WM_NAME && prop->type == XA_STRING &&
206f7df2e56Smrg            prop->data) {
207f7df2e56Smrg            len = min(prop->size, WINDOW_NAME_BUF_LEN - 1);
208f7df2e56Smrg            memcpy(buf, prop->data, len);
209f7df2e56Smrg            buf[len] = '\0';
210f7df2e56Smrg            return buf;
211f7df2e56Smrg        }
212f7df2e56Smrg    }
213f7df2e56Smrg
214f7df2e56Smrg    return NULL;
215f7df2e56Smrg#undef WINDOW_NAME_BUF_LEN
216f7df2e56Smrg}
21705b261ecSmrg
21805b261ecSmrgstatic void
219f7df2e56Smrglog_window_info(WindowPtr pWin, int depth)
22005b261ecSmrg{
22105b261ecSmrg    int i;
222f7df2e56Smrg    const char *win_name, *visibility;
223f7df2e56Smrg    BoxPtr rects;
224f7df2e56Smrg
225f7df2e56Smrg    for (i = 0; i < (depth << 2); i++)
226f7df2e56Smrg        ErrorF(" ");
227f7df2e56Smrg
228f7df2e56Smrg    win_name = get_window_name(pWin);
229f7df2e56Smrg    ErrorF("win 0x%.8x (%s), [%d, %d] to [%d, %d]",
230f7df2e56Smrg           (unsigned) pWin->drawable.id,
231f7df2e56Smrg           win_name ? win_name : "no name",
232f7df2e56Smrg           pWin->drawable.x, pWin->drawable.y,
233f7df2e56Smrg           pWin->drawable.x + pWin->drawable.width,
234f7df2e56Smrg           pWin->drawable.y + pWin->drawable.height);
235f7df2e56Smrg
236f7df2e56Smrg    if (pWin->overrideRedirect)
237f7df2e56Smrg        ErrorF(" (override redirect)");
238f7df2e56Smrg#ifdef COMPOSITE
239f7df2e56Smrg    if (pWin->redirectDraw)
240f7df2e56Smrg        ErrorF(" (%s compositing: pixmap %x)",
241f7df2e56Smrg               (pWin->redirectDraw == RedirectDrawAutomatic) ?
242f7df2e56Smrg               "automatic" : "manual",
243f7df2e56Smrg               (unsigned) pWin->drawable.pScreen->GetWindowPixmap(pWin)->drawable.id);
244f7df2e56Smrg#endif
24505b261ecSmrg
246f7df2e56Smrg    switch (pWin->visibility) {
247f7df2e56Smrg    case VisibilityUnobscured:
248f7df2e56Smrg        visibility = "unobscured";
249f7df2e56Smrg        break;
250f7df2e56Smrg    case VisibilityPartiallyObscured:
251f7df2e56Smrg        visibility = "partially obscured";
252f7df2e56Smrg        break;
253f7df2e56Smrg    case VisibilityFullyObscured:
254f7df2e56Smrg        visibility = "fully obscured";
255f7df2e56Smrg        break;
256f7df2e56Smrg    case VisibilityNotViewable:
257f7df2e56Smrg        visibility = "unviewable";
258f7df2e56Smrg        break;
259f7df2e56Smrg    }
260f7df2e56Smrg    ErrorF(", %s", visibility);
261f7df2e56Smrg
262f7df2e56Smrg    if (RegionNotEmpty(&pWin->clipList)) {
263f7df2e56Smrg        ErrorF(", clip list:");
264f7df2e56Smrg        rects = RegionRects(&pWin->clipList);
265f7df2e56Smrg        for (i = 0; i < RegionNumRects(&pWin->clipList); i++)
266f7df2e56Smrg            ErrorF(" [(%d, %d) to (%d, %d)]",
267f7df2e56Smrg                   rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
268f7df2e56Smrg        ErrorF("; extents [(%d, %d) to (%d, %d)]",
269f7df2e56Smrg               pWin->clipList.extents.x1, pWin->clipList.extents.y1,
270f7df2e56Smrg               pWin->clipList.extents.x2, pWin->clipList.extents.y2);
271f7df2e56Smrg    }
272f7df2e56Smrg
273f7df2e56Smrg    ErrorF("\n");
274f7df2e56Smrg}
275f7df2e56Smrg
276f7df2e56Smrgstatic const char*
277f7df2e56Smrggrab_grabtype_to_text(GrabPtr pGrab)
278f7df2e56Smrg{
279f7df2e56Smrg    switch (pGrab->grabtype) {
280f7df2e56Smrg        case XI2:
281f7df2e56Smrg            return "xi2";
282f7df2e56Smrg        case CORE:
283f7df2e56Smrg            return "core";
284f7df2e56Smrg        default:
285f7df2e56Smrg            return "xi1";
286f7df2e56Smrg    }
287f7df2e56Smrg}
288f7df2e56Smrg
289f7df2e56Smrgstatic const char*
290f7df2e56Smrggrab_type_to_text(GrabPtr pGrab)
291f7df2e56Smrg{
292f7df2e56Smrg    switch (pGrab->type) {
293f7df2e56Smrg        case ButtonPress:
294f7df2e56Smrg            return "ButtonPress";
295f7df2e56Smrg        case KeyPress:
296f7df2e56Smrg            return "KeyPress";
297f7df2e56Smrg        case XI_Enter:
298f7df2e56Smrg            return "XI_Enter";
299f7df2e56Smrg        case XI_FocusIn:
300f7df2e56Smrg            return "XI_FocusIn";
301f7df2e56Smrg        default:
302f7df2e56Smrg            return "unknown?!";
30305b261ecSmrg    }
30405b261ecSmrg}
30505b261ecSmrg
30605b261ecSmrgstatic void
307f7df2e56Smrglog_grab_info(void *value, XID id, void *cdata)
308f7df2e56Smrg{
309f7df2e56Smrg    int i, j;
310f7df2e56Smrg    GrabPtr pGrab = (GrabPtr)value;
311f7df2e56Smrg
312f7df2e56Smrg    ErrorF("  grab 0x%lx (%s), type '%s' on window 0x%lx\n",
313f7df2e56Smrg           (unsigned long) pGrab->resource,
314f7df2e56Smrg           grab_grabtype_to_text(pGrab),
315f7df2e56Smrg           grab_type_to_text(pGrab),
316f7df2e56Smrg           (unsigned long) pGrab->window->drawable.id);
317f7df2e56Smrg    ErrorF("    detail %d (mask %lu), modifiersDetail %d (mask %lu)\n",
318f7df2e56Smrg           pGrab->detail.exact,
319f7df2e56Smrg           pGrab->detail.pMask ? (unsigned long) *(pGrab->detail.pMask) : 0,
320f7df2e56Smrg           pGrab->modifiersDetail.exact,
321f7df2e56Smrg           pGrab->modifiersDetail.pMask ?
322f7df2e56Smrg           (unsigned long) *(pGrab->modifiersDetail.pMask) :
323f7df2e56Smrg           (unsigned long) 0);
324f7df2e56Smrg    ErrorF("    device '%s' (%d), modifierDevice '%s' (%d)\n",
325f7df2e56Smrg           pGrab->device->name, pGrab->device->id,
326f7df2e56Smrg           pGrab->modifierDevice->name, pGrab->modifierDevice->id);
327f7df2e56Smrg    if (pGrab->grabtype == CORE) {
328f7df2e56Smrg        ErrorF("    core event mask 0x%lx\n",
329f7df2e56Smrg               (unsigned long) pGrab->eventMask);
330f7df2e56Smrg    }
331f7df2e56Smrg    else if (pGrab->grabtype == XI) {
332f7df2e56Smrg        ErrorF("    xi1 event mask 0x%lx\n",
333f7df2e56Smrg               (unsigned long) pGrab->eventMask);
334f7df2e56Smrg    }
335f7df2e56Smrg    else if (pGrab->grabtype == XI2) {
336f7df2e56Smrg        for (i = 0; i < xi2mask_num_masks(pGrab->xi2mask); i++) {
337f7df2e56Smrg            const unsigned char *mask;
338f7df2e56Smrg            int print;
339f7df2e56Smrg
340f7df2e56Smrg            print = 0;
341f7df2e56Smrg            for (j = 0; j < XI2MASKSIZE; j++) {
342f7df2e56Smrg                mask = xi2mask_get_one_mask(pGrab->xi2mask, i);
343f7df2e56Smrg                if (mask[j]) {
344f7df2e56Smrg                    print = 1;
345f7df2e56Smrg                    break;
346f7df2e56Smrg                }
347f7df2e56Smrg            }
348f7df2e56Smrg            if (!print)
349f7df2e56Smrg                continue;
350f7df2e56Smrg            ErrorF("      xi2 event mask 0x");
351f7df2e56Smrg            for (j = 0; j < xi2mask_mask_size(pGrab->xi2mask); j++)
352f7df2e56Smrg                ErrorF("%x ", mask[j]);
353f7df2e56Smrg            ErrorF("\n");
354f7df2e56Smrg        }
355f7df2e56Smrg    }
356f7df2e56Smrg    ErrorF("    owner-events %s, kb %d ptr %d, confine 0x%lx, cursor 0x%lx\n",
357f7df2e56Smrg           pGrab->ownerEvents ? "true" : "false",
358f7df2e56Smrg           pGrab->keyboardMode, pGrab->pointerMode,
359f7df2e56Smrg           pGrab->confineTo ? (unsigned long) pGrab->confineTo->drawable.id : 0,
360f7df2e56Smrg           pGrab->cursor ? (unsigned long) pGrab->cursor->id : 0);
361f7df2e56Smrg}
362f7df2e56Smrg
363f7df2e56Smrgvoid
364f7df2e56SmrgPrintPassiveGrabs(void)
36505b261ecSmrg{
36605b261ecSmrg    int i;
367f7df2e56Smrg    LocalClientCredRec *lcc;
368f7df2e56Smrg    pid_t clientpid;
369f7df2e56Smrg    const char *cmdname;
370f7df2e56Smrg    const char *cmdargs;
371f7df2e56Smrg
372f7df2e56Smrg    ErrorF("Printing all currently registered grabs\n");
373f7df2e56Smrg
374f7df2e56Smrg    for (i = 1; i < currentMaxClients; i++) {
375f7df2e56Smrg        if (!clients[i] || clients[i]->clientState != ClientStateRunning)
376f7df2e56Smrg            continue;
377f7df2e56Smrg
378f7df2e56Smrg        clientpid = GetClientPid(clients[i]);
379f7df2e56Smrg        cmdname = GetClientCmdName(clients[i]);
380f7df2e56Smrg        cmdargs = GetClientCmdArgs(clients[i]);
381f7df2e56Smrg        if ((clientpid > 0) && (cmdname != NULL)) {
382f7df2e56Smrg            ErrorF("  Printing all registered grabs of client pid %ld %s %s\n",
383f7df2e56Smrg                   (long) clientpid, cmdname, cmdargs ? cmdargs : "");
384f7df2e56Smrg        } else {
385f7df2e56Smrg            if (GetLocalClientCreds(clients[i], &lcc) == -1) {
386f7df2e56Smrg                ErrorF("  GetLocalClientCreds() failed\n");
387f7df2e56Smrg                continue;
388f7df2e56Smrg            }
389f7df2e56Smrg            ErrorF("  Printing all registered grabs of client pid %ld uid %ld gid %ld\n",
390f7df2e56Smrg                   (lcc->fieldsSet & LCC_PID_SET) ? (long) lcc->pid : 0,
391f7df2e56Smrg                   (lcc->fieldsSet & LCC_UID_SET) ? (long) lcc->euid : 0,
392f7df2e56Smrg                   (lcc->fieldsSet & LCC_GID_SET) ? (long) lcc->egid : 0);
393f7df2e56Smrg            FreeLocalClientCreds(lcc);
394f7df2e56Smrg        }
39505b261ecSmrg
396f7df2e56Smrg        FindClientResourcesByType(clients[i], RT_PASSIVEGRAB, log_grab_info, NULL);
397f7df2e56Smrg    }
398f7df2e56Smrg    ErrorF("End list of registered passive grabs\n");
399f7df2e56Smrg}
400f7df2e56Smrg
401f7df2e56Smrgvoid
402f7df2e56SmrgPrintWindowTree(void)
403f7df2e56Smrg{
404f7df2e56Smrg    int scrnum, depth;
405f7df2e56Smrg    ScreenPtr pScreen;
406f7df2e56Smrg    WindowPtr pWin;
407f7df2e56Smrg
408f7df2e56Smrg    for (scrnum = 0; scrnum < screenInfo.numScreens; scrnum++) {
409f7df2e56Smrg        pScreen = screenInfo.screens[scrnum];
410f7df2e56Smrg        ErrorF("[dix] Dumping windows for screen %d (pixmap %x):\n", scrnum,
411f7df2e56Smrg               (unsigned) pScreen->GetScreenPixmap(pScreen)->drawable.id);
412f7df2e56Smrg        pWin = pScreen->root;
413f7df2e56Smrg        depth = 1;
414f7df2e56Smrg        while (pWin) {
415f7df2e56Smrg            log_window_info(pWin, depth);
416f7df2e56Smrg            if (pWin->firstChild) {
417f7df2e56Smrg                pWin = pWin->firstChild;
418f7df2e56Smrg                depth++;
419f7df2e56Smrg                continue;
420f7df2e56Smrg            }
421f7df2e56Smrg            while (pWin && !pWin->nextSib) {
422f7df2e56Smrg                pWin = pWin->parent;
423f7df2e56Smrg                depth--;
424f7df2e56Smrg            }
425f7df2e56Smrg            if (!pWin)
426f7df2e56Smrg                break;
427f7df2e56Smrg            pWin = pWin->nextSib;
428f7df2e56Smrg        }
42905b261ecSmrg    }
43005b261ecSmrg}
43105b261ecSmrg
4324202a189Smrgint
433f7df2e56SmrgTraverseTree(WindowPtr pWin, VisitWindowProcPtr func, void *data)
43405b261ecSmrg{
43505b261ecSmrg    int result;
43605b261ecSmrg    WindowPtr pChild;
43705b261ecSmrg
43805b261ecSmrg    if (!(pChild = pWin))
439f7df2e56Smrg        return WT_NOMATCH;
440f7df2e56Smrg    while (1) {
441f7df2e56Smrg        result = (*func) (pChild, data);
442f7df2e56Smrg        if (result == WT_STOPWALKING)
443f7df2e56Smrg            return WT_STOPWALKING;
444f7df2e56Smrg        if ((result == WT_WALKCHILDREN) && pChild->firstChild) {
445f7df2e56Smrg            pChild = pChild->firstChild;
446f7df2e56Smrg            continue;
447f7df2e56Smrg        }
448f7df2e56Smrg        while (!pChild->nextSib && (pChild != pWin))
449f7df2e56Smrg            pChild = pChild->parent;
450f7df2e56Smrg        if (pChild == pWin)
451f7df2e56Smrg            break;
452f7df2e56Smrg        pChild = pChild->nextSib;
45305b261ecSmrg    }
4544202a189Smrg    return WT_NOMATCH;
45505b261ecSmrg}
45605b261ecSmrg
45705b261ecSmrg/*****
45805b261ecSmrg * WalkTree
4597e31ba66Smrg *   Walk the window tree, for SCREEN, performing FUNC(pWin, data) on
46005b261ecSmrg *   each window.  If FUNC returns WT_WALKCHILDREN, traverse the children,
4617e31ba66Smrg *   if it returns WT_DONTWALKCHILDREN, don't.  If it returns WT_STOPWALKING,
46205b261ecSmrg *   exit WalkTree.  Does depth-first traverse.
46305b261ecSmrg *****/
46405b261ecSmrg
4654202a189Smrgint
466f7df2e56SmrgWalkTree(ScreenPtr pScreen, VisitWindowProcPtr func, void *data)
46705b261ecSmrg{
468f7df2e56Smrg    return (TraverseTree(pScreen->root, func, data));
46905b261ecSmrg}
47005b261ecSmrg
47105b261ecSmrg/* hack for forcing backing store on all windows */
472f7df2e56Smrgint defaultBackingStore = NotUseful;
473f7df2e56Smrg
47405b261ecSmrg/* hack to force no backing store */
475f7df2e56SmrgBool disableBackingStore = FALSE;
476f7df2e56SmrgBool enableBackingStore = FALSE;
47705b261ecSmrg
47805b261ecSmrgstatic void
47905b261ecSmrgSetWindowToDefaults(WindowPtr pWin)
48005b261ecSmrg{
48105b261ecSmrg    pWin->prevSib = NullWindow;
48205b261ecSmrg    pWin->firstChild = NullWindow;
48305b261ecSmrg    pWin->lastChild = NullWindow;
48405b261ecSmrg
485f7df2e56Smrg    pWin->valdata = NULL;
486f7df2e56Smrg    pWin->optional = NULL;
48705b261ecSmrg    pWin->cursorIsNone = TRUE;
48805b261ecSmrg
48905b261ecSmrg    pWin->backingStore = NotUseful;
490f7df2e56Smrg    pWin->backStorage = 0;
49105b261ecSmrg
492f7df2e56Smrg    pWin->mapped = FALSE;       /* off */
493f7df2e56Smrg    pWin->realized = FALSE;     /* off */
49405b261ecSmrg    pWin->viewable = FALSE;
49505b261ecSmrg    pWin->visibility = VisibilityNotViewable;
49605b261ecSmrg    pWin->overrideRedirect = FALSE;
49705b261ecSmrg    pWin->saveUnder = FALSE;
49805b261ecSmrg
49905b261ecSmrg    pWin->bitGravity = ForgetGravity;
50005b261ecSmrg    pWin->winGravity = NorthWestGravity;
50105b261ecSmrg
50205b261ecSmrg    pWin->eventMask = 0;
50305b261ecSmrg    pWin->deliverableEvents = 0;
50405b261ecSmrg    pWin->dontPropagate = 0;
50505b261ecSmrg    pWin->forcedBS = FALSE;
50605b261ecSmrg    pWin->redirectDraw = RedirectDrawNone;
507637ac9abSmrg    pWin->forcedBG = FALSE;
508f7df2e56Smrg    pWin->unhittable = FALSE;
50965b04b38Smrg
51065b04b38Smrg#ifdef COMPOSITE
51165b04b38Smrg    pWin->damagedDescendants = FALSE;
51265b04b38Smrg#endif
51305b261ecSmrg}
51405b261ecSmrg
51505b261ecSmrgstatic void
51605b261ecSmrgMakeRootTile(WindowPtr pWin)
51705b261ecSmrg{
51805b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
51905b261ecSmrg    GCPtr pGC;
52005b261ecSmrg    unsigned char back[128];
52105b261ecSmrg    int len = BitmapBytePad(sizeof(long));
52205b261ecSmrg    unsigned char *from, *to;
52305b261ecSmrg    int i, j;
52405b261ecSmrg
525f7df2e56Smrg    pWin->background.pixmap = (*pScreen->CreatePixmap) (pScreen, 4, 4,
526f7df2e56Smrg                                                        pScreen->rootDepth, 0);
52705b261ecSmrg
52805b261ecSmrg    pWin->backgroundState = BackgroundPixmap;
52905b261ecSmrg    pGC = GetScratchGC(pScreen->rootDepth, pScreen);
53005b261ecSmrg    if (!pWin->background.pixmap || !pGC)
531f7df2e56Smrg        FatalError("could not create root tile");
53205b261ecSmrg
53305b261ecSmrg    {
534f7df2e56Smrg        ChangeGCVal attributes[2];
53505b261ecSmrg
536f7df2e56Smrg        attributes[0].val = pScreen->whitePixel;
537f7df2e56Smrg        attributes[1].val = pScreen->blackPixel;
53805b261ecSmrg
539f7df2e56Smrg        (void) ChangeGC(NullClient, pGC, GCForeground | GCBackground,
540f7df2e56Smrg                        attributes);
54105b261ecSmrg    }
54205b261ecSmrg
543f7df2e56Smrg    ValidateGC((DrawablePtr) pWin->background.pixmap, pGC);
54405b261ecSmrg
545f7df2e56Smrg    from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb;
546f7df2e56Smrg    to = back;
54705b261ecSmrg
548f7df2e56Smrg    for (i = 4; i > 0; i--, from++)
549f7df2e56Smrg        for (j = len; j > 0; j--)
550f7df2e56Smrg            *to++ = *from;
55105b261ecSmrg
552f7df2e56Smrg    (*pGC->ops->PutImage) ((DrawablePtr) pWin->background.pixmap, pGC, 1,
553f7df2e56Smrg                           0, 0, len, 4, 0, XYBitmap, (char *) back);
55405b261ecSmrg
555f7df2e56Smrg    FreeScratchGC(pGC);
55605b261ecSmrg
55705b261ecSmrg}
55805b261ecSmrg
55905b261ecSmrg/*****
56005b261ecSmrg * CreateRootWindow
56105b261ecSmrg *    Makes a window at initialization time for specified screen
56205b261ecSmrg *****/
56305b261ecSmrg
56405b261ecSmrgBool
56505b261ecSmrgCreateRootWindow(ScreenPtr pScreen)
56605b261ecSmrg{
567f7df2e56Smrg    WindowPtr pWin;
568f7df2e56Smrg    BoxRec box;
56905b261ecSmrg    PixmapFormatRec *format;
57005b261ecSmrg
571f7df2e56Smrg    pWin = dixAllocateScreenObjectWithPrivates(pScreen, WindowRec, PRIVATE_WINDOW);
57205b261ecSmrg    if (!pWin)
573f7df2e56Smrg        return FALSE;
57405b261ecSmrg
5754202a189Smrg    pScreen->screensaver.pWindow = NULL;
5764202a189Smrg    pScreen->screensaver.wid = FakeClientID(0);
5774202a189Smrg    pScreen->screensaver.ExternalScreenSaver = NULL;
57805b261ecSmrg    screenIsSaved = SCREEN_SAVER_OFF;
57905b261ecSmrg
5804202a189Smrg    pScreen->root = pWin;
58105b261ecSmrg
58205b261ecSmrg    pWin->drawable.pScreen = pScreen;
58305b261ecSmrg    pWin->drawable.type = DRAWABLE_WINDOW;
58405b261ecSmrg
58505b261ecSmrg    pWin->drawable.depth = pScreen->rootDepth;
58605b261ecSmrg    for (format = screenInfo.formats;
587f7df2e56Smrg         format->depth != pScreen->rootDepth; format++);
58805b261ecSmrg    pWin->drawable.bitsPerPixel = format->bitsPerPixel;
58905b261ecSmrg
59005b261ecSmrg    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
59105b261ecSmrg
59205b261ecSmrg    pWin->parent = NullWindow;
59305b261ecSmrg    SetWindowToDefaults(pWin);
59405b261ecSmrg
595f7df2e56Smrg    pWin->optional = malloc(sizeof(WindowOptRec));
59605b261ecSmrg    if (!pWin->optional)
59705b261ecSmrg        return FALSE;
59805b261ecSmrg
59905b261ecSmrg    pWin->optional->dontPropagateMask = 0;
60005b261ecSmrg    pWin->optional->otherEventMasks = 0;
60105b261ecSmrg    pWin->optional->otherClients = NULL;
60205b261ecSmrg    pWin->optional->passiveGrabs = NULL;
60305b261ecSmrg    pWin->optional->userProps = NULL;
60405b261ecSmrg    pWin->optional->backingBitPlanes = ~0L;
60505b261ecSmrg    pWin->optional->backingPixel = 0;
60605b261ecSmrg    pWin->optional->boundingShape = NULL;
60705b261ecSmrg    pWin->optional->clipShape = NULL;
60805b261ecSmrg    pWin->optional->inputShape = NULL;
60905b261ecSmrg    pWin->optional->inputMasks = NULL;
610637ac9abSmrg    pWin->optional->deviceCursors = NULL;
61105b261ecSmrg    pWin->optional->colormap = pScreen->defColormap;
61205b261ecSmrg    pWin->optional->visual = pScreen->rootVisual;
61305b261ecSmrg
61405b261ecSmrg    pWin->nextSib = NullWindow;
61505b261ecSmrg
61605b261ecSmrg    pWin->drawable.id = FakeClientID(0);
61705b261ecSmrg
61805b261ecSmrg    pWin->origin.x = pWin->origin.y = 0;
61905b261ecSmrg    pWin->drawable.height = pScreen->height;
62005b261ecSmrg    pWin->drawable.width = pScreen->width;
62105b261ecSmrg    pWin->drawable.x = pWin->drawable.y = 0;
62205b261ecSmrg
62305b261ecSmrg    box.x1 = 0;
62405b261ecSmrg    box.y1 = 0;
62505b261ecSmrg    box.x2 = pScreen->width;
62605b261ecSmrg    box.y2 = pScreen->height;
6274202a189Smrg    RegionInit(&pWin->clipList, &box, 1);
6284202a189Smrg    RegionInit(&pWin->winSize, &box, 1);
6294202a189Smrg    RegionInit(&pWin->borderSize, &box, 1);
6304202a189Smrg    RegionInit(&pWin->borderClip, &box, 1);
63105b261ecSmrg
63205b261ecSmrg    pWin->drawable.class = InputOutput;
63305b261ecSmrg    pWin->optional->visual = pScreen->rootVisual;
63405b261ecSmrg
63505b261ecSmrg    pWin->backgroundState = BackgroundPixel;
63605b261ecSmrg    pWin->background.pixel = pScreen->whitePixel;
63705b261ecSmrg
63805b261ecSmrg    pWin->borderIsPixel = TRUE;
63905b261ecSmrg    pWin->border.pixel = pScreen->blackPixel;
64005b261ecSmrg    pWin->borderWidth = 0;
64105b261ecSmrg
642637ac9abSmrg    /*  security creation/labeling check
643637ac9abSmrg     */
644637ac9abSmrg    if (XaceHook(XACE_RESOURCE_ACCESS, serverClient, pWin->drawable.id,
645f7df2e56Smrg                 RT_WINDOW, pWin, RT_NONE, NULL, DixCreateAccess))
646f7df2e56Smrg        return FALSE;
647637ac9abSmrg
648f7df2e56Smrg    if (!AddResource(pWin->drawable.id, RT_WINDOW, (void *) pWin))
649f7df2e56Smrg        return FALSE;
65005b261ecSmrg
65105b261ecSmrg    if (disableBackingStore)
652f7df2e56Smrg        pScreen->backingStoreSupport = NotUseful;
65305b261ecSmrg    if (enableBackingStore)
654f7df2e56Smrg        pScreen->backingStoreSupport = WhenMapped;
655f7df2e56Smrg#ifdef COMPOSITE
656f7df2e56Smrg    if (noCompositeExtension)
657f7df2e56Smrg        pScreen->backingStoreSupport = NotUseful;
658f7df2e56Smrg#endif
65905b261ecSmrg
660637ac9abSmrg    pScreen->saveUnderSupport = NotUseful;
66105b261ecSmrg
66205b261ecSmrg    return TRUE;
66305b261ecSmrg}
66405b261ecSmrg
66505b261ecSmrgvoid
66605b261ecSmrgInitRootWindow(WindowPtr pWin)
66705b261ecSmrg{
66805b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
66905b261ecSmrg    int backFlag = CWBorderPixel | CWCursor | CWBackingStore;
67005b261ecSmrg
671f7df2e56Smrg    if (!(*pScreen->CreateWindow) (pWin))
672f7df2e56Smrg        return;                 /* XXX */
673f7df2e56Smrg    (*pScreen->PositionWindow) (pWin, 0, 0);
67405b261ecSmrg
67505b261ecSmrg    pWin->cursorIsNone = FALSE;
676f7df2e56Smrg    pWin->optional->cursor = RefCursor(rootCursor);
677637ac9abSmrg
678637ac9abSmrg    if (party_like_its_1989) {
67905b261ecSmrg        MakeRootTile(pWin);
68005b261ecSmrg        backFlag |= CWBackPixmap;
681f7df2e56Smrg    }
682f7df2e56Smrg    else if (pScreen->canDoBGNoneRoot && bgNoneRoot) {
68365b04b38Smrg        pWin->backgroundState = XaceBackgroundNoneState(pWin);
68465b04b38Smrg        pWin->background.pixel = pScreen->whitePixel;
68565b04b38Smrg        backFlag |= CWBackPixmap;
686f7df2e56Smrg    }
687f7df2e56Smrg    else {
68865b04b38Smrg        pWin->backgroundState = BackgroundPixel;
689f7df2e56Smrg        if (whiteRoot)
69005b261ecSmrg            pWin->background.pixel = pScreen->whitePixel;
691637ac9abSmrg        else
692637ac9abSmrg            pWin->background.pixel = pScreen->blackPixel;
69305b261ecSmrg        backFlag |= CWBackPixel;
694f7df2e56Smrg    }
69505b261ecSmrg
69605b261ecSmrg    pWin->backingStore = defaultBackingStore;
69705b261ecSmrg    pWin->forcedBS = (defaultBackingStore != NotUseful);
69805b261ecSmrg    /* We SHOULD check for an error value here XXX */
699f7df2e56Smrg    (*pScreen->ChangeWindowAttributes) (pWin, backFlag);
70005b261ecSmrg
70105b261ecSmrg    MapWindow(pWin, serverClient);
70205b261ecSmrg}
70305b261ecSmrg
70405b261ecSmrg/* Set the region to the intersection of the rectangle and the
70505b261ecSmrg * window's winSize.  The window is typically the parent of the
70605b261ecSmrg * window from which the region came.
70705b261ecSmrg */
70805b261ecSmrg
70905b261ecSmrgstatic void
710f7df2e56SmrgClippedRegionFromBox(WindowPtr pWin, RegionPtr Rgn, int x, int y, int w, int h)
71105b261ecSmrg{
7124202a189Smrg    BoxRec box = *RegionExtents(&pWin->winSize);
71305b261ecSmrg
71405b261ecSmrg    /* we do these calculations to avoid overflows */
71505b261ecSmrg    if (x > box.x1)
716f7df2e56Smrg        box.x1 = x;
71705b261ecSmrg    if (y > box.y1)
718f7df2e56Smrg        box.y1 = y;
71905b261ecSmrg    x += w;
72005b261ecSmrg    if (x < box.x2)
721f7df2e56Smrg        box.x2 = x;
72205b261ecSmrg    y += h;
72305b261ecSmrg    if (y < box.y2)
724f7df2e56Smrg        box.y2 = y;
72505b261ecSmrg    if (box.x1 > box.x2)
726f7df2e56Smrg        box.x2 = box.x1;
72705b261ecSmrg    if (box.y1 > box.y2)
728f7df2e56Smrg        box.y2 = box.y1;
7294202a189Smrg    RegionReset(Rgn, &box);
7304202a189Smrg    RegionIntersect(Rgn, Rgn, &pWin->winSize);
73105b261ecSmrg}
73205b261ecSmrg
73305b261ecSmrgstatic RealChildHeadProc realChildHeadProc = NULL;
73405b261ecSmrg
73505b261ecSmrgvoid
736f7df2e56SmrgRegisterRealChildHeadProc(RealChildHeadProc proc)
73705b261ecSmrg{
73805b261ecSmrg    realChildHeadProc = proc;
73905b261ecSmrg}
74005b261ecSmrg
74105b261ecSmrgWindowPtr
74205b261ecSmrgRealChildHead(WindowPtr pWin)
74305b261ecSmrg{
74405b261ecSmrg    if (realChildHeadProc) {
745f7df2e56Smrg        return realChildHeadProc(pWin);
74605b261ecSmrg    }
74705b261ecSmrg
74805b261ecSmrg    if (!pWin->parent &&
749f7df2e56Smrg        (screenIsSaved == SCREEN_SAVER_ON) &&
750f7df2e56Smrg        (HasSaverWindow(pWin->drawable.pScreen)))
751f7df2e56Smrg        return pWin->firstChild;
75205b261ecSmrg    else
753f7df2e56Smrg        return NullWindow;
75405b261ecSmrg}
75505b261ecSmrg
75605b261ecSmrg/*****
75705b261ecSmrg * CreateWindow
758f7df2e56Smrg *    Makes a window in response to client request
75905b261ecSmrg *****/
76005b261ecSmrg
7614202a189SmrgWindowPtr
76205b261ecSmrgCreateWindow(Window wid, WindowPtr pParent, int x, int y, unsigned w,
76305b261ecSmrg             unsigned h, unsigned bw, unsigned class, Mask vmask, XID *vlist,
76405b261ecSmrg             int depth, ClientPtr client, VisualID visual, int *error)
76505b261ecSmrg{
76605b261ecSmrg    WindowPtr pWin;
76705b261ecSmrg    WindowPtr pHead;
76805b261ecSmrg    ScreenPtr pScreen;
76905b261ecSmrg    int idepth, ivisual;
77005b261ecSmrg    Bool fOK;
77105b261ecSmrg    DepthPtr pDepth;
77205b261ecSmrg    PixmapFormatRec *format;
77305b261ecSmrg    WindowOptPtr ancwopt;
77405b261ecSmrg
77505b261ecSmrg    if (class == CopyFromParent)
776f7df2e56Smrg        class = pParent->drawable.class;
77705b261ecSmrg
778f7df2e56Smrg    if ((class != InputOutput) && (class != InputOnly)) {
779f7df2e56Smrg        *error = BadValue;
780f7df2e56Smrg        client->errorValue = class;
781f7df2e56Smrg        return NullWindow;
78205b261ecSmrg    }
78305b261ecSmrg
784f7df2e56Smrg    if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) {
785f7df2e56Smrg        *error = BadMatch;
786f7df2e56Smrg        return NullWindow;
78705b261ecSmrg    }
78805b261ecSmrg
789f7df2e56Smrg    if ((class == InputOnly) && ((bw != 0) || (depth != 0))) {
790f7df2e56Smrg        *error = BadMatch;
791f7df2e56Smrg        return NullWindow;
79205b261ecSmrg    }
79305b261ecSmrg
79405b261ecSmrg    pScreen = pParent->drawable.pScreen;
79505b261ecSmrg    if ((class == InputOutput) && (depth == 0))
796f7df2e56Smrg        depth = pParent->drawable.depth;
79705b261ecSmrg    ancwopt = pParent->optional;
79805b261ecSmrg    if (!ancwopt)
799f7df2e56Smrg        ancwopt = FindWindowWithOptional(pParent)->optional;
80005b261ecSmrg    if (visual == CopyFromParent) {
801f7df2e56Smrg        visual = ancwopt->visual;
80205b261ecSmrg    }
80305b261ecSmrg
80405b261ecSmrg    /* Find out if the depth and visual are acceptable for this Screen */
805f7df2e56Smrg    if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) {
806f7df2e56Smrg        fOK = FALSE;
807f7df2e56Smrg        for (idepth = 0; idepth < pScreen->numDepths; idepth++) {
808f7df2e56Smrg            pDepth = (DepthPtr) &pScreen->allowedDepths[idepth];
809f7df2e56Smrg            if ((depth == pDepth->depth) || (depth == 0)) {
810f7df2e56Smrg                for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) {
811f7df2e56Smrg                    if (visual == pDepth->vids[ivisual]) {
812f7df2e56Smrg                        fOK = TRUE;
813f7df2e56Smrg                        break;
814f7df2e56Smrg                    }
815f7df2e56Smrg                }
816f7df2e56Smrg            }
817f7df2e56Smrg        }
818f7df2e56Smrg        if (fOK == FALSE) {
819f7df2e56Smrg            *error = BadMatch;
820f7df2e56Smrg            return NullWindow;
821f7df2e56Smrg        }
82205b261ecSmrg    }
82305b261ecSmrg
82405b261ecSmrg    if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) &&
825f7df2e56Smrg        (class != InputOnly) && (depth != pParent->drawable.depth)) {
826f7df2e56Smrg        *error = BadMatch;
827f7df2e56Smrg        return NullWindow;
82805b261ecSmrg    }
82905b261ecSmrg
83005b261ecSmrg    if (((vmask & CWColormap) == 0) &&
831f7df2e56Smrg        (class != InputOnly) &&
832f7df2e56Smrg        ((visual != ancwopt->visual) || (ancwopt->colormap == None))) {
833f7df2e56Smrg        *error = BadMatch;
834f7df2e56Smrg        return NullWindow;
83505b261ecSmrg    }
83605b261ecSmrg
837f7df2e56Smrg    pWin = dixAllocateScreenObjectWithPrivates(pScreen, WindowRec, PRIVATE_WINDOW);
838f7df2e56Smrg    if (!pWin) {
839f7df2e56Smrg        *error = BadAlloc;
840f7df2e56Smrg        return NullWindow;
84105b261ecSmrg    }
84205b261ecSmrg    pWin->drawable = pParent->drawable;
84305b261ecSmrg    pWin->drawable.depth = depth;
84405b261ecSmrg    if (depth == pParent->drawable.depth)
845f7df2e56Smrg        pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel;
846f7df2e56Smrg    else {
847f7df2e56Smrg        for (format = screenInfo.formats; format->depth != depth; format++);
848f7df2e56Smrg        pWin->drawable.bitsPerPixel = format->bitsPerPixel;
84905b261ecSmrg    }
85005b261ecSmrg    if (class == InputOnly)
851f7df2e56Smrg        pWin->drawable.type = (short) UNDRAWABLE_WINDOW;
85205b261ecSmrg    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
85305b261ecSmrg
85405b261ecSmrg    pWin->drawable.id = wid;
85505b261ecSmrg    pWin->drawable.class = class;
85605b261ecSmrg
85705b261ecSmrg    pWin->parent = pParent;
85805b261ecSmrg    SetWindowToDefaults(pWin);
85905b261ecSmrg
860f7df2e56Smrg    if (visual != ancwopt->visual) {
861f7df2e56Smrg        if (!MakeWindowOptional(pWin)) {
862f7df2e56Smrg            dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
863f7df2e56Smrg            *error = BadAlloc;
864f7df2e56Smrg            return NullWindow;
865f7df2e56Smrg        }
866f7df2e56Smrg        pWin->optional->visual = visual;
867f7df2e56Smrg        pWin->optional->colormap = None;
86805b261ecSmrg    }
86905b261ecSmrg
87005b261ecSmrg    pWin->borderWidth = bw;
87105b261ecSmrg
872637ac9abSmrg    /*  security creation/labeling check
87305b261ecSmrg     */
874637ac9abSmrg    *error = XaceHook(XACE_RESOURCE_ACCESS, client, wid, RT_WINDOW, pWin,
875f7df2e56Smrg                      RT_WINDOW, pWin->parent,
876f7df2e56Smrg                      DixCreateAccess | DixSetAttrAccess);
877637ac9abSmrg    if (*error != Success) {
878f7df2e56Smrg        dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
879f7df2e56Smrg        return NullWindow;
88005b261ecSmrg    }
88105b261ecSmrg
882637ac9abSmrg    pWin->backgroundState = XaceBackgroundNoneState(pWin);
883637ac9abSmrg    pWin->background.pixel = pScreen->whitePixel;
884637ac9abSmrg
88505b261ecSmrg    pWin->borderIsPixel = pParent->borderIsPixel;
88605b261ecSmrg    pWin->border = pParent->border;
88705b261ecSmrg    if (pWin->borderIsPixel == FALSE)
888f7df2e56Smrg        pWin->border.pixmap->refcnt++;
889f7df2e56Smrg
890f7df2e56Smrg    pWin->origin.x = x + (int) bw;
891f7df2e56Smrg    pWin->origin.y = y + (int) bw;
89205b261ecSmrg    pWin->drawable.width = w;
89305b261ecSmrg    pWin->drawable.height = h;
894f7df2e56Smrg    pWin->drawable.x = pParent->drawable.x + x + (int) bw;
895f7df2e56Smrg    pWin->drawable.y = pParent->drawable.y + y + (int) bw;
89605b261ecSmrg
897f7df2e56Smrg    /* set up clip list correctly for unobscured WindowPtr */
8984202a189Smrg    RegionNull(&pWin->clipList);
8994202a189Smrg    RegionNull(&pWin->borderClip);
9004202a189Smrg    RegionNull(&pWin->winSize);
9014202a189Smrg    RegionNull(&pWin->borderSize);
90205b261ecSmrg
90305b261ecSmrg    pHead = RealChildHead(pParent);
904f7df2e56Smrg    if (pHead) {
905f7df2e56Smrg        pWin->nextSib = pHead->nextSib;
906f7df2e56Smrg        if (pHead->nextSib)
907f7df2e56Smrg            pHead->nextSib->prevSib = pWin;
908f7df2e56Smrg        else
909f7df2e56Smrg            pParent->lastChild = pWin;
910f7df2e56Smrg        pHead->nextSib = pWin;
911f7df2e56Smrg        pWin->prevSib = pHead;
91205b261ecSmrg    }
913f7df2e56Smrg    else {
914f7df2e56Smrg        pWin->nextSib = pParent->firstChild;
915f7df2e56Smrg        if (pParent->firstChild)
916f7df2e56Smrg            pParent->firstChild->prevSib = pWin;
917f7df2e56Smrg        else
918f7df2e56Smrg            pParent->lastChild = pWin;
919f7df2e56Smrg        pParent->firstChild = pWin;
92005b261ecSmrg    }
92105b261ecSmrg
922f7df2e56Smrg    SetWinSize(pWin);
923f7df2e56Smrg    SetBorderSize(pWin);
92405b261ecSmrg
92505b261ecSmrg    /* We SHOULD check for an error value here XXX */
926f7df2e56Smrg    if (!(*pScreen->CreateWindow) (pWin)) {
927f7df2e56Smrg        *error = BadAlloc;
928f7df2e56Smrg        DeleteWindow(pWin, None);
929f7df2e56Smrg        return NullWindow;
93005b261ecSmrg    }
93105b261ecSmrg    /* We SHOULD check for an error value here XXX */
932f7df2e56Smrg    (*pScreen->PositionWindow) (pWin, pWin->drawable.x, pWin->drawable.y);
93305b261ecSmrg
93405b261ecSmrg    if (!(vmask & CWEventMask))
935f7df2e56Smrg        RecalculateDeliverableEvents(pWin);
93605b261ecSmrg
93705b261ecSmrg    if (vmask)
938f7df2e56Smrg        *error = ChangeWindowAttributes(pWin, vmask, vlist, wClient(pWin));
93905b261ecSmrg    else
940f7df2e56Smrg        *error = Success;
94105b261ecSmrg
942f7df2e56Smrg    if (*error != Success) {
943f7df2e56Smrg        DeleteWindow(pWin, None);
944f7df2e56Smrg        return NullWindow;
945f7df2e56Smrg    }
946f7df2e56Smrg    if (!(vmask & CWBackingStore) && (defaultBackingStore != NotUseful)) {
947f7df2e56Smrg        XID value = defaultBackingStore;
948f7df2e56Smrg
949f7df2e56Smrg        (void) ChangeWindowAttributes(pWin, CWBackingStore, &value,
950f7df2e56Smrg                                      wClient(pWin));
951f7df2e56Smrg        pWin->forcedBS = TRUE;
952f7df2e56Smrg    }
953f7df2e56Smrg
954f7df2e56Smrg    if (SubSend(pParent)) {
955f7df2e56Smrg        xEvent event = {
956f7df2e56Smrg            .u.createNotify.window = wid,
957f7df2e56Smrg            .u.createNotify.parent = pParent->drawable.id,
958f7df2e56Smrg            .u.createNotify.x = x,
959f7df2e56Smrg            .u.createNotify.y = y,
960f7df2e56Smrg            .u.createNotify.width = w,
961f7df2e56Smrg            .u.createNotify.height = h,
962f7df2e56Smrg            .u.createNotify.borderWidth = bw,
963f7df2e56Smrg            .u.createNotify.override = pWin->overrideRedirect
964f7df2e56Smrg        };
965f7df2e56Smrg        event.u.u.type = CreateNotify;
966f7df2e56Smrg        DeliverEvents(pParent, &event, 1, NullWindow);
96705b261ecSmrg    }
96805b261ecSmrg    return pWin;
96905b261ecSmrg}
97005b261ecSmrg
97105b261ecSmrgstatic void
972f7df2e56SmrgDisposeWindowOptional(WindowPtr pWin)
97305b261ecSmrg{
97405b261ecSmrg    if (!pWin->optional)
975f7df2e56Smrg        return;
97605b261ecSmrg    /*
97705b261ecSmrg     * everything is peachy.  Delete the optional record
97805b261ecSmrg     * and clean up
97905b261ecSmrg     */
980f7df2e56Smrg    if (pWin->optional->cursor) {
981f7df2e56Smrg        FreeCursor(pWin->optional->cursor, (Cursor) 0);
982f7df2e56Smrg        pWin->cursorIsNone = FALSE;
98305b261ecSmrg    }
98405b261ecSmrg    else
985f7df2e56Smrg        pWin->cursorIsNone = TRUE;
986637ac9abSmrg
987f7df2e56Smrg    if (pWin->optional->deviceCursors) {
988637ac9abSmrg        DevCursorList pList;
989637ac9abSmrg        DevCursorList pPrev;
990f7df2e56Smrg
991637ac9abSmrg        pList = pWin->optional->deviceCursors;
992f7df2e56Smrg        while (pList) {
993637ac9abSmrg            if (pList->cursor)
994f7df2e56Smrg                FreeCursor(pList->cursor, (XID) 0);
995637ac9abSmrg            pPrev = pList;
996637ac9abSmrg            pList = pList->next;
9974202a189Smrg            free(pPrev);
998637ac9abSmrg        }
999637ac9abSmrg        pWin->optional->deviceCursors = NULL;
1000637ac9abSmrg    }
1001637ac9abSmrg
10024202a189Smrg    free(pWin->optional);
100305b261ecSmrg    pWin->optional = NULL;
100405b261ecSmrg}
100505b261ecSmrg
100605b261ecSmrgstatic void
100705b261ecSmrgFreeWindowResources(WindowPtr pWin)
100805b261ecSmrg{
100905b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
101005b261ecSmrg
101105b261ecSmrg    DeleteWindowFromAnySaveSet(pWin);
101205b261ecSmrg    DeleteWindowFromAnySelections(pWin);
101305b261ecSmrg    DeleteWindowFromAnyEvents(pWin, TRUE);
10144202a189Smrg    RegionUninit(&pWin->clipList);
10154202a189Smrg    RegionUninit(&pWin->winSize);
10164202a189Smrg    RegionUninit(&pWin->borderClip);
10174202a189Smrg    RegionUninit(&pWin->borderSize);
1018f7df2e56Smrg    if (wBoundingShape(pWin))
1019f7df2e56Smrg        RegionDestroy(wBoundingShape(pWin));
1020f7df2e56Smrg    if (wClipShape(pWin))
1021f7df2e56Smrg        RegionDestroy(wClipShape(pWin));
1022f7df2e56Smrg    if (wInputShape(pWin))
1023f7df2e56Smrg        RegionDestroy(wInputShape(pWin));
102405b261ecSmrg    if (pWin->borderIsPixel == FALSE)
1025f7df2e56Smrg        (*pScreen->DestroyPixmap) (pWin->border.pixmap);
102605b261ecSmrg    if (pWin->backgroundState == BackgroundPixmap)
1027f7df2e56Smrg        (*pScreen->DestroyPixmap) (pWin->background.pixmap);
102805b261ecSmrg
102905b261ecSmrg    DeleteAllWindowProperties(pWin);
103005b261ecSmrg    /* We SHOULD check for an error value here XXX */
1031f7df2e56Smrg    (*pScreen->DestroyWindow) (pWin);
1032f7df2e56Smrg    DisposeWindowOptional(pWin);
103305b261ecSmrg}
103405b261ecSmrg
103505b261ecSmrgstatic void
103605b261ecSmrgCrushTree(WindowPtr pWin)
103705b261ecSmrg{
103805b261ecSmrg    WindowPtr pChild, pSib, pParent;
103905b261ecSmrg    UnrealizeWindowProcPtr UnrealizeWindow;
104005b261ecSmrg
104105b261ecSmrg    if (!(pChild = pWin->firstChild))
1042f7df2e56Smrg        return;
104305b261ecSmrg    UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow;
1044f7df2e56Smrg    while (1) {
1045f7df2e56Smrg        if (pChild->firstChild) {
1046f7df2e56Smrg            pChild = pChild->firstChild;
1047f7df2e56Smrg            continue;
1048f7df2e56Smrg        }
1049f7df2e56Smrg        while (1) {
1050f7df2e56Smrg            pParent = pChild->parent;
1051f7df2e56Smrg            if (SubStrSend(pChild, pParent)) {
1052f7df2e56Smrg                xEvent event = { .u.u.type = DestroyNotify };
1053f7df2e56Smrg                event.u.destroyNotify.window = pChild->drawable.id;
1054f7df2e56Smrg                DeliverEvents(pChild, &event, 1, NullWindow);
1055f7df2e56Smrg            }
1056f7df2e56Smrg            FreeResource(pChild->drawable.id, RT_WINDOW);
1057f7df2e56Smrg            pSib = pChild->nextSib;
1058f7df2e56Smrg            pChild->viewable = FALSE;
1059f7df2e56Smrg            if (pChild->realized) {
1060f7df2e56Smrg                pChild->realized = FALSE;
1061f7df2e56Smrg                (*UnrealizeWindow) (pChild);
1062f7df2e56Smrg            }
1063f7df2e56Smrg            FreeWindowResources(pChild);
1064f7df2e56Smrg            dixFreeObjectWithPrivates(pChild, PRIVATE_WINDOW);
1065f7df2e56Smrg            if ((pChild = pSib))
1066f7df2e56Smrg                break;
1067f7df2e56Smrg            pChild = pParent;
1068f7df2e56Smrg            pChild->firstChild = NullWindow;
1069f7df2e56Smrg            pChild->lastChild = NullWindow;
1070f7df2e56Smrg            if (pChild == pWin)
1071f7df2e56Smrg                return;
1072f7df2e56Smrg        }
1073f7df2e56Smrg    }
1074f7df2e56Smrg}
1075f7df2e56Smrg
107605b261ecSmrg/*****
107705b261ecSmrg *  DeleteWindow
107805b261ecSmrg *	 Deletes child of window then window itself
107905b261ecSmrg *	 If wid is None, don't send any events
108005b261ecSmrg *****/
108105b261ecSmrg
108205b261ecSmrgint
1083f7df2e56SmrgDeleteWindow(void *value, XID wid)
1084f7df2e56Smrg{
108505b261ecSmrg    WindowPtr pParent;
1086f7df2e56Smrg    WindowPtr pWin = (WindowPtr) value;
108705b261ecSmrg
108805b261ecSmrg    UnmapWindow(pWin, FALSE);
108905b261ecSmrg
109005b261ecSmrg    CrushTree(pWin);
109105b261ecSmrg
109205b261ecSmrg    pParent = pWin->parent;
1093f7df2e56Smrg    if (wid && pParent && SubStrSend(pWin, pParent)) {
1094f7df2e56Smrg        xEvent event = { .u.u.type = DestroyNotify };
1095f7df2e56Smrg        event.u.destroyNotify.window = pWin->drawable.id;
1096f7df2e56Smrg        DeliverEvents(pWin, &event, 1, NullWindow);
109705b261ecSmrg    }
109805b261ecSmrg
109905b261ecSmrg    FreeWindowResources(pWin);
1100f7df2e56Smrg    if (pParent) {
1101f7df2e56Smrg        if (pParent->firstChild == pWin)
1102f7df2e56Smrg            pParent->firstChild = pWin->nextSib;
1103f7df2e56Smrg        if (pParent->lastChild == pWin)
1104f7df2e56Smrg            pParent->lastChild = pWin->prevSib;
1105f7df2e56Smrg        if (pWin->nextSib)
1106f7df2e56Smrg            pWin->nextSib->prevSib = pWin->prevSib;
1107f7df2e56Smrg        if (pWin->prevSib)
1108f7df2e56Smrg            pWin->prevSib->nextSib = pWin->nextSib;
110905b261ecSmrg    }
11104202a189Smrg    else
1111f7df2e56Smrg        pWin->drawable.pScreen->root = NULL;
11124202a189Smrg    dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
111305b261ecSmrg    return Success;
111405b261ecSmrg}
111505b261ecSmrg
1116637ac9abSmrgint
111705b261ecSmrgDestroySubwindows(WindowPtr pWin, ClientPtr client)
111805b261ecSmrg{
111905b261ecSmrg    /* XXX
112005b261ecSmrg     * The protocol is quite clear that each window should be
112105b261ecSmrg     * destroyed in turn, however, unmapping all of the first
112205b261ecSmrg     * eliminates most of the calls to ValidateTree.  So,
112305b261ecSmrg     * this implementation is incorrect in that all of the
112405b261ecSmrg     * UnmapNotifies occur before all of the DestroyNotifies.
112505b261ecSmrg     * If you care, simply delete the call to UnmapSubwindows.
112605b261ecSmrg     */
112705b261ecSmrg    UnmapSubwindows(pWin);
1128637ac9abSmrg    while (pWin->lastChild) {
1129f7df2e56Smrg        int rc = XaceHook(XACE_RESOURCE_ACCESS, client,
1130f7df2e56Smrg                          pWin->lastChild->drawable.id, RT_WINDOW,
1131f7df2e56Smrg                          pWin->lastChild, RT_NONE, NULL, DixDestroyAccess);
1132f7df2e56Smrg
1133f7df2e56Smrg        if (rc != Success)
1134f7df2e56Smrg            return rc;
1135f7df2e56Smrg        FreeResource(pWin->lastChild->drawable.id, RT_NONE);
1136637ac9abSmrg    }
1137637ac9abSmrg    return Success;
113805b261ecSmrg}
113905b261ecSmrg
114065b04b38Smrgstatic void
114165b04b38SmrgSetRootWindowBackground(WindowPtr pWin, ScreenPtr pScreen, Mask *index2)
114265b04b38Smrg{
114365b04b38Smrg    /* following the protocol: "Changing the background of a root window to
114465b04b38Smrg     * None or ParentRelative restores the default background pixmap" */
114565b04b38Smrg    if (bgNoneRoot) {
1146f7df2e56Smrg        pWin->backgroundState = XaceBackgroundNoneState(pWin);
1147f7df2e56Smrg        pWin->background.pixel = pScreen->whitePixel;
114865b04b38Smrg    }
114965b04b38Smrg    else if (party_like_its_1989)
1150f7df2e56Smrg        MakeRootTile(pWin);
115165b04b38Smrg    else {
115265b04b38Smrg        pWin->backgroundState = BackgroundPixel;
1153f7df2e56Smrg        if (whiteRoot)
1154f7df2e56Smrg            pWin->background.pixel = pScreen->whitePixel;
1155f7df2e56Smrg        else
1156f7df2e56Smrg            pWin->background.pixel = pScreen->blackPixel;
1157f7df2e56Smrg        *index2 = CWBackPixel;
115865b04b38Smrg    }
115965b04b38Smrg}
116065b04b38Smrg
116105b261ecSmrg/*****
116205b261ecSmrg *  ChangeWindowAttributes
1163f7df2e56Smrg *
116405b261ecSmrg *  The value-mask specifies which attributes are to be changed; the
116505b261ecSmrg *  value-list contains one value for each one bit in the mask, from least
1166f7df2e56Smrg *  to most significant bit in the mask.
116705b261ecSmrg *****/
1168f7df2e56Smrg
11694202a189Smrgint
117005b261ecSmrgChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client)
117105b261ecSmrg{
117205b261ecSmrg    XID *pVlist;
117305b261ecSmrg    PixmapPtr pPixmap;
117405b261ecSmrg    Pixmap pixID;
117505b261ecSmrg    CursorPtr pCursor, pOldCursor;
117605b261ecSmrg    Cursor cursorID;
117705b261ecSmrg    WindowPtr pChild;
117805b261ecSmrg    Colormap cmap;
1179f7df2e56Smrg    ColormapPtr pCmap;
118005b261ecSmrg    xEvent xE;
1181637ac9abSmrg    int error, rc;
118205b261ecSmrg    ScreenPtr pScreen;
1183637ac9abSmrg    Mask index2, tmask, vmaskCopy = 0;
118405b261ecSmrg    unsigned int val;
1185637ac9abSmrg    Bool checkOptional = FALSE, borderRelative = FALSE;
118605b261ecSmrg
1187f7df2e56Smrg    if ((pWin->drawable.class == InputOnly) &&
1188f7df2e56Smrg        (vmask & (~INPUTONLY_LEGAL_MASK)))
1189f7df2e56Smrg        return BadMatch;
119005b261ecSmrg
119105b261ecSmrg    error = Success;
119205b261ecSmrg    pScreen = pWin->drawable.pScreen;
119305b261ecSmrg    pVlist = vlist;
119405b261ecSmrg    tmask = vmask;
1195f7df2e56Smrg    while (tmask) {
1196f7df2e56Smrg        index2 = (Mask) lowbit(tmask);
1197f7df2e56Smrg        tmask &= ~index2;
1198f7df2e56Smrg        switch (index2) {
1199f7df2e56Smrg        case CWBackPixmap:
1200f7df2e56Smrg            pixID = (Pixmap) * pVlist;
1201f7df2e56Smrg            pVlist++;
1202f7df2e56Smrg            if (pWin->backgroundState == ParentRelative)
1203f7df2e56Smrg                borderRelative = TRUE;
1204f7df2e56Smrg            if (pixID == None) {
1205f7df2e56Smrg                if (pWin->backgroundState == BackgroundPixmap)
1206f7df2e56Smrg                    (*pScreen->DestroyPixmap) (pWin->background.pixmap);
1207f7df2e56Smrg                if (!pWin->parent)
1208f7df2e56Smrg                    SetRootWindowBackground(pWin, pScreen, &index2);
1209f7df2e56Smrg                else {
1210f7df2e56Smrg                    pWin->backgroundState = XaceBackgroundNoneState(pWin);
1211f7df2e56Smrg                    pWin->background.pixel = pScreen->whitePixel;
1212f7df2e56Smrg                }
1213f7df2e56Smrg            }
1214f7df2e56Smrg            else if (pixID == ParentRelative) {
1215f7df2e56Smrg                if (pWin->parent &&
1216f7df2e56Smrg                    pWin->drawable.depth != pWin->parent->drawable.depth) {
1217f7df2e56Smrg                    error = BadMatch;
1218f7df2e56Smrg                    goto PatchUp;
1219f7df2e56Smrg                }
1220f7df2e56Smrg                if (pWin->backgroundState == BackgroundPixmap)
1221f7df2e56Smrg                    (*pScreen->DestroyPixmap) (pWin->background.pixmap);
1222f7df2e56Smrg                if (!pWin->parent)
1223f7df2e56Smrg                    SetRootWindowBackground(pWin, pScreen, &index2);
1224f7df2e56Smrg                else
1225f7df2e56Smrg                    pWin->backgroundState = ParentRelative;
1226f7df2e56Smrg                borderRelative = TRUE;
1227f7df2e56Smrg                /* Note that the parent's backgroundTile's refcnt is NOT
1228f7df2e56Smrg                 * incremented. */
1229f7df2e56Smrg            }
1230f7df2e56Smrg            else {
1231f7df2e56Smrg                rc = dixLookupResourceByType((void **) &pPixmap, pixID,
1232f7df2e56Smrg                                             RT_PIXMAP, client, DixReadAccess);
1233f7df2e56Smrg                if (rc == Success) {
1234f7df2e56Smrg                    if ((pPixmap->drawable.depth != pWin->drawable.depth) ||
1235f7df2e56Smrg                        (pPixmap->drawable.pScreen != pScreen)) {
1236f7df2e56Smrg                        error = BadMatch;
1237f7df2e56Smrg                        goto PatchUp;
1238f7df2e56Smrg                    }
1239f7df2e56Smrg                    if (pWin->backgroundState == BackgroundPixmap)
1240f7df2e56Smrg                        (*pScreen->DestroyPixmap) (pWin->background.pixmap);
1241f7df2e56Smrg                    pWin->backgroundState = BackgroundPixmap;
1242f7df2e56Smrg                    pWin->background.pixmap = pPixmap;
1243f7df2e56Smrg                    pPixmap->refcnt++;
1244f7df2e56Smrg                }
1245f7df2e56Smrg                else {
1246f7df2e56Smrg                    error = rc;
1247f7df2e56Smrg                    client->errorValue = pixID;
1248f7df2e56Smrg                    goto PatchUp;
1249f7df2e56Smrg                }
1250f7df2e56Smrg            }
1251f7df2e56Smrg            break;
1252f7df2e56Smrg        case CWBackPixel:
1253f7df2e56Smrg            if (pWin->backgroundState == ParentRelative)
1254f7df2e56Smrg                borderRelative = TRUE;
1255f7df2e56Smrg            if (pWin->backgroundState == BackgroundPixmap)
1256f7df2e56Smrg                (*pScreen->DestroyPixmap) (pWin->background.pixmap);
1257f7df2e56Smrg            pWin->backgroundState = BackgroundPixel;
1258f7df2e56Smrg            pWin->background.pixel = (CARD32) *pVlist;
1259f7df2e56Smrg            /* background pixel overrides background pixmap,
1260f7df2e56Smrg               so don't let the ddx layer see both bits */
1261f7df2e56Smrg            vmaskCopy &= ~CWBackPixmap;
1262f7df2e56Smrg            pVlist++;
1263f7df2e56Smrg            break;
1264f7df2e56Smrg        case CWBorderPixmap:
1265f7df2e56Smrg            pixID = (Pixmap) * pVlist;
1266f7df2e56Smrg            pVlist++;
1267f7df2e56Smrg            if (pixID == CopyFromParent) {
1268f7df2e56Smrg                if (!pWin->parent ||
1269f7df2e56Smrg                    (pWin->drawable.depth != pWin->parent->drawable.depth)) {
1270f7df2e56Smrg                    error = BadMatch;
1271f7df2e56Smrg                    goto PatchUp;
1272f7df2e56Smrg                }
1273f7df2e56Smrg                if (pWin->parent->borderIsPixel == TRUE) {
1274f7df2e56Smrg                    if (pWin->borderIsPixel == FALSE)
1275f7df2e56Smrg                        (*pScreen->DestroyPixmap) (pWin->border.pixmap);
1276f7df2e56Smrg                    pWin->border = pWin->parent->border;
1277f7df2e56Smrg                    pWin->borderIsPixel = TRUE;
1278f7df2e56Smrg                    index2 = CWBorderPixel;
1279f7df2e56Smrg                    break;
1280f7df2e56Smrg                }
1281f7df2e56Smrg                else {
1282f7df2e56Smrg                    pixID = pWin->parent->border.pixmap->drawable.id;
1283f7df2e56Smrg                }
1284f7df2e56Smrg            }
1285f7df2e56Smrg            rc = dixLookupResourceByType((void **) &pPixmap, pixID, RT_PIXMAP,
1286f7df2e56Smrg                                         client, DixReadAccess);
1287f7df2e56Smrg            if (rc == Success) {
1288f7df2e56Smrg                if ((pPixmap->drawable.depth != pWin->drawable.depth) ||
1289f7df2e56Smrg                    (pPixmap->drawable.pScreen != pScreen)) {
1290f7df2e56Smrg                    error = BadMatch;
1291f7df2e56Smrg                    goto PatchUp;
1292f7df2e56Smrg                }
1293f7df2e56Smrg                if (pWin->borderIsPixel == FALSE)
1294f7df2e56Smrg                    (*pScreen->DestroyPixmap) (pWin->border.pixmap);
1295f7df2e56Smrg                pWin->borderIsPixel = FALSE;
1296f7df2e56Smrg                pWin->border.pixmap = pPixmap;
1297f7df2e56Smrg                pPixmap->refcnt++;
1298f7df2e56Smrg            }
1299f7df2e56Smrg            else {
1300f7df2e56Smrg                error = rc;
1301f7df2e56Smrg                client->errorValue = pixID;
1302f7df2e56Smrg                goto PatchUp;
1303f7df2e56Smrg            }
1304f7df2e56Smrg            break;
1305f7df2e56Smrg        case CWBorderPixel:
1306f7df2e56Smrg            if (pWin->borderIsPixel == FALSE)
1307f7df2e56Smrg                (*pScreen->DestroyPixmap) (pWin->border.pixmap);
1308f7df2e56Smrg            pWin->borderIsPixel = TRUE;
1309f7df2e56Smrg            pWin->border.pixel = (CARD32) *pVlist;
1310f7df2e56Smrg            /* border pixel overrides border pixmap,
1311f7df2e56Smrg               so don't let the ddx layer see both bits */
1312f7df2e56Smrg            vmaskCopy &= ~CWBorderPixmap;
1313f7df2e56Smrg            pVlist++;
1314f7df2e56Smrg            break;
1315f7df2e56Smrg        case CWBitGravity:
1316f7df2e56Smrg            val = (CARD8) *pVlist;
1317f7df2e56Smrg            pVlist++;
1318f7df2e56Smrg            if (val > StaticGravity) {
1319f7df2e56Smrg                error = BadValue;
1320f7df2e56Smrg                client->errorValue = val;
1321f7df2e56Smrg                goto PatchUp;
1322f7df2e56Smrg            }
1323f7df2e56Smrg            pWin->bitGravity = val;
1324f7df2e56Smrg            break;
1325f7df2e56Smrg        case CWWinGravity:
1326f7df2e56Smrg            val = (CARD8) *pVlist;
1327f7df2e56Smrg            pVlist++;
1328f7df2e56Smrg            if (val > StaticGravity) {
1329f7df2e56Smrg                error = BadValue;
1330f7df2e56Smrg                client->errorValue = val;
1331f7df2e56Smrg                goto PatchUp;
1332f7df2e56Smrg            }
1333f7df2e56Smrg            pWin->winGravity = val;
1334f7df2e56Smrg            break;
1335f7df2e56Smrg        case CWBackingStore:
1336f7df2e56Smrg            val = (CARD8) *pVlist;
1337f7df2e56Smrg            pVlist++;
1338f7df2e56Smrg            if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) {
1339f7df2e56Smrg                error = BadValue;
1340f7df2e56Smrg                client->errorValue = val;
1341f7df2e56Smrg                goto PatchUp;
1342f7df2e56Smrg            }
1343f7df2e56Smrg            pWin->backingStore = val;
1344f7df2e56Smrg            pWin->forcedBS = FALSE;
1345f7df2e56Smrg            break;
1346f7df2e56Smrg        case CWBackingPlanes:
1347f7df2e56Smrg            if (pWin->optional || ((CARD32) *pVlist != (CARD32) ~0L)) {
1348f7df2e56Smrg                if (!pWin->optional && !MakeWindowOptional(pWin)) {
1349f7df2e56Smrg                    error = BadAlloc;
1350f7df2e56Smrg                    goto PatchUp;
1351f7df2e56Smrg                }
1352f7df2e56Smrg                pWin->optional->backingBitPlanes = (CARD32) *pVlist;
1353f7df2e56Smrg                if ((CARD32) *pVlist == (CARD32) ~0L)
1354f7df2e56Smrg                    checkOptional = TRUE;
1355f7df2e56Smrg            }
1356f7df2e56Smrg            pVlist++;
1357f7df2e56Smrg            break;
1358f7df2e56Smrg        case CWBackingPixel:
1359f7df2e56Smrg            if (pWin->optional || (CARD32) *pVlist) {
1360f7df2e56Smrg                if (!pWin->optional && !MakeWindowOptional(pWin)) {
1361f7df2e56Smrg                    error = BadAlloc;
1362f7df2e56Smrg                    goto PatchUp;
1363f7df2e56Smrg                }
1364f7df2e56Smrg                pWin->optional->backingPixel = (CARD32) *pVlist;
1365f7df2e56Smrg                if (!*pVlist)
1366f7df2e56Smrg                    checkOptional = TRUE;
1367f7df2e56Smrg            }
1368f7df2e56Smrg            pVlist++;
1369f7df2e56Smrg            break;
1370f7df2e56Smrg        case CWSaveUnder:
1371f7df2e56Smrg            val = (BOOL) * pVlist;
1372f7df2e56Smrg            pVlist++;
1373f7df2e56Smrg            if ((val != xTrue) && (val != xFalse)) {
1374f7df2e56Smrg                error = BadValue;
1375f7df2e56Smrg                client->errorValue = val;
1376f7df2e56Smrg                goto PatchUp;
1377f7df2e56Smrg            }
1378f7df2e56Smrg            pWin->saveUnder = val;
1379f7df2e56Smrg            break;
1380f7df2e56Smrg        case CWEventMask:
1381f7df2e56Smrg            rc = EventSelectForWindow(pWin, client, (Mask) *pVlist);
1382f7df2e56Smrg            if (rc) {
1383f7df2e56Smrg                error = rc;
1384f7df2e56Smrg                goto PatchUp;
1385f7df2e56Smrg            }
1386f7df2e56Smrg            pVlist++;
1387f7df2e56Smrg            break;
1388f7df2e56Smrg        case CWDontPropagate:
1389f7df2e56Smrg            rc = EventSuppressForWindow(pWin, client, (Mask) *pVlist,
1390f7df2e56Smrg                                        &checkOptional);
1391f7df2e56Smrg            if (rc) {
1392f7df2e56Smrg                error = rc;
1393f7df2e56Smrg                goto PatchUp;
1394f7df2e56Smrg            }
1395f7df2e56Smrg            pVlist++;
1396f7df2e56Smrg            break;
1397f7df2e56Smrg        case CWOverrideRedirect:
1398f7df2e56Smrg            val = (BOOL) * pVlist;
1399f7df2e56Smrg            pVlist++;
1400f7df2e56Smrg            if ((val != xTrue) && (val != xFalse)) {
1401f7df2e56Smrg                error = BadValue;
1402f7df2e56Smrg                client->errorValue = val;
1403f7df2e56Smrg                goto PatchUp;
1404f7df2e56Smrg            }
1405f7df2e56Smrg            if (val == xTrue) {
1406f7df2e56Smrg                rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
1407f7df2e56Smrg                              RT_WINDOW, pWin, RT_NONE, NULL, DixGrabAccess);
1408f7df2e56Smrg                if (rc != Success) {
1409f7df2e56Smrg                    error = rc;
1410f7df2e56Smrg                    client->errorValue = pWin->drawable.id;
1411f7df2e56Smrg                    goto PatchUp;
1412f7df2e56Smrg                }
1413f7df2e56Smrg            }
1414f7df2e56Smrg            pWin->overrideRedirect = val;
1415f7df2e56Smrg            break;
1416f7df2e56Smrg        case CWColormap:
1417f7df2e56Smrg            cmap = (Colormap) * pVlist;
1418f7df2e56Smrg            pVlist++;
1419f7df2e56Smrg            if (cmap == CopyFromParent) {
1420f7df2e56Smrg                if (pWin->parent &&
1421f7df2e56Smrg                    (!pWin->optional ||
1422f7df2e56Smrg                     pWin->optional->visual == wVisual(pWin->parent))) {
1423f7df2e56Smrg                    cmap = wColormap(pWin->parent);
1424f7df2e56Smrg                }
1425f7df2e56Smrg                else
1426f7df2e56Smrg                    cmap = None;
1427f7df2e56Smrg            }
1428f7df2e56Smrg            if (cmap == None) {
1429f7df2e56Smrg                error = BadMatch;
1430f7df2e56Smrg                goto PatchUp;
1431f7df2e56Smrg            }
1432f7df2e56Smrg            rc = dixLookupResourceByType((void **) &pCmap, cmap, RT_COLORMAP,
1433f7df2e56Smrg                                         client, DixUseAccess);
1434f7df2e56Smrg            if (rc != Success) {
1435f7df2e56Smrg                error = rc;
1436f7df2e56Smrg                client->errorValue = cmap;
1437f7df2e56Smrg                goto PatchUp;
1438f7df2e56Smrg            }
1439f7df2e56Smrg            if (pCmap->pVisual->vid != wVisual(pWin) ||
1440f7df2e56Smrg                pCmap->pScreen != pScreen) {
1441f7df2e56Smrg                error = BadMatch;
1442f7df2e56Smrg                goto PatchUp;
1443f7df2e56Smrg            }
1444f7df2e56Smrg            if (cmap != wColormap(pWin)) {
1445f7df2e56Smrg                if (!pWin->optional) {
1446f7df2e56Smrg                    if (!MakeWindowOptional(pWin)) {
1447f7df2e56Smrg                        error = BadAlloc;
1448f7df2e56Smrg                        goto PatchUp;
1449f7df2e56Smrg                    }
1450f7df2e56Smrg                }
1451f7df2e56Smrg                else if (pWin->parent && cmap == wColormap(pWin->parent))
1452f7df2e56Smrg                    checkOptional = TRUE;
1453f7df2e56Smrg
1454f7df2e56Smrg                /*
1455f7df2e56Smrg                 * propagate the original colormap to any children
1456f7df2e56Smrg                 * inheriting it
1457f7df2e56Smrg                 */
1458f7df2e56Smrg
1459f7df2e56Smrg                for (pChild = pWin->firstChild; pChild;
1460f7df2e56Smrg                     pChild = pChild->nextSib) {
1461f7df2e56Smrg                    if (!pChild->optional && !MakeWindowOptional(pChild)) {
1462f7df2e56Smrg                        error = BadAlloc;
1463f7df2e56Smrg                        goto PatchUp;
1464f7df2e56Smrg                    }
1465f7df2e56Smrg                }
1466f7df2e56Smrg
1467f7df2e56Smrg                pWin->optional->colormap = cmap;
1468f7df2e56Smrg
1469f7df2e56Smrg                /*
1470f7df2e56Smrg                 * check on any children now matching the new colormap
1471f7df2e56Smrg                 */
1472f7df2e56Smrg
1473f7df2e56Smrg                for (pChild = pWin->firstChild; pChild;
1474f7df2e56Smrg                     pChild = pChild->nextSib) {
1475f7df2e56Smrg                    if (pChild->optional->colormap == cmap)
1476f7df2e56Smrg                        CheckWindowOptionalNeed(pChild);
1477f7df2e56Smrg                }
1478f7df2e56Smrg
1479f7df2e56Smrg                xE = (xEvent) {
1480f7df2e56Smrg                    .u.colormap.window = pWin->drawable.id,
1481f7df2e56Smrg                    .u.colormap.colormap = cmap,
1482f7df2e56Smrg                    .u.colormap.new = xTrue,
1483f7df2e56Smrg                    .u.colormap.state = IsMapInstalled(cmap, pWin)
1484f7df2e56Smrg                };
1485f7df2e56Smrg                xE.u.u.type = ColormapNotify;
1486f7df2e56Smrg                DeliverEvents(pWin, &xE, 1, NullWindow);
1487f7df2e56Smrg            }
1488f7df2e56Smrg            break;
1489f7df2e56Smrg        case CWCursor:
1490f7df2e56Smrg            cursorID = (Cursor) * pVlist;
1491f7df2e56Smrg            pVlist++;
1492f7df2e56Smrg            /*
1493f7df2e56Smrg             * install the new
1494f7df2e56Smrg             */
1495f7df2e56Smrg            if (cursorID == None) {
1496f7df2e56Smrg                if (pWin == pWin->drawable.pScreen->root)
1497f7df2e56Smrg                    pCursor = rootCursor;
1498f7df2e56Smrg                else
1499f7df2e56Smrg                    pCursor = (CursorPtr) None;
1500f7df2e56Smrg            }
1501f7df2e56Smrg            else {
1502f7df2e56Smrg                rc = dixLookupResourceByType((void **) &pCursor, cursorID,
1503f7df2e56Smrg                                             RT_CURSOR, client, DixUseAccess);
1504f7df2e56Smrg                if (rc != Success) {
1505f7df2e56Smrg                    error = rc;
1506f7df2e56Smrg                    client->errorValue = cursorID;
1507f7df2e56Smrg                    goto PatchUp;
1508f7df2e56Smrg                }
1509f7df2e56Smrg            }
1510f7df2e56Smrg
1511f7df2e56Smrg            if (pCursor != wCursor(pWin)) {
1512f7df2e56Smrg                /*
1513f7df2e56Smrg                 * patch up child windows so they don't lose cursors.
1514f7df2e56Smrg                 */
1515f7df2e56Smrg
1516f7df2e56Smrg                for (pChild = pWin->firstChild; pChild;
1517f7df2e56Smrg                     pChild = pChild->nextSib) {
1518f7df2e56Smrg                    if (!pChild->optional && !pChild->cursorIsNone &&
1519f7df2e56Smrg                        !MakeWindowOptional(pChild)) {
1520f7df2e56Smrg                        error = BadAlloc;
1521f7df2e56Smrg                        goto PatchUp;
1522f7df2e56Smrg                    }
1523f7df2e56Smrg                }
1524f7df2e56Smrg
1525f7df2e56Smrg                pOldCursor = 0;
1526f7df2e56Smrg                if (pCursor == (CursorPtr) None) {
1527f7df2e56Smrg                    pWin->cursorIsNone = TRUE;
1528f7df2e56Smrg                    if (pWin->optional) {
1529f7df2e56Smrg                        pOldCursor = pWin->optional->cursor;
1530f7df2e56Smrg                        pWin->optional->cursor = (CursorPtr) None;
1531f7df2e56Smrg                        checkOptional = TRUE;
1532f7df2e56Smrg                    }
1533f7df2e56Smrg                }
1534f7df2e56Smrg                else {
1535f7df2e56Smrg                    if (!pWin->optional) {
1536f7df2e56Smrg                        if (!MakeWindowOptional(pWin)) {
1537f7df2e56Smrg                            error = BadAlloc;
1538f7df2e56Smrg                            goto PatchUp;
1539f7df2e56Smrg                        }
1540f7df2e56Smrg                    }
1541f7df2e56Smrg                    else if (pWin->parent && pCursor == wCursor(pWin->parent))
1542f7df2e56Smrg                        checkOptional = TRUE;
1543f7df2e56Smrg                    pOldCursor = pWin->optional->cursor;
1544f7df2e56Smrg                    pWin->optional->cursor = RefCursor(pCursor);
1545f7df2e56Smrg                    pWin->cursorIsNone = FALSE;
1546f7df2e56Smrg                    /*
1547f7df2e56Smrg                     * check on any children now matching the new cursor
1548f7df2e56Smrg                     */
1549f7df2e56Smrg
1550f7df2e56Smrg                    for (pChild = pWin->firstChild; pChild;
1551f7df2e56Smrg                         pChild = pChild->nextSib) {
1552f7df2e56Smrg                        if (pChild->optional &&
1553f7df2e56Smrg                            (pChild->optional->cursor == pCursor))
1554f7df2e56Smrg                            CheckWindowOptionalNeed(pChild);
1555f7df2e56Smrg                    }
1556f7df2e56Smrg                }
1557f7df2e56Smrg
1558f7df2e56Smrg                CursorVisible = TRUE;
1559f7df2e56Smrg
1560f7df2e56Smrg                if (pWin->realized)
1561f7df2e56Smrg                    WindowHasNewCursor(pWin);
1562f7df2e56Smrg
1563f7df2e56Smrg                /* Can't free cursor until here - old cursor
1564f7df2e56Smrg                 * is needed in WindowHasNewCursor
1565f7df2e56Smrg                 */
1566f7df2e56Smrg                if (pOldCursor)
1567f7df2e56Smrg                    FreeCursor(pOldCursor, (Cursor) 0);
1568f7df2e56Smrg            }
1569f7df2e56Smrg            break;
1570f7df2e56Smrg        default:
1571f7df2e56Smrg            error = BadValue;
1572f7df2e56Smrg            client->errorValue = vmask;
1573f7df2e56Smrg            goto PatchUp;
1574f7df2e56Smrg        }
1575f7df2e56Smrg        vmaskCopy |= index2;
1576f7df2e56Smrg    }
1577f7df2e56Smrg PatchUp:
157805b261ecSmrg    if (checkOptional)
1579f7df2e56Smrg        CheckWindowOptionalNeed(pWin);
158005b261ecSmrg
1581f7df2e56Smrg    /* We SHOULD check for an error value here XXX */
1582f7df2e56Smrg    (*pScreen->ChangeWindowAttributes) (pWin, vmaskCopy);
158305b261ecSmrg
1584f7df2e56Smrg    /*
1585f7df2e56Smrg       If the border contents have changed, redraw the border.
1586f7df2e56Smrg       Note that this has to be done AFTER pScreen->ChangeWindowAttributes
1587f7df2e56Smrg       for the tile to be rotated, and the correct function selected.
1588f7df2e56Smrg     */
158905b261ecSmrg    if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative)
1590f7df2e56Smrg        && pWin->viewable && HasBorder(pWin)) {
1591f7df2e56Smrg        RegionRec exposed;
159205b261ecSmrg
1593f7df2e56Smrg        RegionNull(&exposed);
1594f7df2e56Smrg        RegionSubtract(&exposed, &pWin->borderClip, &pWin->winSize);
1595f7df2e56Smrg        pWin->drawable.pScreen->PaintWindow(pWin, &exposed, PW_BORDER);
1596f7df2e56Smrg        RegionUninit(&exposed);
159705b261ecSmrg    }
159805b261ecSmrg    return error;
159905b261ecSmrg}
160005b261ecSmrg
160105b261ecSmrg/*****
160205b261ecSmrg * GetWindowAttributes
160305b261ecSmrg *    Notice that this is different than ChangeWindowAttributes
160405b261ecSmrg *****/
160505b261ecSmrg
160605b261ecSmrgvoid
1607f7df2e56SmrgGetWindowAttributes(WindowPtr pWin, ClientPtr client,
1608f7df2e56Smrg                    xGetWindowAttributesReply * wa)
160905b261ecSmrg{
161005b261ecSmrg    wa->type = X_Reply;
161105b261ecSmrg    wa->bitGravity = pWin->bitGravity;
161205b261ecSmrg    wa->winGravity = pWin->winGravity;
161305b261ecSmrg    if (pWin->forcedBS && pWin->backingStore != Always)
1614f7df2e56Smrg        wa->backingStore = NotUseful;
161505b261ecSmrg    else
1616f7df2e56Smrg        wa->backingStore = pWin->backingStore;
16174202a189Smrg    wa->length = bytes_to_int32(sizeof(xGetWindowAttributesReply) -
1618f7df2e56Smrg                                sizeof(xGenericReply));
161905b261ecSmrg    wa->sequenceNumber = client->sequence;
1620f7df2e56Smrg    wa->backingBitPlanes = wBackingBitPlanes(pWin);
1621f7df2e56Smrg    wa->backingPixel = wBackingPixel(pWin);
1622f7df2e56Smrg    wa->saveUnder = (BOOL) pWin->saveUnder;
162305b261ecSmrg    wa->override = pWin->overrideRedirect;
162405b261ecSmrg    if (!pWin->mapped)
1625f7df2e56Smrg        wa->mapState = IsUnmapped;
162605b261ecSmrg    else if (pWin->realized)
1627f7df2e56Smrg        wa->mapState = IsViewable;
162805b261ecSmrg    else
1629f7df2e56Smrg        wa->mapState = IsUnviewable;
163005b261ecSmrg
1631f7df2e56Smrg    wa->colormap = wColormap(pWin);
163205b261ecSmrg    wa->mapInstalled = (wa->colormap == None) ? xFalse
1633f7df2e56Smrg        : IsMapInstalled(wa->colormap, pWin);
163405b261ecSmrg
163505b261ecSmrg    wa->yourEventMask = EventMaskForClient(pWin, client);
1636f7df2e56Smrg    wa->allEventMasks = pWin->eventMask | wOtherEventMasks(pWin);
1637f7df2e56Smrg    wa->doNotPropagateMask = wDontPropagateMask(pWin);
163805b261ecSmrg    wa->class = pWin->drawable.class;
1639f7df2e56Smrg    wa->visualID = wVisual(pWin);
164005b261ecSmrg}
164105b261ecSmrg
1642637ac9abSmrgWindowPtr
164305b261ecSmrgMoveWindowInStack(WindowPtr pWin, WindowPtr pNextSib)
164405b261ecSmrg{
164505b261ecSmrg    WindowPtr pParent = pWin->parent;
1646f7df2e56Smrg    WindowPtr pFirstChange = pWin;      /* highest window where list changes */
1647f7df2e56Smrg
1648f7df2e56Smrg    if (pWin->nextSib != pNextSib) {
1649f7df2e56Smrg        WindowPtr pOldNextSib = pWin->nextSib;
1650f7df2e56Smrg
1651f7df2e56Smrg        if (!pNextSib) {        /* move to bottom */
1652f7df2e56Smrg            if (pParent->firstChild == pWin)
1653f7df2e56Smrg                pParent->firstChild = pWin->nextSib;
1654f7df2e56Smrg            /* if (pWin->nextSib) *//* is always True: pNextSib == NULL
1655f7df2e56Smrg             * and pWin->nextSib != pNextSib
1656f7df2e56Smrg             * therefore pWin->nextSib != NULL */
1657f7df2e56Smrg            pFirstChange = pWin->nextSib;
1658f7df2e56Smrg            pWin->nextSib->prevSib = pWin->prevSib;
1659f7df2e56Smrg            if (pWin->prevSib)
1660f7df2e56Smrg                pWin->prevSib->nextSib = pWin->nextSib;
1661f7df2e56Smrg            pParent->lastChild->nextSib = pWin;
1662f7df2e56Smrg            pWin->prevSib = pParent->lastChild;
1663f7df2e56Smrg            pWin->nextSib = NullWindow;
1664f7df2e56Smrg            pParent->lastChild = pWin;
1665f7df2e56Smrg        }
1666f7df2e56Smrg        else if (pParent->firstChild == pNextSib) {     /* move to top */
1667f7df2e56Smrg            pFirstChange = pWin;
1668f7df2e56Smrg            if (pParent->lastChild == pWin)
1669f7df2e56Smrg                pParent->lastChild = pWin->prevSib;
1670f7df2e56Smrg            if (pWin->nextSib)
1671f7df2e56Smrg                pWin->nextSib->prevSib = pWin->prevSib;
1672f7df2e56Smrg            if (pWin->prevSib)
1673f7df2e56Smrg                pWin->prevSib->nextSib = pWin->nextSib;
1674f7df2e56Smrg            pWin->nextSib = pParent->firstChild;
1675f7df2e56Smrg            pWin->prevSib = NULL;
1676f7df2e56Smrg            pNextSib->prevSib = pWin;
1677f7df2e56Smrg            pParent->firstChild = pWin;
1678f7df2e56Smrg        }
1679f7df2e56Smrg        else {                  /* move in middle of list */
168005b261ecSmrg
1681f7df2e56Smrg            WindowPtr pOldNext = pWin->nextSib;
1682f7df2e56Smrg
1683f7df2e56Smrg            pFirstChange = NullWindow;
1684f7df2e56Smrg            if (pParent->firstChild == pWin)
1685f7df2e56Smrg                pFirstChange = pParent->firstChild = pWin->nextSib;
1686f7df2e56Smrg            if (pParent->lastChild == pWin) {
1687f7df2e56Smrg                pFirstChange = pWin;
1688f7df2e56Smrg                pParent->lastChild = pWin->prevSib;
1689f7df2e56Smrg            }
1690f7df2e56Smrg            if (pWin->nextSib)
1691f7df2e56Smrg                pWin->nextSib->prevSib = pWin->prevSib;
1692f7df2e56Smrg            if (pWin->prevSib)
1693f7df2e56Smrg                pWin->prevSib->nextSib = pWin->nextSib;
1694f7df2e56Smrg            pWin->nextSib = pNextSib;
1695f7df2e56Smrg            pWin->prevSib = pNextSib->prevSib;
1696f7df2e56Smrg            if (pNextSib->prevSib)
1697f7df2e56Smrg                pNextSib->prevSib->nextSib = pWin;
1698f7df2e56Smrg            pNextSib->prevSib = pWin;
1699f7df2e56Smrg            if (!pFirstChange) {        /* do we know it yet? */
1700f7df2e56Smrg                pFirstChange = pParent->firstChild;     /* no, search from top */
1701f7df2e56Smrg                while ((pFirstChange != pWin) && (pFirstChange != pOldNext))
1702f7df2e56Smrg                    pFirstChange = pFirstChange->nextSib;
1703f7df2e56Smrg            }
1704f7df2e56Smrg        }
1705f7df2e56Smrg        if (pWin->drawable.pScreen->RestackWindow)
1706f7df2e56Smrg            (*pWin->drawable.pScreen->RestackWindow) (pWin, pOldNextSib);
170705b261ecSmrg    }
170805b261ecSmrg
170905b261ecSmrg#ifdef ROOTLESS
171005b261ecSmrg    /*
171105b261ecSmrg     * In rootless mode we can't optimize away window restacks.
171205b261ecSmrg     * There may be non-X windows around, so even if the window
171305b261ecSmrg     * is in the correct position from X's point of view,
171405b261ecSmrg     * the underlying window system may want to reorder it.
171505b261ecSmrg     */
171605b261ecSmrg    else if (pWin->drawable.pScreen->RestackWindow)
1717f7df2e56Smrg        (*pWin->drawable.pScreen->RestackWindow) (pWin, pWin->nextSib);
171805b261ecSmrg#endif
171905b261ecSmrg
17204202a189Smrg    return pFirstChange;
172105b261ecSmrg}
172205b261ecSmrg
1723637ac9abSmrgvoid
1724f7df2e56SmrgSetWinSize(WindowPtr pWin)
172505b261ecSmrg{
172605b261ecSmrg#ifdef COMPOSITE
1727f7df2e56Smrg    if (pWin->redirectDraw != RedirectDrawNone) {
1728f7df2e56Smrg        BoxRec box;
1729f7df2e56Smrg
1730f7df2e56Smrg        /*
1731f7df2e56Smrg         * Redirected clients get clip list equal to their
1732f7df2e56Smrg         * own geometry, not clipped to their parent
1733f7df2e56Smrg         */
1734f7df2e56Smrg        box.x1 = pWin->drawable.x;
1735f7df2e56Smrg        box.y1 = pWin->drawable.y;
1736f7df2e56Smrg        box.x2 = pWin->drawable.x + pWin->drawable.width;
1737f7df2e56Smrg        box.y2 = pWin->drawable.y + pWin->drawable.height;
1738f7df2e56Smrg        RegionReset(&pWin->winSize, &box);
173905b261ecSmrg    }
174005b261ecSmrg    else
174105b261ecSmrg#endif
1742f7df2e56Smrg        ClippedRegionFromBox(pWin->parent, &pWin->winSize,
1743f7df2e56Smrg                             pWin->drawable.x, pWin->drawable.y,
1744f7df2e56Smrg                             (int) pWin->drawable.width,
1745f7df2e56Smrg                             (int) pWin->drawable.height);
1746f7df2e56Smrg    if (wBoundingShape(pWin) || wClipShape(pWin)) {
1747f7df2e56Smrg        RegionTranslate(&pWin->winSize, -pWin->drawable.x, -pWin->drawable.y);
1748f7df2e56Smrg        if (wBoundingShape(pWin))
1749f7df2e56Smrg            RegionIntersect(&pWin->winSize, &pWin->winSize,
1750f7df2e56Smrg                            wBoundingShape(pWin));
1751f7df2e56Smrg        if (wClipShape(pWin))
1752f7df2e56Smrg            RegionIntersect(&pWin->winSize, &pWin->winSize, wClipShape(pWin));
1753f7df2e56Smrg        RegionTranslate(&pWin->winSize, pWin->drawable.x, pWin->drawable.y);
175405b261ecSmrg    }
175505b261ecSmrg}
175605b261ecSmrg
1757637ac9abSmrgvoid
1758f7df2e56SmrgSetBorderSize(WindowPtr pWin)
175905b261ecSmrg{
1760f7df2e56Smrg    int bw;
176105b261ecSmrg
1762f7df2e56Smrg    if (HasBorder(pWin)) {
1763f7df2e56Smrg        bw = wBorderWidth(pWin);
176405b261ecSmrg#ifdef COMPOSITE
1765f7df2e56Smrg        if (pWin->redirectDraw != RedirectDrawNone) {
1766f7df2e56Smrg            BoxRec box;
1767f7df2e56Smrg
1768f7df2e56Smrg            /*
1769f7df2e56Smrg             * Redirected clients get clip list equal to their
1770f7df2e56Smrg             * own geometry, not clipped to their parent
1771f7df2e56Smrg             */
1772f7df2e56Smrg            box.x1 = pWin->drawable.x - bw;
1773f7df2e56Smrg            box.y1 = pWin->drawable.y - bw;
1774f7df2e56Smrg            box.x2 = pWin->drawable.x + pWin->drawable.width + bw;
1775f7df2e56Smrg            box.y2 = pWin->drawable.y + pWin->drawable.height + bw;
1776f7df2e56Smrg            RegionReset(&pWin->borderSize, &box);
1777f7df2e56Smrg        }
1778f7df2e56Smrg        else
177905b261ecSmrg#endif
1780f7df2e56Smrg            ClippedRegionFromBox(pWin->parent, &pWin->borderSize,
1781f7df2e56Smrg                                 pWin->drawable.x - bw, pWin->drawable.y - bw,
1782f7df2e56Smrg                                 (int) (pWin->drawable.width + (bw << 1)),
1783f7df2e56Smrg                                 (int) (pWin->drawable.height + (bw << 1)));
1784f7df2e56Smrg        if (wBoundingShape(pWin)) {
1785f7df2e56Smrg            RegionTranslate(&pWin->borderSize, -pWin->drawable.x,
1786f7df2e56Smrg                            -pWin->drawable.y);
1787f7df2e56Smrg            RegionIntersect(&pWin->borderSize, &pWin->borderSize,
1788f7df2e56Smrg                            wBoundingShape(pWin));
1789f7df2e56Smrg            RegionTranslate(&pWin->borderSize, pWin->drawable.x,
1790f7df2e56Smrg                            pWin->drawable.y);
1791f7df2e56Smrg            RegionUnion(&pWin->borderSize, &pWin->borderSize, &pWin->winSize);
1792f7df2e56Smrg        }
1793f7df2e56Smrg    }
1794f7df2e56Smrg    else {
1795f7df2e56Smrg        RegionCopy(&pWin->borderSize, &pWin->winSize);
179605b261ecSmrg    }
179705b261ecSmrg}
179805b261ecSmrg
179905b261ecSmrg/**
180005b261ecSmrg *
180105b261ecSmrg *  \param x,y          new window position
180205b261ecSmrg *  \param oldx,oldy    old window position
180305b261ecSmrg *  \param destx,desty  position relative to gravity
180405b261ecSmrg */
180505b261ecSmrg
18064202a189Smrgvoid
1807f7df2e56SmrgGravityTranslate(int x, int y, int oldx, int oldy,
1808f7df2e56Smrg                 int dw, int dh, unsigned gravity, int *destx, int *desty)
180905b261ecSmrg{
181005b261ecSmrg    switch (gravity) {
181105b261ecSmrg    case NorthGravity:
1812f7df2e56Smrg        *destx = x + dw / 2;
1813f7df2e56Smrg        *desty = y;
1814f7df2e56Smrg        break;
181505b261ecSmrg    case NorthEastGravity:
1816f7df2e56Smrg        *destx = x + dw;
1817f7df2e56Smrg        *desty = y;
1818f7df2e56Smrg        break;
181905b261ecSmrg    case WestGravity:
1820f7df2e56Smrg        *destx = x;
1821f7df2e56Smrg        *desty = y + dh / 2;
1822f7df2e56Smrg        break;
182305b261ecSmrg    case CenterGravity:
1824f7df2e56Smrg        *destx = x + dw / 2;
1825f7df2e56Smrg        *desty = y + dh / 2;
1826f7df2e56Smrg        break;
182705b261ecSmrg    case EastGravity:
1828f7df2e56Smrg        *destx = x + dw;
1829f7df2e56Smrg        *desty = y + dh / 2;
1830f7df2e56Smrg        break;
183105b261ecSmrg    case SouthWestGravity:
1832f7df2e56Smrg        *destx = x;
1833f7df2e56Smrg        *desty = y + dh;
1834f7df2e56Smrg        break;
183505b261ecSmrg    case SouthGravity:
1836f7df2e56Smrg        *destx = x + dw / 2;
1837f7df2e56Smrg        *desty = y + dh;
1838f7df2e56Smrg        break;
183905b261ecSmrg    case SouthEastGravity:
1840f7df2e56Smrg        *destx = x + dw;
1841f7df2e56Smrg        *desty = y + dh;
1842f7df2e56Smrg        break;
184305b261ecSmrg    case StaticGravity:
1844f7df2e56Smrg        *destx = oldx;
1845f7df2e56Smrg        *desty = oldy;
1846f7df2e56Smrg        break;
184705b261ecSmrg    default:
1848f7df2e56Smrg        *destx = x;
1849f7df2e56Smrg        *desty = y;
1850f7df2e56Smrg        break;
185105b261ecSmrg    }
185205b261ecSmrg}
185305b261ecSmrg
185405b261ecSmrg/* XXX need to retile border on each window with ParentRelative origin */
1855637ac9abSmrgvoid
185605b261ecSmrgResizeChildrenWinSize(WindowPtr pWin, int dx, int dy, int dw, int dh)
185705b261ecSmrg{
185805b261ecSmrg    ScreenPtr pScreen;
185905b261ecSmrg    WindowPtr pSib, pChild;
186005b261ecSmrg    Bool resized = (dw || dh);
186105b261ecSmrg
186205b261ecSmrg    pScreen = pWin->drawable.pScreen;
186305b261ecSmrg
1864f7df2e56Smrg    for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib) {
1865f7df2e56Smrg        if (resized && (pSib->winGravity > NorthWestGravity)) {
1866f7df2e56Smrg            int cwsx, cwsy;
1867f7df2e56Smrg
1868f7df2e56Smrg            cwsx = pSib->origin.x;
1869f7df2e56Smrg            cwsy = pSib->origin.y;
1870f7df2e56Smrg            GravityTranslate(cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh,
1871f7df2e56Smrg                             pSib->winGravity, &cwsx, &cwsy);
1872f7df2e56Smrg            if (cwsx != pSib->origin.x || cwsy != pSib->origin.y) {
1873f7df2e56Smrg                xEvent event = {
1874f7df2e56Smrg                    .u.gravity.window = pSib->drawable.id,
1875f7df2e56Smrg                    .u.gravity.x = cwsx - wBorderWidth(pSib),
1876f7df2e56Smrg                    .u.gravity.y = cwsy - wBorderWidth(pSib)
1877f7df2e56Smrg                };
1878f7df2e56Smrg                event.u.u.type = GravityNotify;
1879f7df2e56Smrg                DeliverEvents(pSib, &event, 1, NullWindow);
1880f7df2e56Smrg                pSib->origin.x = cwsx;
1881f7df2e56Smrg                pSib->origin.y = cwsy;
1882f7df2e56Smrg            }
1883f7df2e56Smrg        }
1884f7df2e56Smrg        pSib->drawable.x = pWin->drawable.x + pSib->origin.x;
1885f7df2e56Smrg        pSib->drawable.y = pWin->drawable.y + pSib->origin.y;
1886f7df2e56Smrg        SetWinSize(pSib);
1887f7df2e56Smrg        SetBorderSize(pSib);
1888f7df2e56Smrg        (*pScreen->PositionWindow) (pSib, pSib->drawable.x, pSib->drawable.y);
1889f7df2e56Smrg
1890f7df2e56Smrg        if ((pChild = pSib->firstChild)) {
1891f7df2e56Smrg            while (1) {
1892f7df2e56Smrg                pChild->drawable.x = pChild->parent->drawable.x +
1893f7df2e56Smrg                    pChild->origin.x;
1894f7df2e56Smrg                pChild->drawable.y = pChild->parent->drawable.y +
1895f7df2e56Smrg                    pChild->origin.y;
1896f7df2e56Smrg                SetWinSize(pChild);
1897f7df2e56Smrg                SetBorderSize(pChild);
1898f7df2e56Smrg                (*pScreen->PositionWindow) (pChild,
1899f7df2e56Smrg                                            pChild->drawable.x,
1900f7df2e56Smrg                                            pChild->drawable.y);
1901f7df2e56Smrg                if (pChild->firstChild) {
1902f7df2e56Smrg                    pChild = pChild->firstChild;
1903f7df2e56Smrg                    continue;
1904f7df2e56Smrg                }
1905f7df2e56Smrg                while (!pChild->nextSib && (pChild != pSib))
1906f7df2e56Smrg                    pChild = pChild->parent;
1907f7df2e56Smrg                if (pChild == pSib)
1908f7df2e56Smrg                    break;
1909f7df2e56Smrg                pChild = pChild->nextSib;
1910f7df2e56Smrg            }
1911f7df2e56Smrg        }
191205b261ecSmrg    }
191305b261ecSmrg}
191405b261ecSmrg
191505b261ecSmrg#define GET_INT16(m, f) \
191605b261ecSmrg	if (m & mask) \
191705b261ecSmrg	  { \
191805b261ecSmrg	     f = (INT16) *pVlist;\
191905b261ecSmrg	    pVlist++; \
192005b261ecSmrg	 }
192105b261ecSmrg#define GET_CARD16(m, f) \
192205b261ecSmrg	if (m & mask) \
192305b261ecSmrg	 { \
192405b261ecSmrg	    f = (CARD16) *pVlist;\
192505b261ecSmrg	    pVlist++;\
192605b261ecSmrg	 }
192705b261ecSmrg
192805b261ecSmrg#define GET_CARD8(m, f) \
192905b261ecSmrg	if (m & mask) \
193005b261ecSmrg	 { \
193105b261ecSmrg	    f = (CARD8) *pVlist;\
193205b261ecSmrg	    pVlist++;\
193305b261ecSmrg	 }
193405b261ecSmrg
193505b261ecSmrg#define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight))
193605b261ecSmrg
193705b261ecSmrg/*
193805b261ecSmrg * IsSiblingAboveMe
1939f7df2e56Smrg *     returns Above if pSib above pMe in stack or Below otherwise
194005b261ecSmrg */
194105b261ecSmrg
194205b261ecSmrgstatic int
1943f7df2e56SmrgIsSiblingAboveMe(WindowPtr pMe, WindowPtr pSib)
194405b261ecSmrg{
194505b261ecSmrg    WindowPtr pWin;
194605b261ecSmrg
194705b261ecSmrg    pWin = pMe->parent->firstChild;
1948f7df2e56Smrg    while (pWin) {
1949f7df2e56Smrg        if (pWin == pSib)
1950f7df2e56Smrg            return Above;
1951f7df2e56Smrg        else if (pWin == pMe)
1952f7df2e56Smrg            return Below;
1953f7df2e56Smrg        pWin = pWin->nextSib;
195405b261ecSmrg    }
19554202a189Smrg    return Below;
195605b261ecSmrg}
195705b261ecSmrg
195805b261ecSmrgstatic BoxPtr
1959f7df2e56SmrgWindowExtents(WindowPtr pWin, BoxPtr pBox)
1960f7df2e56Smrg{
1961f7df2e56Smrg    pBox->x1 = pWin->drawable.x - wBorderWidth(pWin);
1962f7df2e56Smrg    pBox->y1 = pWin->drawable.y - wBorderWidth(pWin);
1963f7df2e56Smrg    pBox->x2 = pWin->drawable.x + (int) pWin->drawable.width
1964f7df2e56Smrg        + wBorderWidth(pWin);
1965f7df2e56Smrg    pBox->y2 = pWin->drawable.y + (int) pWin->drawable.height
1966f7df2e56Smrg        + wBorderWidth(pWin);
19674202a189Smrg    return pBox;
196805b261ecSmrg}
196905b261ecSmrg
1970f7df2e56Smrg#define IS_SHAPED(pWin)	(wBoundingShape (pWin) != NULL)
197105b261ecSmrg
197205b261ecSmrgstatic RegionPtr
1973f7df2e56SmrgMakeBoundingRegion(WindowPtr pWin, BoxPtr pBox)
197405b261ecSmrg{
1975f7df2e56Smrg    RegionPtr pRgn = RegionCreate(pBox, 1);
1976f7df2e56Smrg
1977f7df2e56Smrg    if (wBoundingShape(pWin)) {
1978f7df2e56Smrg        RegionTranslate(pRgn, -pWin->origin.x, -pWin->origin.y);
1979f7df2e56Smrg        RegionIntersect(pRgn, pRgn, wBoundingShape(pWin));
1980f7df2e56Smrg        RegionTranslate(pRgn, pWin->origin.x, pWin->origin.y);
198105b261ecSmrg    }
198205b261ecSmrg    return pRgn;
198305b261ecSmrg}
198405b261ecSmrg
198505b261ecSmrgstatic Bool
1986f7df2e56SmrgShapeOverlap(WindowPtr pWin, BoxPtr pWinBox, WindowPtr pSib, BoxPtr pSibBox)
198705b261ecSmrg{
1988f7df2e56Smrg    RegionPtr pWinRgn, pSibRgn;
1989f7df2e56Smrg    Bool ret;
199005b261ecSmrg
199105b261ecSmrg    if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib))
1992f7df2e56Smrg        return TRUE;
1993f7df2e56Smrg    pWinRgn = MakeBoundingRegion(pWin, pWinBox);
1994f7df2e56Smrg    pSibRgn = MakeBoundingRegion(pSib, pSibBox);
19954202a189Smrg    RegionIntersect(pWinRgn, pWinRgn, pSibRgn);
19964202a189Smrg    ret = RegionNotEmpty(pWinRgn);
19974202a189Smrg    RegionDestroy(pWinRgn);
19984202a189Smrg    RegionDestroy(pSibRgn);
199905b261ecSmrg    return ret;
200005b261ecSmrg}
200105b261ecSmrg
200205b261ecSmrgstatic Bool
2003f7df2e56SmrgAnyWindowOverlapsMe(WindowPtr pWin, WindowPtr pHead, BoxPtr box)
200405b261ecSmrg{
200505b261ecSmrg    WindowPtr pSib;
200605b261ecSmrg    BoxRec sboxrec;
200705b261ecSmrg    BoxPtr sbox;
200805b261ecSmrg
2009f7df2e56Smrg    for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib) {
2010f7df2e56Smrg        if (pSib->mapped) {
2011f7df2e56Smrg            sbox = WindowExtents(pSib, &sboxrec);
2012f7df2e56Smrg            if (BOXES_OVERLAP(sbox, box)
2013f7df2e56Smrg                && ShapeOverlap(pWin, box, pSib, sbox))
2014f7df2e56Smrg                return TRUE;
2015f7df2e56Smrg        }
201605b261ecSmrg    }
20174202a189Smrg    return FALSE;
201805b261ecSmrg}
201905b261ecSmrg
202005b261ecSmrgstatic Bool
2021f7df2e56SmrgIOverlapAnyWindow(WindowPtr pWin, BoxPtr box)
202205b261ecSmrg{
202305b261ecSmrg    WindowPtr pSib;
202405b261ecSmrg    BoxRec sboxrec;
202505b261ecSmrg    BoxPtr sbox;
202605b261ecSmrg
2027f7df2e56Smrg    for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib) {
2028f7df2e56Smrg        if (pSib->mapped) {
2029f7df2e56Smrg            sbox = WindowExtents(pSib, &sboxrec);
2030f7df2e56Smrg            if (BOXES_OVERLAP(sbox, box)
2031f7df2e56Smrg                && ShapeOverlap(pWin, box, pSib, sbox))
2032f7df2e56Smrg                return TRUE;
2033f7df2e56Smrg        }
203405b261ecSmrg    }
20354202a189Smrg    return FALSE;
203605b261ecSmrg}
203705b261ecSmrg
203805b261ecSmrg/*
2039f7df2e56Smrg *   WhereDoIGoInTheStack()
204005b261ecSmrg *	  Given pWin and pSib and the relationshipe smode, return
204105b261ecSmrg *	  the window that pWin should go ABOVE.
204205b261ecSmrg *	  If a pSib is specified:
204305b261ecSmrg *	      Above:  pWin is placed just above pSib
204405b261ecSmrg *	      Below:  pWin is placed just below pSib
204505b261ecSmrg *	      TopIf:  if pSib occludes pWin, then pWin is placed
204605b261ecSmrg *		      at the top of the stack
2047f7df2e56Smrg *	      BottomIf:	 if pWin occludes pSib, then pWin is
204805b261ecSmrg *			 placed at the bottom of the stack
204905b261ecSmrg *	      Opposite: if pSib occludes pWin, then pWin is placed at the
205005b261ecSmrg *			top of the stack, else if pWin occludes pSib, then
205105b261ecSmrg *			pWin is placed at the bottom of the stack
205205b261ecSmrg *
205305b261ecSmrg *	  If pSib is NULL:
205405b261ecSmrg *	      Above:  pWin is placed at the top of the stack
205505b261ecSmrg *	      Below:  pWin is placed at the bottom of the stack
205605b261ecSmrg *	      TopIf:  if any sibling occludes pWin, then pWin is placed at
205705b261ecSmrg *		      the top of the stack
205805b261ecSmrg *	      BottomIf: if pWin occludes any sibline, then pWin is placed at
205905b261ecSmrg *			the bottom of the stack
206005b261ecSmrg *	      Opposite: if any sibling occludes pWin, then pWin is placed at
206105b261ecSmrg *			the top of the stack, else if pWin occludes any
206205b261ecSmrg *			sibling, then pWin is placed at the bottom of the stack
206305b261ecSmrg *
206405b261ecSmrg */
206505b261ecSmrg
206605b261ecSmrgstatic WindowPtr
2067f7df2e56SmrgWhereDoIGoInTheStack(WindowPtr pWin,
2068f7df2e56Smrg                     WindowPtr pSib,
2069f7df2e56Smrg                     short x,
2070f7df2e56Smrg                     short y, unsigned short w, unsigned short h, int smode)
207105b261ecSmrg{
207205b261ecSmrg    BoxRec box;
207305b261ecSmrg    WindowPtr pHead, pFirst;
207405b261ecSmrg
2075f7df2e56Smrg    if ((pWin == pWin->parent->firstChild) && (pWin == pWin->parent->lastChild))
2076f7df2e56Smrg        return NULL;
207705b261ecSmrg    pHead = RealChildHead(pWin->parent);
207805b261ecSmrg    pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild;
207905b261ecSmrg    box.x1 = x;
208005b261ecSmrg    box.y1 = y;
2081f7df2e56Smrg    box.x2 = x + (int) w;
2082f7df2e56Smrg    box.y2 = y + (int) h;
2083f7df2e56Smrg    switch (smode) {
2084f7df2e56Smrg    case Above:
2085f7df2e56Smrg        if (pSib)
2086f7df2e56Smrg            return pSib;
2087f7df2e56Smrg        else if (pWin == pFirst)
2088f7df2e56Smrg            return pWin->nextSib;
2089f7df2e56Smrg        else
2090f7df2e56Smrg            return pFirst;
2091f7df2e56Smrg    case Below:
2092f7df2e56Smrg        if (pSib)
2093f7df2e56Smrg            if (pSib->nextSib != pWin)
2094f7df2e56Smrg                return pSib->nextSib;
2095f7df2e56Smrg            else
2096f7df2e56Smrg                return pWin->nextSib;
2097f7df2e56Smrg        else
2098f7df2e56Smrg            return NullWindow;
2099f7df2e56Smrg    case TopIf:
2100f7df2e56Smrg        if ((!pWin->mapped || (pSib && !pSib->mapped)))
2101f7df2e56Smrg            return pWin->nextSib;
2102f7df2e56Smrg        else if (pSib) {
2103f7df2e56Smrg            if ((IsSiblingAboveMe(pWin, pSib) == Above) &&
2104f7df2e56Smrg                (RegionContainsRect(&pSib->borderSize, &box) != rgnOUT))
2105f7df2e56Smrg                return pFirst;
2106f7df2e56Smrg            else
2107f7df2e56Smrg                return pWin->nextSib;
2108f7df2e56Smrg        }
2109f7df2e56Smrg        else if (AnyWindowOverlapsMe(pWin, pHead, &box))
2110f7df2e56Smrg            return pFirst;
2111f7df2e56Smrg        else
2112f7df2e56Smrg            return pWin->nextSib;
2113f7df2e56Smrg    case BottomIf:
2114f7df2e56Smrg        if ((!pWin->mapped || (pSib && !pSib->mapped)))
2115f7df2e56Smrg            return pWin->nextSib;
2116f7df2e56Smrg        else if (pSib) {
2117f7df2e56Smrg            if ((IsSiblingAboveMe(pWin, pSib) == Below) &&
2118f7df2e56Smrg                (RegionContainsRect(&pSib->borderSize, &box) != rgnOUT))
2119f7df2e56Smrg                return NullWindow;
2120f7df2e56Smrg            else
2121f7df2e56Smrg                return pWin->nextSib;
2122f7df2e56Smrg        }
2123f7df2e56Smrg        else if (IOverlapAnyWindow(pWin, &box))
2124f7df2e56Smrg            return NullWindow;
2125f7df2e56Smrg        else
2126f7df2e56Smrg            return pWin->nextSib;
2127f7df2e56Smrg    case Opposite:
2128f7df2e56Smrg        if ((!pWin->mapped || (pSib && !pSib->mapped)))
2129f7df2e56Smrg            return pWin->nextSib;
2130f7df2e56Smrg        else if (pSib) {
2131f7df2e56Smrg            if (RegionContainsRect(&pSib->borderSize, &box) != rgnOUT) {
2132f7df2e56Smrg                if (IsSiblingAboveMe(pWin, pSib) == Above)
2133f7df2e56Smrg                    return pFirst;
2134f7df2e56Smrg                else
2135f7df2e56Smrg                    return NullWindow;
2136f7df2e56Smrg            }
2137f7df2e56Smrg            else
2138f7df2e56Smrg                return pWin->nextSib;
2139f7df2e56Smrg        }
2140f7df2e56Smrg        else if (AnyWindowOverlapsMe(pWin, pHead, &box)) {
2141f7df2e56Smrg            /* If I'm occluded, I can't possibly be the first child
2142f7df2e56Smrg             * if (pWin == pWin->parent->firstChild)
2143f7df2e56Smrg             *    return pWin->nextSib;
2144f7df2e56Smrg             */
2145f7df2e56Smrg            return pFirst;
2146f7df2e56Smrg        }
2147f7df2e56Smrg        else if (IOverlapAnyWindow(pWin, &box))
2148f7df2e56Smrg            return NullWindow;
2149f7df2e56Smrg        else
2150f7df2e56Smrg            return pWin->nextSib;
2151f7df2e56Smrg    default:
215205b261ecSmrg    {
2153f7df2e56Smrg        /* should never happen; make something up. */
2154f7df2e56Smrg        return pWin->nextSib;
2155f7df2e56Smrg    }
215605b261ecSmrg    }
215705b261ecSmrg}
215805b261ecSmrg
215905b261ecSmrgstatic void
2160f7df2e56SmrgReflectStackChange(WindowPtr pWin, WindowPtr pSib, VTKind kind)
216105b261ecSmrg{
216205b261ecSmrg/* Note that pSib might be NULL */
216305b261ecSmrg
2164f7df2e56Smrg    Bool WasViewable = (Bool) pWin->viewable;
216505b261ecSmrg    Bool anyMarked;
216605b261ecSmrg    WindowPtr pFirstChange;
2167f7df2e56Smrg    WindowPtr pLayerWin;
216805b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
216905b261ecSmrg
217005b261ecSmrg    /* if this is a root window, can't be restacked */
217105b261ecSmrg    if (!pWin->parent)
2172f7df2e56Smrg        return;
217305b261ecSmrg
217405b261ecSmrg    pFirstChange = MoveWindowInStack(pWin, pSib);
217505b261ecSmrg
2176f7df2e56Smrg    if (WasViewable) {
2177f7df2e56Smrg        anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pFirstChange,
2178f7df2e56Smrg                                                       &pLayerWin);
2179f7df2e56Smrg        if (pLayerWin != pWin)
2180f7df2e56Smrg            pFirstChange = pLayerWin;
2181f7df2e56Smrg        if (anyMarked) {
2182f7df2e56Smrg            (*pScreen->ValidateTree) (pLayerWin->parent, pFirstChange, kind);
2183f7df2e56Smrg            (*pScreen->HandleExposures) (pLayerWin->parent);
2184f7df2e56Smrg            if (pWin->drawable.pScreen->PostValidateTree)
2185f7df2e56Smrg                (*pScreen->PostValidateTree) (pLayerWin->parent, pFirstChange,
2186f7df2e56Smrg                                              kind);
2187f7df2e56Smrg        }
218805b261ecSmrg    }
218905b261ecSmrg    if (pWin->realized)
2190f7df2e56Smrg        WindowsRestructured();
219105b261ecSmrg}
219205b261ecSmrg
219305b261ecSmrg/*****
219405b261ecSmrg * ConfigureWindow
219505b261ecSmrg *****/
219605b261ecSmrg
219705b261ecSmrgint
219805b261ecSmrgConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client)
219905b261ecSmrg{
220005b261ecSmrg#define RESTACK_WIN    0
220105b261ecSmrg#define MOVE_WIN       1
220205b261ecSmrg#define RESIZE_WIN     2
220305b261ecSmrg#define REBORDER_WIN   3
220405b261ecSmrg    WindowPtr pSib = NullWindow;
220505b261ecSmrg    WindowPtr pParent = pWin->parent;
220605b261ecSmrg    Window sibwid = 0;
220705b261ecSmrg    Mask index2, tmask;
220805b261ecSmrg    XID *pVlist;
2209f7df2e56Smrg    short x, y, beforeX, beforeY;
221005b261ecSmrg    unsigned short w = pWin->drawable.width,
2211f7df2e56Smrg        h = pWin->drawable.height, bw = pWin->borderWidth;
2212637ac9abSmrg    int rc, action, smode = Above;
221305b261ecSmrg
2214f7df2e56Smrg    if ((pWin->drawable.class == InputOnly) && (mask & CWBorderWidth))
2215f7df2e56Smrg        return BadMatch;
221605b261ecSmrg
221705b261ecSmrg    if ((mask & CWSibling) && !(mask & CWStackMode))
2218f7df2e56Smrg        return BadMatch;
221905b261ecSmrg
222005b261ecSmrg    pVlist = vlist;
222105b261ecSmrg
2222f7df2e56Smrg    if (pParent) {
2223f7df2e56Smrg        x = pWin->drawable.x - pParent->drawable.x - (int) bw;
2224f7df2e56Smrg        y = pWin->drawable.y - pParent->drawable.y - (int) bw;
222505b261ecSmrg    }
2226f7df2e56Smrg    else {
2227f7df2e56Smrg        x = pWin->drawable.x;
2228f7df2e56Smrg        y = pWin->drawable.y;
222905b261ecSmrg    }
223005b261ecSmrg    beforeX = x;
223105b261ecSmrg    beforeY = y;
2232f7df2e56Smrg    action = RESTACK_WIN;
2233f7df2e56Smrg    if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth)))) {
2234f7df2e56Smrg        GET_INT16(CWX, x);
2235f7df2e56Smrg        GET_INT16(CWY, y);
2236f7df2e56Smrg        action = MOVE_WIN;
2237f7df2e56Smrg    }
2238f7df2e56Smrg    /* or should be resized */
2239f7df2e56Smrg    else if (mask & (CWX | CWY | CWWidth | CWHeight)) {
2240f7df2e56Smrg        GET_INT16(CWX, x);
2241f7df2e56Smrg        GET_INT16(CWY, y);
2242f7df2e56Smrg        GET_CARD16(CWWidth, w);
2243f7df2e56Smrg        GET_CARD16(CWHeight, h);
2244f7df2e56Smrg        if (!w || !h) {
2245f7df2e56Smrg            client->errorValue = 0;
2246f7df2e56Smrg            return BadValue;
2247f7df2e56Smrg        }
2248f7df2e56Smrg        action = RESIZE_WIN;
224905b261ecSmrg    }
225005b261ecSmrg    tmask = mask & ~ChangeMask;
2251f7df2e56Smrg    while (tmask) {
2252f7df2e56Smrg        index2 = (Mask) lowbit(tmask);
2253f7df2e56Smrg        tmask &= ~index2;
2254f7df2e56Smrg        switch (index2) {
2255f7df2e56Smrg        case CWBorderWidth:
2256f7df2e56Smrg            GET_CARD16(CWBorderWidth, bw);
2257f7df2e56Smrg            break;
2258f7df2e56Smrg        case CWSibling:
2259f7df2e56Smrg            sibwid = (Window) *pVlist;
2260f7df2e56Smrg            pVlist++;
2261f7df2e56Smrg            rc = dixLookupWindow(&pSib, sibwid, client, DixGetAttrAccess);
2262f7df2e56Smrg            if (rc != Success) {
2263f7df2e56Smrg                client->errorValue = sibwid;
2264f7df2e56Smrg                return rc;
2265f7df2e56Smrg            }
2266f7df2e56Smrg            if (pSib->parent != pParent)
2267f7df2e56Smrg                return BadMatch;
2268f7df2e56Smrg            if (pSib == pWin)
2269f7df2e56Smrg                return BadMatch;
2270f7df2e56Smrg            break;
2271f7df2e56Smrg        case CWStackMode:
2272f7df2e56Smrg            GET_CARD8(CWStackMode, smode);
2273f7df2e56Smrg            if ((smode != TopIf) && (smode != BottomIf) &&
2274f7df2e56Smrg                (smode != Opposite) && (smode != Above) && (smode != Below)) {
2275f7df2e56Smrg                client->errorValue = smode;
2276f7df2e56Smrg                return BadValue;
2277f7df2e56Smrg            }
2278f7df2e56Smrg            break;
2279f7df2e56Smrg        default:
2280f7df2e56Smrg            client->errorValue = mask;
2281f7df2e56Smrg            return BadValue;
2282f7df2e56Smrg        }
2283f7df2e56Smrg    }
2284f7df2e56Smrg    /* root really can't be reconfigured, so just return */
228505b261ecSmrg    if (!pParent)
2286f7df2e56Smrg        return Success;
228705b261ecSmrg
2288f7df2e56Smrg    /* Figure out if the window should be moved.  Doesnt
2289f7df2e56Smrg       make the changes to the window if event sent */
229005b261ecSmrg
229105b261ecSmrg    if (mask & CWStackMode)
2292f7df2e56Smrg        pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x,
2293f7df2e56Smrg                                    pParent->drawable.y + y,
2294f7df2e56Smrg                                    w + (bw << 1), h + (bw << 1), smode);
229505b261ecSmrg    else
2296f7df2e56Smrg        pSib = pWin->nextSib;
2297f7df2e56Smrg
2298f7df2e56Smrg    if ((!pWin->overrideRedirect) && (RedirectSend(pParent))) {
2299f7df2e56Smrg        xEvent event = {
2300f7df2e56Smrg            .u.configureRequest.window = pWin->drawable.id,
2301f7df2e56Smrg            .u.configureRequest.sibling = (mask & CWSibling) ? sibwid : None,
2302f7df2e56Smrg            .u.configureRequest.x = x,
2303f7df2e56Smrg            .u.configureRequest.y = y,
2304f7df2e56Smrg            .u.configureRequest.width = w,
2305f7df2e56Smrg            .u.configureRequest.height = h,
2306f7df2e56Smrg            .u.configureRequest.borderWidth = bw,
2307f7df2e56Smrg            .u.configureRequest.valueMask = mask,
2308f7df2e56Smrg            .u.configureRequest.parent = pParent->drawable.id
2309f7df2e56Smrg        };
2310f7df2e56Smrg        event.u.u.type = ConfigureRequest;
2311f7df2e56Smrg        event.u.u.detail = (mask & CWStackMode) ? smode : Above;
231205b261ecSmrg#ifdef PANORAMIX
2313f7df2e56Smrg        if (!noPanoramiXExtension && (!pParent || !pParent->parent)) {
23144202a189Smrg            event.u.configureRequest.x += screenInfo.screens[0]->x;
23154202a189Smrg            event.u.configureRequest.y += screenInfo.screens[0]->y;
2316f7df2e56Smrg        }
231705b261ecSmrg#endif
2318f7df2e56Smrg        if (MaybeDeliverEventsToClient(pParent, &event, 1,
2319f7df2e56Smrg                                       SubstructureRedirectMask, client) == 1)
2320f7df2e56Smrg            return Success;
232105b261ecSmrg    }
2322f7df2e56Smrg    if (action == RESIZE_WIN) {
2323f7df2e56Smrg        Bool size_change = (w != pWin->drawable.width)
2324f7df2e56Smrg            || (h != pWin->drawable.height);
2325f7df2e56Smrg
2326f7df2e56Smrg        if (size_change &&
2327f7df2e56Smrg            ((pWin->eventMask | wOtherEventMasks(pWin)) & ResizeRedirectMask)) {
2328f7df2e56Smrg            xEvent eventT = {
2329f7df2e56Smrg                .u.resizeRequest.window = pWin->drawable.id,
2330f7df2e56Smrg                .u.resizeRequest.width = w,
2331f7df2e56Smrg                .u.resizeRequest.height = h
2332f7df2e56Smrg            };
2333f7df2e56Smrg            eventT.u.u.type = ResizeRequest;
2334f7df2e56Smrg            if (MaybeDeliverEventsToClient(pWin, &eventT, 1,
2335f7df2e56Smrg                                           ResizeRedirectMask, client) == 1) {
2336f7df2e56Smrg                /* if event is delivered, leave the actual size alone. */
2337f7df2e56Smrg                w = pWin->drawable.width;
2338f7df2e56Smrg                h = pWin->drawable.height;
2339f7df2e56Smrg                size_change = FALSE;
2340f7df2e56Smrg            }
2341f7df2e56Smrg        }
2342f7df2e56Smrg        if (!size_change) {
2343f7df2e56Smrg            if (mask & (CWX | CWY))
2344f7df2e56Smrg                action = MOVE_WIN;
2345f7df2e56Smrg            else if (mask & (CWStackMode | CWBorderWidth))
2346f7df2e56Smrg                action = RESTACK_WIN;
2347f7df2e56Smrg            else                /* really nothing to do */
2348f7df2e56Smrg                return (Success);
2349f7df2e56Smrg        }
235005b261ecSmrg    }
235105b261ecSmrg
235205b261ecSmrg    if (action == RESIZE_WIN)
2353f7df2e56Smrg        /* we've already checked whether there's really a size change */
2354f7df2e56Smrg        goto ActuallyDoSomething;
235505b261ecSmrg    if ((mask & CWX) && (x != beforeX))
2356f7df2e56Smrg        goto ActuallyDoSomething;
235705b261ecSmrg    if ((mask & CWY) && (y != beforeY))
2358f7df2e56Smrg        goto ActuallyDoSomething;
2359f7df2e56Smrg    if ((mask & CWBorderWidth) && (bw != wBorderWidth(pWin)))
2360f7df2e56Smrg        goto ActuallyDoSomething;
2361f7df2e56Smrg    if (mask & CWStackMode) {
236205b261ecSmrg#ifndef ROOTLESS
236305b261ecSmrg        /* See above for why we always reorder in rootless mode. */
2364f7df2e56Smrg        if (pWin->nextSib != pSib)
236505b261ecSmrg#endif
2366f7df2e56Smrg            goto ActuallyDoSomething;
236705b261ecSmrg    }
23684202a189Smrg    return Success;
236905b261ecSmrg
2370f7df2e56Smrg ActuallyDoSomething:
2371f7df2e56Smrg    if (pWin->drawable.pScreen->ConfigNotify) {
2372f7df2e56Smrg        int ret;
2373f7df2e56Smrg
2374f7df2e56Smrg        ret =
2375f7df2e56Smrg            (*pWin->drawable.pScreen->ConfigNotify) (pWin, x, y, w, h, bw,
2376f7df2e56Smrg                                                     pSib);
2377f7df2e56Smrg        if (ret) {
2378f7df2e56Smrg            client->errorValue = 0;
2379f7df2e56Smrg            return ret;
2380f7df2e56Smrg        }
23814202a189Smrg    }
23824202a189Smrg
2383f7df2e56Smrg    if (SubStrSend(pWin, pParent)) {
2384f7df2e56Smrg        xEvent event = {
2385f7df2e56Smrg            .u.configureNotify.window = pWin->drawable.id,
2386f7df2e56Smrg            .u.configureNotify.aboveSibling = pSib ? pSib->drawable.id : None,
2387f7df2e56Smrg            .u.configureNotify.x = x,
2388f7df2e56Smrg            .u.configureNotify.y = y,
2389f7df2e56Smrg            .u.configureNotify.width = w,
2390f7df2e56Smrg            .u.configureNotify.height = h,
2391f7df2e56Smrg            .u.configureNotify.borderWidth = bw,
2392f7df2e56Smrg            .u.configureNotify.override = pWin->overrideRedirect
2393f7df2e56Smrg        };
2394f7df2e56Smrg        event.u.u.type = ConfigureNotify;
239505b261ecSmrg#ifdef PANORAMIX
2396f7df2e56Smrg        if (!noPanoramiXExtension && (!pParent || !pParent->parent)) {
2397f7df2e56Smrg            event.u.configureNotify.x += screenInfo.screens[0]->x;
2398f7df2e56Smrg            event.u.configureNotify.y += screenInfo.screens[0]->y;
2399f7df2e56Smrg        }
240005b261ecSmrg#endif
2401f7df2e56Smrg        DeliverEvents(pWin, &event, 1, NullWindow);
240205b261ecSmrg    }
2403f7df2e56Smrg    if (mask & CWBorderWidth) {
2404f7df2e56Smrg        if (action == RESTACK_WIN) {
2405f7df2e56Smrg            action = MOVE_WIN;
2406f7df2e56Smrg            pWin->borderWidth = bw;
2407f7df2e56Smrg        }
2408f7df2e56Smrg        else if ((action == MOVE_WIN) &&
2409f7df2e56Smrg                 (beforeX + wBorderWidth(pWin) == x + (int) bw) &&
2410f7df2e56Smrg                 (beforeY + wBorderWidth(pWin) == y + (int) bw)) {
2411f7df2e56Smrg            action = REBORDER_WIN;
2412f7df2e56Smrg            (*pWin->drawable.pScreen->ChangeBorderWidth) (pWin, bw);
2413f7df2e56Smrg        }
2414f7df2e56Smrg        else
2415f7df2e56Smrg            pWin->borderWidth = bw;
241605b261ecSmrg    }
241705b261ecSmrg    if (action == MOVE_WIN)
2418f7df2e56Smrg        (*pWin->drawable.pScreen->MoveWindow) (pWin, x, y, pSib,
2419f7df2e56Smrg                                               (mask & CWBorderWidth) ? VTOther
2420f7df2e56Smrg                                               : VTMove);
242105b261ecSmrg    else if (action == RESIZE_WIN)
2422f7df2e56Smrg        (*pWin->drawable.pScreen->ResizeWindow) (pWin, x, y, w, h, pSib);
242305b261ecSmrg    else if (mask & CWStackMode)
2424f7df2e56Smrg        ReflectStackChange(pWin, pSib, VTOther);
242505b261ecSmrg
242605b261ecSmrg    if (action != RESTACK_WIN)
2427f7df2e56Smrg        CheckCursorConfinement(pWin);
24284202a189Smrg    return Success;
242905b261ecSmrg#undef RESTACK_WIN
243005b261ecSmrg#undef MOVE_WIN
243105b261ecSmrg#undef RESIZE_WIN
243205b261ecSmrg#undef REBORDER_WIN
243305b261ecSmrg}
243405b261ecSmrg
243505b261ecSmrg/******
243605b261ecSmrg *
243705b261ecSmrg * CirculateWindow
243805b261ecSmrg *    For RaiseLowest, raises the lowest mapped child (if any) that is
243905b261ecSmrg *    obscured by another child to the top of the stack.  For LowerHighest,
244005b261ecSmrg *    lowers the highest mapped child (if any) that is obscuring another
2441f7df2e56Smrg *    child to the bottom of the stack.	 Exposure processing is performed
244205b261ecSmrg *
244305b261ecSmrg ******/
244405b261ecSmrg
244505b261ecSmrgint
244605b261ecSmrgCirculateWindow(WindowPtr pParent, int direction, ClientPtr client)
244705b261ecSmrg{
244805b261ecSmrg    WindowPtr pWin, pHead, pFirst;
244905b261ecSmrg    xEvent event;
245005b261ecSmrg    BoxRec box;
245105b261ecSmrg
245205b261ecSmrg    pHead = RealChildHead(pParent);
245305b261ecSmrg    pFirst = pHead ? pHead->nextSib : pParent->firstChild;
2454f7df2e56Smrg    if (direction == RaiseLowest) {
2455f7df2e56Smrg        for (pWin = pParent->lastChild;
2456f7df2e56Smrg             (pWin != pHead) &&
2457f7df2e56Smrg             !(pWin->mapped &&
2458f7df2e56Smrg               AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box)));
2459f7df2e56Smrg             pWin = pWin->prevSib);
2460f7df2e56Smrg        if (pWin == pHead)
2461f7df2e56Smrg            return Success;
2462f7df2e56Smrg    }
2463f7df2e56Smrg    else {
2464f7df2e56Smrg        for (pWin = pFirst;
2465f7df2e56Smrg             pWin &&
2466f7df2e56Smrg             !(pWin->mapped &&
2467f7df2e56Smrg               IOverlapAnyWindow(pWin, WindowExtents(pWin, &box)));
2468f7df2e56Smrg             pWin = pWin->nextSib);
2469f7df2e56Smrg        if (!pWin)
2470f7df2e56Smrg            return Success;
247105b261ecSmrg    }
247205b261ecSmrg
2473f7df2e56Smrg    event = (xEvent) {
2474f7df2e56Smrg        .u.circulate.window = pWin->drawable.id,
2475f7df2e56Smrg        .u.circulate.parent = pParent->drawable.id,
2476f7df2e56Smrg        .u.circulate.event = pParent->drawable.id,
2477f7df2e56Smrg        .u.circulate.place = (direction == RaiseLowest) ?
2478f7df2e56Smrg                              PlaceOnTop : PlaceOnBottom,
2479f7df2e56Smrg    };
2480f7df2e56Smrg
2481f7df2e56Smrg    if (RedirectSend(pParent)) {
2482f7df2e56Smrg        event.u.u.type = CirculateRequest;
2483f7df2e56Smrg        if (MaybeDeliverEventsToClient(pParent, &event, 1,
2484f7df2e56Smrg                                       SubstructureRedirectMask, client) == 1)
2485f7df2e56Smrg            return Success;
248605b261ecSmrg    }
248705b261ecSmrg
248805b261ecSmrg    event.u.u.type = CirculateNotify;
248905b261ecSmrg    DeliverEvents(pWin, &event, 1, NullWindow);
249005b261ecSmrg    ReflectStackChange(pWin,
2491f7df2e56Smrg                       (direction == RaiseLowest) ? pFirst : NullWindow,
2492f7df2e56Smrg                       VTStack);
249305b261ecSmrg
24944202a189Smrg    return Success;
249505b261ecSmrg}
249605b261ecSmrg
249705b261ecSmrgstatic int
2498f7df2e56SmrgCompareWIDs(WindowPtr pWin, void *value)
2499f7df2e56Smrg{                               /* must conform to VisitWindowProcPtr */
2500f7df2e56Smrg    Window *wid = (Window *) value;
250105b261ecSmrg
250205b261ecSmrg    if (pWin->drawable.id == *wid)
2503f7df2e56Smrg        return WT_STOPWALKING;
250405b261ecSmrg    else
2505f7df2e56Smrg        return WT_WALKCHILDREN;
250605b261ecSmrg}
250705b261ecSmrg
250805b261ecSmrg/*****
250905b261ecSmrg *  ReparentWindow
251005b261ecSmrg *****/
251105b261ecSmrg
251205b261ecSmrgint
251305b261ecSmrgReparentWindow(WindowPtr pWin, WindowPtr pParent,
251405b261ecSmrg               int x, int y, ClientPtr client)
251505b261ecSmrg{
251605b261ecSmrg    WindowPtr pPrev, pPriorParent;
2517f7df2e56Smrg    Bool WasMapped = (Bool) (pWin->mapped);
251805b261ecSmrg    xEvent event;
2519f7df2e56Smrg    int bw = wBorderWidth(pWin);
252005b261ecSmrg    ScreenPtr pScreen;
252105b261ecSmrg
252205b261ecSmrg    pScreen = pWin->drawable.pScreen;
2523f7df2e56Smrg    if (TraverseTree(pWin, CompareWIDs, (void *) &pParent->drawable.id) ==
2524f7df2e56Smrg        WT_STOPWALKING)
2525f7df2e56Smrg        return BadMatch;
252605b261ecSmrg    if (!MakeWindowOptional(pWin))
2527f7df2e56Smrg        return BadAlloc;
252805b261ecSmrg
252905b261ecSmrg    if (WasMapped)
2530f7df2e56Smrg        UnmapWindow(pWin, FALSE);
2531f7df2e56Smrg
2532f7df2e56Smrg    event = (xEvent) {
2533f7df2e56Smrg        .u.reparent.window = pWin->drawable.id,
2534f7df2e56Smrg        .u.reparent.parent = pParent->drawable.id,
2535f7df2e56Smrg        .u.reparent.x = x,
2536f7df2e56Smrg        .u.reparent.y = y,
2537f7df2e56Smrg        .u.reparent.override = pWin->overrideRedirect
2538f7df2e56Smrg    };
253905b261ecSmrg    event.u.u.type = ReparentNotify;
254005b261ecSmrg#ifdef PANORAMIX
2541f7df2e56Smrg    if (!noPanoramiXExtension && !pParent->parent) {
2542f7df2e56Smrg        event.u.reparent.x += screenInfo.screens[0]->x;
2543f7df2e56Smrg        event.u.reparent.y += screenInfo.screens[0]->y;
254405b261ecSmrg    }
254505b261ecSmrg#endif
254605b261ecSmrg    DeliverEvents(pWin, &event, 1, pParent);
254705b261ecSmrg
254805b261ecSmrg    /* take out of sibling chain */
254905b261ecSmrg
255005b261ecSmrg    pPriorParent = pPrev = pWin->parent;
255105b261ecSmrg    if (pPrev->firstChild == pWin)
2552f7df2e56Smrg        pPrev->firstChild = pWin->nextSib;
255305b261ecSmrg    if (pPrev->lastChild == pWin)
2554f7df2e56Smrg        pPrev->lastChild = pWin->prevSib;
255505b261ecSmrg
255605b261ecSmrg    if (pWin->nextSib)
2557f7df2e56Smrg        pWin->nextSib->prevSib = pWin->prevSib;
255805b261ecSmrg    if (pWin->prevSib)
2559f7df2e56Smrg        pWin->prevSib->nextSib = pWin->nextSib;
256005b261ecSmrg
256105b261ecSmrg    /* insert at begining of pParent */
256205b261ecSmrg    pWin->parent = pParent;
256305b261ecSmrg    pPrev = RealChildHead(pParent);
2564f7df2e56Smrg    if (pPrev) {
2565f7df2e56Smrg        pWin->nextSib = pPrev->nextSib;
2566f7df2e56Smrg        if (pPrev->nextSib)
2567f7df2e56Smrg            pPrev->nextSib->prevSib = pWin;
2568f7df2e56Smrg        else
2569f7df2e56Smrg            pParent->lastChild = pWin;
2570f7df2e56Smrg        pPrev->nextSib = pWin;
2571f7df2e56Smrg        pWin->prevSib = pPrev;
257205b261ecSmrg    }
2573f7df2e56Smrg    else {
2574f7df2e56Smrg        pWin->nextSib = pParent->firstChild;
2575f7df2e56Smrg        pWin->prevSib = NullWindow;
2576f7df2e56Smrg        if (pParent->firstChild)
2577f7df2e56Smrg            pParent->firstChild->prevSib = pWin;
2578f7df2e56Smrg        else
2579f7df2e56Smrg            pParent->lastChild = pWin;
2580f7df2e56Smrg        pParent->firstChild = pWin;
258105b261ecSmrg    }
258205b261ecSmrg
258305b261ecSmrg    pWin->origin.x = x + bw;
258405b261ecSmrg    pWin->origin.y = y + bw;
258505b261ecSmrg    pWin->drawable.x = x + bw + pParent->drawable.x;
258605b261ecSmrg    pWin->drawable.y = y + bw + pParent->drawable.y;
258705b261ecSmrg
258805b261ecSmrg    /* clip to parent */
2589f7df2e56Smrg    SetWinSize(pWin);
2590f7df2e56Smrg    SetBorderSize(pWin);
259105b261ecSmrg
259205b261ecSmrg    if (pScreen->ReparentWindow)
2593f7df2e56Smrg        (*pScreen->ReparentWindow) (pWin, pPriorParent);
2594f7df2e56Smrg    (*pScreen->PositionWindow) (pWin, pWin->drawable.x, pWin->drawable.y);
259505b261ecSmrg    ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
259605b261ecSmrg
259705b261ecSmrg    CheckWindowOptionalNeed(pWin);
259805b261ecSmrg
259905b261ecSmrg    if (WasMapped)
2600f7df2e56Smrg        MapWindow(pWin, client);
260105b261ecSmrg    RecalculateDeliverableEvents(pWin);
26024202a189Smrg    return Success;
260305b261ecSmrg}
260405b261ecSmrg
260505b261ecSmrgstatic void
260605b261ecSmrgRealizeTree(WindowPtr pWin)
260705b261ecSmrg{
260805b261ecSmrg    WindowPtr pChild;
260905b261ecSmrg    RealizeWindowProcPtr Realize;
261005b261ecSmrg
261105b261ecSmrg    Realize = pWin->drawable.pScreen->RealizeWindow;
261205b261ecSmrg    pChild = pWin;
2613f7df2e56Smrg    while (1) {
2614f7df2e56Smrg        if (pChild->mapped) {
2615f7df2e56Smrg            pChild->realized = TRUE;
2616f7df2e56Smrg            pChild->viewable = (pChild->drawable.class == InputOutput);
2617f7df2e56Smrg            (*Realize) (pChild);
2618f7df2e56Smrg            if (pChild->firstChild) {
2619f7df2e56Smrg                pChild = pChild->firstChild;
2620f7df2e56Smrg                continue;
2621f7df2e56Smrg            }
2622f7df2e56Smrg        }
2623f7df2e56Smrg        while (!pChild->nextSib && (pChild != pWin))
2624f7df2e56Smrg            pChild = pChild->parent;
2625f7df2e56Smrg        if (pChild == pWin)
2626f7df2e56Smrg            return;
2627f7df2e56Smrg        pChild = pChild->nextSib;
2628f7df2e56Smrg    }
262905b261ecSmrg}
263005b261ecSmrg
2631f7df2e56Smrgstatic Bool
2632f7df2e56SmrgMaybeDeliverMapRequest(WindowPtr pWin, WindowPtr pParent, ClientPtr client)
263305b261ecSmrg{
2634f7df2e56Smrg    xEvent event = {
2635f7df2e56Smrg        .u.mapRequest.window = pWin->drawable.id,
2636f7df2e56Smrg        .u.mapRequest.parent = pParent->drawable.id
2637f7df2e56Smrg    };
2638f7df2e56Smrg    event.u.u.type = MapRequest;
2639f7df2e56Smrg
2640f7df2e56Smrg    return MaybeDeliverEventsToClient(pParent, &event, 1,
2641f7df2e56Smrg                                      SubstructureRedirectMask,
2642f7df2e56Smrg                                      client) == 1;
264305b261ecSmrg}
264405b261ecSmrg
2645f7df2e56Smrgstatic void
2646f7df2e56SmrgDeliverMapNotify(WindowPtr pWin)
264705b261ecSmrg{
2648f7df2e56Smrg    xEvent event = {
2649f7df2e56Smrg        .u.mapNotify.window = pWin->drawable.id,
2650f7df2e56Smrg        .u.mapNotify.override = pWin->overrideRedirect,
2651f7df2e56Smrg    };
2652f7df2e56Smrg    event.u.u.type = MapNotify;
2653f7df2e56Smrg    DeliverEvents(pWin, &event, 1, NullWindow);
265405b261ecSmrg}
265505b261ecSmrg
265605b261ecSmrg/*****
265705b261ecSmrg * MapWindow
265805b261ecSmrg *    If some other client has selected SubStructureReDirect on the parent
265905b261ecSmrg *    and override-redirect is xFalse, then a MapRequest event is generated,
266005b261ecSmrg *    but the window remains unmapped.	Otherwise, the window is mapped and a
266105b261ecSmrg *    MapNotify event is generated.
266205b261ecSmrg *****/
266305b261ecSmrg
26644202a189Smrgint
266505b261ecSmrgMapWindow(WindowPtr pWin, ClientPtr client)
266605b261ecSmrg{
266705b261ecSmrg    ScreenPtr pScreen;
266805b261ecSmrg
266905b261ecSmrg    WindowPtr pParent;
2670f7df2e56Smrg    WindowPtr pLayerWin;
267105b261ecSmrg
267205b261ecSmrg    if (pWin->mapped)
2673f7df2e56Smrg        return Success;
267405b261ecSmrg
2675f7df2e56Smrg    /* general check for permission to map window */
2676637ac9abSmrg    if (XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id, RT_WINDOW,
2677f7df2e56Smrg                 pWin, RT_NONE, NULL, DixShowAccess) != Success)
2678f7df2e56Smrg        return Success;
267905b261ecSmrg
268005b261ecSmrg    pScreen = pWin->drawable.pScreen;
2681f7df2e56Smrg    if ((pParent = pWin->parent)) {
2682f7df2e56Smrg        Bool anyMarked;
2683f7df2e56Smrg
2684f7df2e56Smrg        if ((!pWin->overrideRedirect) && (RedirectSend(pParent)))
2685f7df2e56Smrg            if (MaybeDeliverMapRequest(pWin, pParent, client))
2686f7df2e56Smrg                return Success;
2687f7df2e56Smrg
2688f7df2e56Smrg        pWin->mapped = TRUE;
2689f7df2e56Smrg        if (SubStrSend(pWin, pParent))
2690f7df2e56Smrg            DeliverMapNotify(pWin);
2691f7df2e56Smrg
2692f7df2e56Smrg        if (!pParent->realized)
2693f7df2e56Smrg            return Success;
2694f7df2e56Smrg        RealizeTree(pWin);
2695f7df2e56Smrg        if (pWin->viewable) {
2696f7df2e56Smrg            anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin,
2697f7df2e56Smrg                                                           &pLayerWin);
2698f7df2e56Smrg            if (anyMarked) {
2699f7df2e56Smrg                (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTMap);
2700f7df2e56Smrg                (*pScreen->HandleExposures) (pLayerWin->parent);
2701f7df2e56Smrg                if (pScreen->PostValidateTree)
2702f7df2e56Smrg                    (*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin,
2703f7df2e56Smrg                                                  VTMap);
2704f7df2e56Smrg            }
2705f7df2e56Smrg        }
2706f7df2e56Smrg        WindowsRestructured();
270705b261ecSmrg    }
2708f7df2e56Smrg    else {
2709f7df2e56Smrg        RegionRec temp;
2710f7df2e56Smrg
2711f7df2e56Smrg        pWin->mapped = TRUE;
2712f7df2e56Smrg        pWin->realized = TRUE;  /* for roots */
2713f7df2e56Smrg        pWin->viewable = pWin->drawable.class == InputOutput;
2714f7df2e56Smrg        /* We SHOULD check for an error value here XXX */
2715f7df2e56Smrg        (*pScreen->RealizeWindow) (pWin);
2716f7df2e56Smrg        if (pScreen->ClipNotify)
2717f7df2e56Smrg            (*pScreen->ClipNotify) (pWin, 0, 0);
2718f7df2e56Smrg        if (pScreen->PostValidateTree)
2719f7df2e56Smrg            (*pScreen->PostValidateTree) (NullWindow, pWin, VTMap);
2720f7df2e56Smrg        RegionNull(&temp);
2721f7df2e56Smrg        RegionCopy(&temp, &pWin->clipList);
2722f7df2e56Smrg        (*pScreen->WindowExposures) (pWin, &temp);
2723f7df2e56Smrg        RegionUninit(&temp);
272405b261ecSmrg    }
272505b261ecSmrg
27264202a189Smrg    return Success;
272705b261ecSmrg}
272805b261ecSmrg
272905b261ecSmrg/*****
273005b261ecSmrg * MapSubwindows
273105b261ecSmrg *    Performs a MapWindow all unmapped children of the window, in top
273205b261ecSmrg *    to bottom stacking order.
273305b261ecSmrg *****/
273405b261ecSmrg
273505b261ecSmrgvoid
273605b261ecSmrgMapSubwindows(WindowPtr pParent, ClientPtr client)
273705b261ecSmrg{
2738f7df2e56Smrg    WindowPtr pWin;
2739f7df2e56Smrg    WindowPtr pFirstMapped = NullWindow;
2740f7df2e56Smrg    ScreenPtr pScreen;
2741f7df2e56Smrg    Mask parentRedirect;
2742f7df2e56Smrg    Mask parentNotify;
2743f7df2e56Smrg    Bool anyMarked;
2744f7df2e56Smrg    WindowPtr pLayerWin;
274505b261ecSmrg
274605b261ecSmrg    pScreen = pParent->drawable.pScreen;
274705b261ecSmrg    parentRedirect = RedirectSend(pParent);
274805b261ecSmrg    parentNotify = SubSend(pParent);
274905b261ecSmrg    anyMarked = FALSE;
2750f7df2e56Smrg    for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) {
2751f7df2e56Smrg        if (!pWin->mapped) {
2752f7df2e56Smrg            if (parentRedirect && !pWin->overrideRedirect)
2753f7df2e56Smrg                if (MaybeDeliverMapRequest(pWin, pParent, client))
2754f7df2e56Smrg                    continue;
2755f7df2e56Smrg
2756f7df2e56Smrg            pWin->mapped = TRUE;
2757f7df2e56Smrg            if (parentNotify || StrSend(pWin))
2758f7df2e56Smrg                DeliverMapNotify(pWin);
2759f7df2e56Smrg
2760f7df2e56Smrg            if (!pFirstMapped)
2761f7df2e56Smrg                pFirstMapped = pWin;
2762f7df2e56Smrg            if (pParent->realized) {
2763f7df2e56Smrg                RealizeTree(pWin);
2764f7df2e56Smrg                if (pWin->viewable) {
2765f7df2e56Smrg                    anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin,
2766f7df2e56Smrg                                                                    NULL);
2767f7df2e56Smrg                }
2768f7df2e56Smrg            }
2769f7df2e56Smrg        }
2770f7df2e56Smrg    }
2771f7df2e56Smrg
2772f7df2e56Smrg    if (pFirstMapped) {
2773f7df2e56Smrg        pLayerWin = (*pScreen->GetLayerWindow) (pParent);
2774f7df2e56Smrg        if (pLayerWin->parent != pParent) {
2775f7df2e56Smrg            anyMarked |= (*pScreen->MarkOverlappedWindows) (pLayerWin,
2776f7df2e56Smrg                                                            pLayerWin, NULL);
2777f7df2e56Smrg            pFirstMapped = pLayerWin;
2778f7df2e56Smrg        }
2779f7df2e56Smrg        if (anyMarked) {
2780f7df2e56Smrg            (*pScreen->ValidateTree) (pLayerWin->parent, pFirstMapped, VTMap);
2781f7df2e56Smrg            (*pScreen->HandleExposures) (pLayerWin->parent);
2782f7df2e56Smrg            if (pScreen->PostValidateTree)
2783f7df2e56Smrg                (*pScreen->PostValidateTree) (pLayerWin->parent, pFirstMapped,
2784f7df2e56Smrg                                              VTMap);
2785f7df2e56Smrg        }
2786f7df2e56Smrg        WindowsRestructured();
278705b261ecSmrg    }
278805b261ecSmrg}
278905b261ecSmrg
279005b261ecSmrgstatic void
2791f7df2e56SmrgUnrealizeTree(WindowPtr pWin, Bool fromConfigure)
279205b261ecSmrg{
279305b261ecSmrg    WindowPtr pChild;
279405b261ecSmrg    UnrealizeWindowProcPtr Unrealize;
279505b261ecSmrg    MarkUnrealizedWindowProcPtr MarkUnrealizedWindow;
279605b261ecSmrg
279705b261ecSmrg    Unrealize = pWin->drawable.pScreen->UnrealizeWindow;
279805b261ecSmrg    MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow;
279905b261ecSmrg    pChild = pWin;
2800f7df2e56Smrg    while (1) {
2801f7df2e56Smrg        if (pChild->realized) {
2802f7df2e56Smrg            pChild->realized = FALSE;
2803f7df2e56Smrg            pChild->visibility = VisibilityNotViewable;
280405b261ecSmrg#ifdef PANORAMIX
2805f7df2e56Smrg            if (!noPanoramiXExtension && !pChild->drawable.pScreen->myNum) {
2806f7df2e56Smrg                PanoramiXRes *win;
2807f7df2e56Smrg                int rc = dixLookupResourceByType((void **) &win,
2808f7df2e56Smrg                                                 pChild->drawable.id,
2809f7df2e56Smrg                                                 XRT_WINDOW,
2810f7df2e56Smrg                                                 serverClient, DixWriteAccess);
2811f7df2e56Smrg
2812f7df2e56Smrg                if (rc == Success)
2813f7df2e56Smrg                    win->u.win.visibility = VisibilityNotViewable;
2814f7df2e56Smrg            }
281505b261ecSmrg#endif
2816f7df2e56Smrg            (*Unrealize) (pChild);
2817f7df2e56Smrg            DeleteWindowFromAnyEvents(pChild, FALSE);
2818f7df2e56Smrg            if (pChild->viewable) {
2819f7df2e56Smrg                pChild->viewable = FALSE;
2820f7df2e56Smrg                (*MarkUnrealizedWindow) (pChild, pWin, fromConfigure);
2821f7df2e56Smrg                pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
2822f7df2e56Smrg            }
2823f7df2e56Smrg            if (pChild->firstChild) {
2824f7df2e56Smrg                pChild = pChild->firstChild;
2825f7df2e56Smrg                continue;
2826f7df2e56Smrg            }
2827f7df2e56Smrg        }
2828f7df2e56Smrg        while (!pChild->nextSib && (pChild != pWin))
2829f7df2e56Smrg            pChild = pChild->parent;
2830f7df2e56Smrg        if (pChild == pWin)
2831f7df2e56Smrg            return;
2832f7df2e56Smrg        pChild = pChild->nextSib;
283305b261ecSmrg    }
283405b261ecSmrg}
283505b261ecSmrg
2836f7df2e56Smrgstatic void
2837f7df2e56SmrgDeliverUnmapNotify(WindowPtr pWin, Bool fromConfigure)
2838f7df2e56Smrg{
2839f7df2e56Smrg    xEvent event = {
2840f7df2e56Smrg        .u.unmapNotify.window = pWin->drawable.id,
2841f7df2e56Smrg        .u.unmapNotify.fromConfigure = fromConfigure
2842f7df2e56Smrg    };
2843f7df2e56Smrg    event.u.u.type = UnmapNotify;
2844f7df2e56Smrg    DeliverEvents(pWin, &event, 1, NullWindow);
2845f7df2e56Smrg}
2846f7df2e56Smrg
284705b261ecSmrg/*****
284805b261ecSmrg * UnmapWindow
284905b261ecSmrg *    If the window is already unmapped, this request has no effect.
285005b261ecSmrg *    Otherwise, the window is unmapped and an UnMapNotify event is
285105b261ecSmrg *    generated.  Cannot unmap a root window.
285205b261ecSmrg *****/
285305b261ecSmrg
28544202a189Smrgint
285505b261ecSmrgUnmapWindow(WindowPtr pWin, Bool fromConfigure)
285605b261ecSmrg{
285705b261ecSmrg    WindowPtr pParent;
2858f7df2e56Smrg    Bool wasRealized = (Bool) pWin->realized;
2859f7df2e56Smrg    Bool wasViewable = (Bool) pWin->viewable;
286005b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
286105b261ecSmrg    WindowPtr pLayerWin = pWin;
286205b261ecSmrg
286305b261ecSmrg    if ((!pWin->mapped) || (!(pParent = pWin->parent)))
2864f7df2e56Smrg        return Success;
2865f7df2e56Smrg    if (SubStrSend(pWin, pParent))
2866f7df2e56Smrg        DeliverUnmapNotify(pWin, fromConfigure);
2867f7df2e56Smrg    if (wasViewable && !fromConfigure) {
2868f7df2e56Smrg        pWin->valdata = UnmapValData;
2869f7df2e56Smrg        (*pScreen->MarkOverlappedWindows) (pWin, pWin->nextSib, &pLayerWin);
2870f7df2e56Smrg        (*pScreen->MarkWindow) (pLayerWin->parent);
287105b261ecSmrg    }
287205b261ecSmrg    pWin->mapped = FALSE;
287305b261ecSmrg    if (wasRealized)
2874f7df2e56Smrg        UnrealizeTree(pWin, fromConfigure);
2875f7df2e56Smrg    if (wasViewable) {
2876f7df2e56Smrg        if (!fromConfigure) {
2877f7df2e56Smrg            (*pScreen->ValidateTree) (pLayerWin->parent, pWin, VTUnmap);
2878f7df2e56Smrg            (*pScreen->HandleExposures) (pLayerWin->parent);
2879f7df2e56Smrg            if (pScreen->PostValidateTree)
2880f7df2e56Smrg                (*pScreen->PostValidateTree) (pLayerWin->parent, pWin, VTUnmap);
2881f7df2e56Smrg        }
2882f7df2e56Smrg    }
2883f7df2e56Smrg    if (wasRealized && !fromConfigure) {
2884f7df2e56Smrg        WindowsRestructured();
2885f7df2e56Smrg        WindowGone(pWin);
2886f7df2e56Smrg    }
28874202a189Smrg    return Success;
288805b261ecSmrg}
288905b261ecSmrg
289005b261ecSmrg/*****
289105b261ecSmrg * UnmapSubwindows
289205b261ecSmrg *    Performs an UnmapWindow request with the specified mode on all mapped
289305b261ecSmrg *    children of the window, in bottom to top stacking order.
289405b261ecSmrg *****/
289505b261ecSmrg
289605b261ecSmrgvoid
289705b261ecSmrgUnmapSubwindows(WindowPtr pWin)
289805b261ecSmrg{
289905b261ecSmrg    WindowPtr pChild, pHead;
2900f7df2e56Smrg    Bool wasRealized = (Bool) pWin->realized;
2901f7df2e56Smrg    Bool wasViewable = (Bool) pWin->viewable;
290205b261ecSmrg    Bool anyMarked = FALSE;
290305b261ecSmrg    Mask parentNotify;
290405b261ecSmrg    WindowPtr pLayerWin = NULL;
290505b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
290605b261ecSmrg
290705b261ecSmrg    if (!pWin->firstChild)
2908f7df2e56Smrg        return;
290905b261ecSmrg    parentNotify = SubSend(pWin);
291005b261ecSmrg    pHead = RealChildHead(pWin);
291105b261ecSmrg
291205b261ecSmrg    if (wasViewable)
2913f7df2e56Smrg        pLayerWin = (*pScreen->GetLayerWindow) (pWin);
2914f7df2e56Smrg
2915f7df2e56Smrg    for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) {
2916f7df2e56Smrg        if (pChild->mapped) {
2917f7df2e56Smrg            if (parentNotify || StrSend(pChild))
2918f7df2e56Smrg                DeliverUnmapNotify(pChild, xFalse);
2919f7df2e56Smrg            if (pChild->viewable) {
2920f7df2e56Smrg                pChild->valdata = UnmapValData;
2921f7df2e56Smrg                anyMarked = TRUE;
2922f7df2e56Smrg            }
2923f7df2e56Smrg            pChild->mapped = FALSE;
2924f7df2e56Smrg            if (pChild->realized)
2925f7df2e56Smrg                UnrealizeTree(pChild, FALSE);
2926f7df2e56Smrg        }
292705b261ecSmrg    }
2928f7df2e56Smrg    if (wasViewable) {
2929f7df2e56Smrg        if (anyMarked) {
2930f7df2e56Smrg            if (pLayerWin->parent == pWin)
2931f7df2e56Smrg                (*pScreen->MarkWindow) (pWin);
2932f7df2e56Smrg            else {
2933f7df2e56Smrg                WindowPtr ptmp;
2934f7df2e56Smrg
2935f7df2e56Smrg                (*pScreen->MarkOverlappedWindows) (pWin, pLayerWin, NULL);
2936f7df2e56Smrg                (*pScreen->MarkWindow) (pLayerWin->parent);
2937f7df2e56Smrg
2938f7df2e56Smrg                /* Windows between pWin and pLayerWin may not have been marked */
2939f7df2e56Smrg                ptmp = pWin;
2940f7df2e56Smrg
2941f7df2e56Smrg                while (ptmp != pLayerWin->parent) {
2942f7df2e56Smrg                    (*pScreen->MarkWindow) (ptmp);
2943f7df2e56Smrg                    ptmp = ptmp->parent;
2944f7df2e56Smrg                }
294505b261ecSmrg                pHead = pWin->firstChild;
2946f7df2e56Smrg            }
2947f7df2e56Smrg            (*pScreen->ValidateTree) (pLayerWin->parent, pHead, VTUnmap);
2948f7df2e56Smrg            (*pScreen->HandleExposures) (pLayerWin->parent);
2949f7df2e56Smrg            if (pScreen->PostValidateTree)
2950f7df2e56Smrg                (*pScreen->PostValidateTree) (pLayerWin->parent, pHead,
2951f7df2e56Smrg                                              VTUnmap);
2952f7df2e56Smrg        }
2953f7df2e56Smrg    }
2954f7df2e56Smrg    if (wasRealized) {
2955f7df2e56Smrg        WindowsRestructured();
2956f7df2e56Smrg        WindowGone(pWin);
295705b261ecSmrg    }
295805b261ecSmrg}
295905b261ecSmrg
296005b261ecSmrgvoid
296105b261ecSmrgHandleSaveSet(ClientPtr client)
296205b261ecSmrg{
296305b261ecSmrg    WindowPtr pParent, pWin;
296405b261ecSmrg    int j;
296505b261ecSmrg
2966f7df2e56Smrg    for (j = 0; j < client->numSaved; j++) {
2967f7df2e56Smrg        pWin = SaveSetWindow(client->saveSet[j]);
2968f7df2e56Smrg        if (SaveSetToRoot(client->saveSet[j]))
2969f7df2e56Smrg            pParent = pWin->drawable.pScreen->root;
2970f7df2e56Smrg        else
2971f7df2e56Smrg        {
2972f7df2e56Smrg            pParent = pWin->parent;
2973f7df2e56Smrg            while (pParent && (wClient(pParent) == client))
2974f7df2e56Smrg                pParent = pParent->parent;
2975f7df2e56Smrg        }
2976f7df2e56Smrg        if (pParent) {
2977f7df2e56Smrg            if (pParent != pWin->parent) {
2978f7df2e56Smrg                /* unmap first so that ReparentWindow doesn't remap */
2979f7df2e56Smrg                if (!SaveSetShouldMap(client->saveSet[j]))
2980f7df2e56Smrg                    UnmapWindow(pWin, FALSE);
2981f7df2e56Smrg                ReparentWindow(pWin, pParent,
2982f7df2e56Smrg                               pWin->drawable.x - wBorderWidth(pWin) -
2983f7df2e56Smrg                               pParent->drawable.x,
2984f7df2e56Smrg                               pWin->drawable.y - wBorderWidth(pWin) -
2985f7df2e56Smrg                               pParent->drawable.y, client);
2986f7df2e56Smrg                if (!pWin->realized && pWin->mapped)
2987f7df2e56Smrg                    pWin->mapped = FALSE;
2988f7df2e56Smrg            }
2989f7df2e56Smrg            if (SaveSetShouldMap(client->saveSet[j]))
2990f7df2e56Smrg                MapWindow(pWin, client);
2991f7df2e56Smrg        }
299205b261ecSmrg    }
29934202a189Smrg    free(client->saveSet);
299405b261ecSmrg    client->numSaved = 0;
2995f7df2e56Smrg    client->saveSet = NULL;
299605b261ecSmrg}
299705b261ecSmrg
299805b261ecSmrg/**
299905b261ecSmrg *
300005b261ecSmrg * \param x,y  in root
300105b261ecSmrg */
300205b261ecSmrgBool
300305b261ecSmrgPointInWindowIsVisible(WindowPtr pWin, int x, int y)
300405b261ecSmrg{
300505b261ecSmrg    BoxRec box;
300605b261ecSmrg
300705b261ecSmrg    if (!pWin->realized)
3008f7df2e56Smrg        return FALSE;
3009f7df2e56Smrg    if (RegionContainsPoint(&pWin->borderClip, x, y, &box)
3010f7df2e56Smrg        && (!wInputShape(pWin) ||
3011f7df2e56Smrg            RegionContainsPoint(wInputShape(pWin),
3012f7df2e56Smrg                                x - pWin->drawable.x,
3013f7df2e56Smrg                                y - pWin->drawable.y, &box)))
3014f7df2e56Smrg        return TRUE;
30154202a189Smrg    return FALSE;
301605b261ecSmrg}
301705b261ecSmrg
30184202a189SmrgRegionPtr
301905b261ecSmrgNotClippedByChildren(WindowPtr pWin)
302005b261ecSmrg{
30214202a189Smrg    RegionPtr pReg = RegionCreate(NullBox, 1);
3022f7df2e56Smrg
302305b261ecSmrg    if (pWin->parent ||
3024f7df2e56Smrg        screenIsSaved != SCREEN_SAVER_ON ||
3025f7df2e56Smrg        !HasSaverWindow(pWin->drawable.pScreen)) {
3026f7df2e56Smrg        RegionIntersect(pReg, &pWin->borderClip, &pWin->winSize);
302705b261ecSmrg    }
30284202a189Smrg    return pReg;
302905b261ecSmrg}
303005b261ecSmrg
3031637ac9abSmrgvoid
303205b261ecSmrgSendVisibilityNotify(WindowPtr pWin)
303305b261ecSmrg{
303405b261ecSmrg    xEvent event;
30354202a189Smrg    unsigned int visibility = pWin->visibility;
30364202a189Smrg
303705b261ecSmrg#ifdef PANORAMIX
303805b261ecSmrg    /* This is not quite correct yet, but it's close */
3039f7df2e56Smrg    if (!noPanoramiXExtension) {
3040f7df2e56Smrg        PanoramiXRes *win;
3041f7df2e56Smrg        WindowPtr pWin2;
3042f7df2e56Smrg        int rc, i, Scrnum;
3043f7df2e56Smrg
3044f7df2e56Smrg        Scrnum = pWin->drawable.pScreen->myNum;
3045f7df2e56Smrg
3046f7df2e56Smrg        win = PanoramiXFindIDByScrnum(XRT_WINDOW, pWin->drawable.id, Scrnum);
3047f7df2e56Smrg
3048f7df2e56Smrg        if (!win || (win->u.win.visibility == visibility))
3049f7df2e56Smrg            return;
3050f7df2e56Smrg
3051f7df2e56Smrg        switch (visibility) {
3052f7df2e56Smrg        case VisibilityUnobscured:
3053f7df2e56Smrg        FOR_NSCREENS(i) {
3054f7df2e56Smrg            if (i == Scrnum)
3055f7df2e56Smrg                continue;
3056f7df2e56Smrg
3057f7df2e56Smrg            rc = dixLookupWindow(&pWin2, win->info[i].id, serverClient,
3058f7df2e56Smrg                                 DixWriteAccess);
3059f7df2e56Smrg
3060f7df2e56Smrg            if (rc == Success) {
3061f7df2e56Smrg                if (pWin2->visibility == VisibilityPartiallyObscured)
3062f7df2e56Smrg                    return;
3063f7df2e56Smrg
3064f7df2e56Smrg                if (!i)
3065f7df2e56Smrg                    pWin = pWin2;
3066f7df2e56Smrg            }
3067f7df2e56Smrg        }
3068f7df2e56Smrg            break;
3069f7df2e56Smrg        case VisibilityPartiallyObscured:
3070f7df2e56Smrg            if (Scrnum) {
3071f7df2e56Smrg                rc = dixLookupWindow(&pWin2, win->info[0].id, serverClient,
3072f7df2e56Smrg                                     DixWriteAccess);
3073f7df2e56Smrg                if (rc == Success)
3074f7df2e56Smrg                    pWin = pWin2;
3075f7df2e56Smrg            }
3076f7df2e56Smrg            break;
3077f7df2e56Smrg        case VisibilityFullyObscured:
3078f7df2e56Smrg        FOR_NSCREENS(i) {
3079f7df2e56Smrg            if (i == Scrnum)
3080f7df2e56Smrg                continue;
3081f7df2e56Smrg
3082f7df2e56Smrg            rc = dixLookupWindow(&pWin2, win->info[i].id, serverClient,
3083f7df2e56Smrg                                 DixWriteAccess);
3084f7df2e56Smrg
3085f7df2e56Smrg            if (rc == Success) {
3086f7df2e56Smrg                if (pWin2->visibility != VisibilityFullyObscured)
3087f7df2e56Smrg                    return;
3088f7df2e56Smrg
3089f7df2e56Smrg                if (!i)
3090f7df2e56Smrg                    pWin = pWin2;
3091f7df2e56Smrg            }
3092f7df2e56Smrg        }
3093f7df2e56Smrg            break;
3094f7df2e56Smrg        }
3095f7df2e56Smrg
3096f7df2e56Smrg        win->u.win.visibility = visibility;
309705b261ecSmrg    }
309805b261ecSmrg#endif
309905b261ecSmrg
3100f7df2e56Smrg    event = (xEvent) {
3101f7df2e56Smrg        .u.visibility.window = pWin->drawable.id,
3102f7df2e56Smrg        .u.visibility.state = visibility
3103f7df2e56Smrg    };
310405b261ecSmrg    event.u.u.type = VisibilityNotify;
310505b261ecSmrg    DeliverEvents(pWin, &event, 1, NullWindow);
310605b261ecSmrg}
310705b261ecSmrg
310805b261ecSmrg#define RANDOM_WIDTH 32
31094202a189Smrgint
3110637ac9abSmrgdixSaveScreens(ClientPtr client, int on, int mode)
311105b261ecSmrg{
3112637ac9abSmrg    int rc, i, what, type;
311305b261ecSmrg
3114f7df2e56Smrg    if (on == SCREEN_SAVER_FORCER) {
3115f7df2e56Smrg        if (mode == ScreenSaverReset)
3116f7df2e56Smrg            what = SCREEN_SAVER_OFF;
3117f7df2e56Smrg        else
3118f7df2e56Smrg            what = SCREEN_SAVER_ON;
3119f7df2e56Smrg        type = what;
312005b261ecSmrg    }
3121f7df2e56Smrg    else {
3122f7df2e56Smrg        what = on;
3123f7df2e56Smrg        type = what;
3124f7df2e56Smrg        if (what == screenIsSaved)
3125f7df2e56Smrg            type = SCREEN_SAVER_CYCLE;
312605b261ecSmrg    }
3127637ac9abSmrg
3128637ac9abSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
3129f7df2e56Smrg        rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3130f7df2e56Smrg                      DixShowAccess | DixHideAccess);
3131f7df2e56Smrg        if (rc != Success)
3132f7df2e56Smrg            return rc;
3133637ac9abSmrg    }
3134f7df2e56Smrg    for (i = 0; i < screenInfo.numScreens; i++) {
3135f7df2e56Smrg        ScreenPtr pScreen = screenInfo.screens[i];
3136f7df2e56Smrg
3137f7df2e56Smrg        if (on == SCREEN_SAVER_FORCER)
3138f7df2e56Smrg            (*pScreen->SaveScreen) (pScreen, on);
3139f7df2e56Smrg        if (pScreen->screensaver.ExternalScreenSaver) {
3140f7df2e56Smrg            if ((*pScreen->screensaver.ExternalScreenSaver)
3141f7df2e56Smrg                (pScreen, type, on == SCREEN_SAVER_FORCER))
3142f7df2e56Smrg                continue;
3143f7df2e56Smrg        }
3144f7df2e56Smrg        if (type == screenIsSaved)
3145f7df2e56Smrg            continue;
3146f7df2e56Smrg        switch (type) {
3147f7df2e56Smrg        case SCREEN_SAVER_OFF:
3148f7df2e56Smrg            if (pScreen->screensaver.blanked == SCREEN_IS_BLANKED) {
3149f7df2e56Smrg                (*pScreen->SaveScreen) (pScreen, what);
3150f7df2e56Smrg            }
3151f7df2e56Smrg            else if (HasSaverWindow(pScreen)) {
3152f7df2e56Smrg                pScreen->screensaver.pWindow = NullWindow;
3153f7df2e56Smrg                FreeResource(pScreen->screensaver.wid, RT_NONE);
3154f7df2e56Smrg            }
3155f7df2e56Smrg            break;
3156f7df2e56Smrg        case SCREEN_SAVER_CYCLE:
3157f7df2e56Smrg            if (pScreen->screensaver.blanked == SCREEN_IS_TILED) {
3158f7df2e56Smrg                WindowPtr pWin = pScreen->screensaver.pWindow;
3159f7df2e56Smrg
3160f7df2e56Smrg                /* make it look like screen saver is off, so that
3161f7df2e56Smrg                 * NotClippedByChildren will compute a clip list
3162f7df2e56Smrg                 * for the root window, so PaintWindow works
3163f7df2e56Smrg                 */
3164f7df2e56Smrg                screenIsSaved = SCREEN_SAVER_OFF;
3165f7df2e56Smrg                (*pWin->drawable.pScreen->MoveWindow) (pWin,
3166f7df2e56Smrg                                                       (short) (-
3167f7df2e56Smrg                                                                (rand() %
3168f7df2e56Smrg                                                                 RANDOM_WIDTH)),
3169f7df2e56Smrg                                                       (short) (-
3170f7df2e56Smrg                                                                (rand() %
3171f7df2e56Smrg                                                                 RANDOM_WIDTH)),
3172f7df2e56Smrg                                                       pWin->nextSib, VTMove);
3173f7df2e56Smrg                screenIsSaved = SCREEN_SAVER_ON;
3174f7df2e56Smrg            }
3175f7df2e56Smrg            /*
3176f7df2e56Smrg             * Call the DDX saver in case it wants to do something
3177f7df2e56Smrg             * at cycle time
3178f7df2e56Smrg             */
3179f7df2e56Smrg            else if (pScreen->screensaver.blanked == SCREEN_IS_BLANKED) {
3180f7df2e56Smrg                (*pScreen->SaveScreen) (pScreen, type);
3181f7df2e56Smrg            }
3182f7df2e56Smrg            break;
3183f7df2e56Smrg        case SCREEN_SAVER_ON:
3184f7df2e56Smrg            if (ScreenSaverBlanking != DontPreferBlanking) {
3185f7df2e56Smrg                if ((*pScreen->SaveScreen) (pScreen, what)) {
3186f7df2e56Smrg                    pScreen->screensaver.blanked = SCREEN_IS_BLANKED;
3187f7df2e56Smrg                    continue;
3188f7df2e56Smrg                }
3189f7df2e56Smrg                if ((ScreenSaverAllowExposures != DontAllowExposures) &&
3190f7df2e56Smrg                    TileScreenSaver(pScreen, SCREEN_IS_BLACK)) {
3191f7df2e56Smrg                    pScreen->screensaver.blanked = SCREEN_IS_BLACK;
3192f7df2e56Smrg                    continue;
3193f7df2e56Smrg                }
3194f7df2e56Smrg            }
3195f7df2e56Smrg            if ((ScreenSaverAllowExposures != DontAllowExposures) &&
3196f7df2e56Smrg                TileScreenSaver(pScreen, SCREEN_IS_TILED)) {
3197f7df2e56Smrg                pScreen->screensaver.blanked = SCREEN_IS_TILED;
3198f7df2e56Smrg            }
3199f7df2e56Smrg            else
3200f7df2e56Smrg                pScreen->screensaver.blanked = SCREEN_ISNT_SAVED;
3201f7df2e56Smrg            break;
3202f7df2e56Smrg        }
320305b261ecSmrg    }
320405b261ecSmrg    screenIsSaved = what;
32054202a189Smrg    if (mode == ScreenSaverReset) {
3206f7df2e56Smrg        if (on == SCREEN_SAVER_FORCER) {
3207f7df2e56Smrg            DeviceIntPtr dev;
3208f7df2e56Smrg            UpdateCurrentTimeIf();
3209f7df2e56Smrg            nt_list_for_each_entry(dev, inputInfo.devices, next)
3210f7df2e56Smrg                NoticeTime(dev, currentTime);
3211f7df2e56Smrg        }
3212f7df2e56Smrg        SetScreenSaverTimer();
32134202a189Smrg    }
3214637ac9abSmrg    return Success;
3215637ac9abSmrg}
3216637ac9abSmrg
32174202a189Smrgint
3218637ac9abSmrgSaveScreens(int on, int mode)
3219637ac9abSmrg{
3220637ac9abSmrg    return dixSaveScreens(serverClient, on, mode);
322105b261ecSmrg}
322205b261ecSmrg
322305b261ecSmrgstatic Bool
32244202a189SmrgTileScreenSaver(ScreenPtr pScreen, int kind)
322505b261ecSmrg{
322605b261ecSmrg    int j;
322705b261ecSmrg    int result;
322805b261ecSmrg    XID attributes[3];
322905b261ecSmrg    Mask mask;
3230f7df2e56Smrg    WindowPtr pWin;
323105b261ecSmrg    CursorMetricRec cm;
323205b261ecSmrg    unsigned char *srcbits, *mskbits;
323305b261ecSmrg    CursorPtr cursor;
3234f7df2e56Smrg    XID cursorID = 0;
3235f7df2e56Smrg    int attri;
323605b261ecSmrg
323705b261ecSmrg    mask = 0;
323805b261ecSmrg    attri = 0;
323905b261ecSmrg    switch (kind) {
324005b261ecSmrg    case SCREEN_IS_TILED:
3241f7df2e56Smrg        switch (pScreen->root->backgroundState) {
3242f7df2e56Smrg        case BackgroundPixel:
3243f7df2e56Smrg            attributes[attri++] = pScreen->root->background.pixel;
3244f7df2e56Smrg            mask |= CWBackPixel;
3245f7df2e56Smrg            break;
3246f7df2e56Smrg        case BackgroundPixmap:
3247f7df2e56Smrg            attributes[attri++] = None;
3248f7df2e56Smrg            mask |= CWBackPixmap;
3249f7df2e56Smrg            break;
3250f7df2e56Smrg        default:
3251f7df2e56Smrg            break;
3252f7df2e56Smrg        }
3253f7df2e56Smrg        break;
325405b261ecSmrg    case SCREEN_IS_BLACK:
3255f7df2e56Smrg        attributes[attri++] = pScreen->root->drawable.pScreen->blackPixel;
3256f7df2e56Smrg        mask |= CWBackPixel;
3257f7df2e56Smrg        break;
325805b261ecSmrg    }
325905b261ecSmrg    mask |= CWOverrideRedirect;
326005b261ecSmrg    attributes[attri++] = xTrue;
326105b261ecSmrg
326205b261ecSmrg    /*
326305b261ecSmrg     * create a blank cursor
326405b261ecSmrg     */
326505b261ecSmrg
3266f7df2e56Smrg    cm.width = 16;
3267f7df2e56Smrg    cm.height = 16;
3268f7df2e56Smrg    cm.xhot = 8;
3269f7df2e56Smrg    cm.yhot = 8;
3270f7df2e56Smrg    srcbits = malloc(BitmapBytePad(32) * 16);
3271f7df2e56Smrg    mskbits = malloc(BitmapBytePad(32) * 16);
3272f7df2e56Smrg    if (!srcbits || !mskbits) {
3273f7df2e56Smrg        free(srcbits);
3274f7df2e56Smrg        free(mskbits);
3275f7df2e56Smrg        cursor = 0;
327605b261ecSmrg    }
3277f7df2e56Smrg    else {
3278f7df2e56Smrg        for (j = 0; j < BitmapBytePad(32) * 16; j++)
3279f7df2e56Smrg            srcbits[j] = mskbits[j] = 0x0;
3280f7df2e56Smrg        result = AllocARGBCursor(srcbits, mskbits, NULL, &cm, 0, 0, 0, 0, 0, 0,
3281f7df2e56Smrg                                 &cursor, serverClient, (XID) 0);
3282f7df2e56Smrg        if (cursor) {
3283f7df2e56Smrg            cursorID = FakeClientID(0);
3284f7df2e56Smrg            if (AddResource(cursorID, RT_CURSOR, (void *) cursor)) {
3285f7df2e56Smrg                attributes[attri] = cursorID;
3286f7df2e56Smrg                mask |= CWCursor;
3287f7df2e56Smrg            }
3288f7df2e56Smrg            else
3289f7df2e56Smrg                cursor = 0;
3290f7df2e56Smrg        }
3291f7df2e56Smrg        else {
3292f7df2e56Smrg            free(srcbits);
3293f7df2e56Smrg            free(mskbits);
3294f7df2e56Smrg        }
329505b261ecSmrg    }
329605b261ecSmrg
32974202a189Smrg    pWin = pScreen->screensaver.pWindow =
3298f7df2e56Smrg        CreateWindow(pScreen->screensaver.wid,
3299f7df2e56Smrg                     pScreen->root,
3300f7df2e56Smrg                     -RANDOM_WIDTH, -RANDOM_WIDTH,
3301f7df2e56Smrg                     (unsigned short) pScreen->width + RANDOM_WIDTH,
3302f7df2e56Smrg                     (unsigned short) pScreen->height + RANDOM_WIDTH,
3303f7df2e56Smrg                     0, InputOutput, mask, attributes, 0, serverClient,
3304f7df2e56Smrg                     wVisual(pScreen->root), &result);
330505b261ecSmrg
330605b261ecSmrg    if (cursor)
3307f7df2e56Smrg        FreeResource(cursorID, RT_NONE);
330805b261ecSmrg
330905b261ecSmrg    if (!pWin)
3310f7df2e56Smrg        return FALSE;
331105b261ecSmrg
331205b261ecSmrg    if (!AddResource(pWin->drawable.id, RT_WINDOW,
3313f7df2e56Smrg                     (void *) pScreen->screensaver.pWindow))
3314f7df2e56Smrg        return FALSE;
331505b261ecSmrg
3316f7df2e56Smrg    if (mask & CWBackPixmap) {
3317f7df2e56Smrg        MakeRootTile(pWin);
3318f7df2e56Smrg        (*pWin->drawable.pScreen->ChangeWindowAttributes) (pWin, CWBackPixmap);
331905b261ecSmrg    }
332005b261ecSmrg    MapWindow(pWin, serverClient);
332105b261ecSmrg    return TRUE;
332205b261ecSmrg}
332305b261ecSmrg
332405b261ecSmrg/*
332505b261ecSmrg * FindWindowWithOptional
332605b261ecSmrg *
332705b261ecSmrg * search ancestors of the given window for an entry containing
332805b261ecSmrg * a WindowOpt structure.  Assumptions:	 some parent will
332905b261ecSmrg * contain the structure.
333005b261ecSmrg */
333105b261ecSmrg
33324202a189SmrgWindowPtr
3333f7df2e56SmrgFindWindowWithOptional(WindowPtr w)
333405b261ecSmrg{
333505b261ecSmrg    do
3336f7df2e56Smrg        w = w->parent;
333705b261ecSmrg    while (!w->optional);
333805b261ecSmrg    return w;
333905b261ecSmrg}
334005b261ecSmrg
334105b261ecSmrg/*
334205b261ecSmrg * CheckWindowOptionalNeed
334305b261ecSmrg *
334405b261ecSmrg * check each optional entry in the given window to see if
334505b261ecSmrg * the value is satisfied by the default rules.	 If so,
334605b261ecSmrg * release the optional record
334705b261ecSmrg */
334805b261ecSmrg
33494202a189Smrgvoid
3350f7df2e56SmrgCheckWindowOptionalNeed(WindowPtr w)
335105b261ecSmrg{
335205b261ecSmrg    WindowOptPtr optional;
335305b261ecSmrg    WindowOptPtr parentOptional;
335405b261ecSmrg
33554202a189Smrg    if (!w->parent || !w->optional)
3356f7df2e56Smrg        return;
335705b261ecSmrg    optional = w->optional;
335805b261ecSmrg    if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate])
3359f7df2e56Smrg        return;
336005b261ecSmrg    if (optional->otherEventMasks != 0)
3361f7df2e56Smrg        return;
336205b261ecSmrg    if (optional->otherClients != NULL)
3363f7df2e56Smrg        return;
336405b261ecSmrg    if (optional->passiveGrabs != NULL)
3365f7df2e56Smrg        return;
336605b261ecSmrg    if (optional->userProps != NULL)
3367f7df2e56Smrg        return;
3368f7df2e56Smrg    if (optional->backingBitPlanes != (CARD32)~0L)
3369f7df2e56Smrg        return;
337005b261ecSmrg    if (optional->backingPixel != 0)
3371f7df2e56Smrg        return;
337205b261ecSmrg    if (optional->boundingShape != NULL)
3373f7df2e56Smrg        return;
337405b261ecSmrg    if (optional->clipShape != NULL)
3375f7df2e56Smrg        return;
337605b261ecSmrg    if (optional->inputShape != NULL)
3377f7df2e56Smrg        return;
337805b261ecSmrg    if (optional->inputMasks != NULL)
3379f7df2e56Smrg        return;
3380f7df2e56Smrg    if (optional->deviceCursors != NULL) {
3381637ac9abSmrg        DevCursNodePtr pNode = optional->deviceCursors;
3382f7df2e56Smrg
3383f7df2e56Smrg        while (pNode) {
3384637ac9abSmrg            if (pNode->cursor != None)
3385637ac9abSmrg                return;
3386637ac9abSmrg            pNode = pNode->next;
3387637ac9abSmrg        }
3388637ac9abSmrg    }
3389637ac9abSmrg
339005b261ecSmrg    parentOptional = FindWindowWithOptional(w)->optional;
339105b261ecSmrg    if (optional->visual != parentOptional->visual)
3392f7df2e56Smrg        return;
339305b261ecSmrg    if (optional->cursor != None &&
3394f7df2e56Smrg        (optional->cursor != parentOptional->cursor || w->parent->cursorIsNone))
3395f7df2e56Smrg        return;
339605b261ecSmrg    if (optional->colormap != parentOptional->colormap)
3397f7df2e56Smrg        return;
3398f7df2e56Smrg    DisposeWindowOptional(w);
339905b261ecSmrg}
340005b261ecSmrg
340105b261ecSmrg/*
340205b261ecSmrg * MakeWindowOptional
340305b261ecSmrg *
340405b261ecSmrg * create an optional record and initialize it with the default
340505b261ecSmrg * values.
340605b261ecSmrg */
340705b261ecSmrg
34084202a189SmrgBool
3409f7df2e56SmrgMakeWindowOptional(WindowPtr pWin)
341005b261ecSmrg{
341105b261ecSmrg    WindowOptPtr optional;
341205b261ecSmrg    WindowOptPtr parentOptional;
341305b261ecSmrg
341405b261ecSmrg    if (pWin->optional)
3415f7df2e56Smrg        return TRUE;
3416f7df2e56Smrg    optional = malloc(sizeof(WindowOptRec));
341705b261ecSmrg    if (!optional)
3418f7df2e56Smrg        return FALSE;
341905b261ecSmrg    optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate];
342005b261ecSmrg    optional->otherEventMasks = 0;
342105b261ecSmrg    optional->otherClients = NULL;
342205b261ecSmrg    optional->passiveGrabs = NULL;
342305b261ecSmrg    optional->userProps = NULL;
342405b261ecSmrg    optional->backingBitPlanes = ~0L;
342505b261ecSmrg    optional->backingPixel = 0;
342605b261ecSmrg    optional->boundingShape = NULL;
342705b261ecSmrg    optional->clipShape = NULL;
342805b261ecSmrg    optional->inputShape = NULL;
342905b261ecSmrg    optional->inputMasks = NULL;
3430637ac9abSmrg    optional->deviceCursors = NULL;
3431637ac9abSmrg
343205b261ecSmrg    parentOptional = FindWindowWithOptional(pWin)->optional;
343305b261ecSmrg    optional->visual = parentOptional->visual;
3434f7df2e56Smrg    if (!pWin->cursorIsNone) {
3435f7df2e56Smrg        optional->cursor = RefCursor(parentOptional->cursor);
343605b261ecSmrg    }
3437f7df2e56Smrg    else {
3438f7df2e56Smrg        optional->cursor = None;
343905b261ecSmrg    }
344005b261ecSmrg    optional->colormap = parentOptional->colormap;
344105b261ecSmrg    pWin->optional = optional;
344205b261ecSmrg    return TRUE;
344305b261ecSmrg}
344405b261ecSmrg
3445637ac9abSmrg/*
3446637ac9abSmrg * Changes the cursor struct for the given device and the given window.
3447637ac9abSmrg * A cursor that does not have a device cursor set will use whatever the
3448637ac9abSmrg * standard cursor is for the window. If all devices have a cursor set,
3449637ac9abSmrg * changing the window cursor (e.g. using XDefineCursor()) will not have any
3450637ac9abSmrg * visible effect. Only when one of the device cursors is set to None again,
3451637ac9abSmrg * this device's cursor will display the changed standard cursor.
3452f7df2e56Smrg *
3453637ac9abSmrg * CursorIsNone of the window struct is NOT modified if you set a device
3454f7df2e56Smrg * cursor.
3455637ac9abSmrg *
3456637ac9abSmrg * Assumption: If there is a node for a device in the list, the device has a
3457637ac9abSmrg * cursor. If the cursor is set to None, it is inherited by the parent.
3458637ac9abSmrg */
34594202a189Smrgint
3460f7df2e56SmrgChangeWindowDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev, CursorPtr pCursor)
3461637ac9abSmrg{
3462637ac9abSmrg    DevCursNodePtr pNode, pPrev;
3463637ac9abSmrg    CursorPtr pOldCursor = NULL;
3464637ac9abSmrg    ScreenPtr pScreen;
3465637ac9abSmrg    WindowPtr pChild;
3466637ac9abSmrg
3467637ac9abSmrg    if (!pWin->optional && !MakeWindowOptional(pWin))
3468637ac9abSmrg        return BadAlloc;
3469637ac9abSmrg
3470637ac9abSmrg    /* 1) Check if window has device cursor set
3471637ac9abSmrg     *  Yes: 1.1) swap cursor with given cursor if parent does not have same
3472637ac9abSmrg     *            cursor, free old cursor
3473637ac9abSmrg     *       1.2) free old cursor, use parent cursor
3474637ac9abSmrg     *  No: 1.1) add node to beginning of list.
3475637ac9abSmrg     *      1.2) add cursor to node if parent does not have same cursor
3476637ac9abSmrg     *      1.3) use parent cursor if parent does not have same cursor
3477637ac9abSmrg     *  2) Patch up children if child has a devcursor
3478637ac9abSmrg     *  2.1) if child has cursor None, it inherited from parent, set to old
3479637ac9abSmrg     *  cursor
3480637ac9abSmrg     *  2.2) if child has same cursor as new cursor, remove and set to None
3481637ac9abSmrg     */
3482637ac9abSmrg
3483637ac9abSmrg    pScreen = pWin->drawable.pScreen;
3484637ac9abSmrg
3485f7df2e56Smrg    if (WindowSeekDeviceCursor(pWin, pDev, &pNode, &pPrev)) {
3486637ac9abSmrg        /* has device cursor */
3487637ac9abSmrg
3488637ac9abSmrg        if (pNode->cursor == pCursor)
3489637ac9abSmrg            return Success;
3490637ac9abSmrg
3491637ac9abSmrg        pOldCursor = pNode->cursor;
3492637ac9abSmrg
3493f7df2e56Smrg        if (!pCursor) {         /* remove from list */
3494f7df2e56Smrg            if (pPrev)
3495f7df2e56Smrg                pPrev->next = pNode->next;
3496f7df2e56Smrg            else
3497f7df2e56Smrg                /* first item in list */
3498f7df2e56Smrg                pWin->optional->deviceCursors = pNode->next;
3499637ac9abSmrg
35004202a189Smrg            free(pNode);
35014202a189Smrg            goto out;
3502637ac9abSmrg        }
3503637ac9abSmrg
3504f7df2e56Smrg    }
3505f7df2e56Smrg    else {
3506637ac9abSmrg        /* no device cursor yet */
3507637ac9abSmrg        DevCursNodePtr pNewNode;
3508637ac9abSmrg
3509637ac9abSmrg        if (!pCursor)
3510637ac9abSmrg            return Success;
3511637ac9abSmrg
35124202a189Smrg        pNewNode = malloc(sizeof(DevCursNodeRec));
3513637ac9abSmrg        pNewNode->dev = pDev;
3514637ac9abSmrg        pNewNode->next = pWin->optional->deviceCursors;
3515637ac9abSmrg        pWin->optional->deviceCursors = pNewNode;
3516637ac9abSmrg        pNode = pNewNode;
3517637ac9abSmrg
3518637ac9abSmrg    }
3519637ac9abSmrg
3520637ac9abSmrg    if (pCursor && WindowParentHasDeviceCursor(pWin, pDev, pCursor))
3521637ac9abSmrg        pNode->cursor = None;
3522f7df2e56Smrg    else {
3523f7df2e56Smrg        pNode->cursor = RefCursor(pCursor);
3524637ac9abSmrg    }
3525637ac9abSmrg
3526637ac9abSmrg    pNode = pPrev = NULL;
3527637ac9abSmrg    /* fix up children */
3528f7df2e56Smrg    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
3529f7df2e56Smrg        if (WindowSeekDeviceCursor(pChild, pDev, &pNode, &pPrev)) {
3530f7df2e56Smrg            if (pNode->cursor == None) {        /* inherited from parent */
3531f7df2e56Smrg                pNode->cursor = RefCursor(pOldCursor);
3532f7df2e56Smrg            }
3533f7df2e56Smrg            else if (pNode->cursor == pCursor) {
3534637ac9abSmrg                pNode->cursor = None;
3535f7df2e56Smrg                FreeCursor(pCursor, (Cursor) 0);        /* fix up refcnt */
3536637ac9abSmrg            }
3537637ac9abSmrg        }
3538637ac9abSmrg    }
3539637ac9abSmrg
3540f7df2e56Smrg out:
3541f7df2e56Smrg    CursorVisible = TRUE;
3542f7df2e56Smrg
3543637ac9abSmrg    if (pWin->realized)
3544637ac9abSmrg        WindowHasNewCursor(pWin);
3545637ac9abSmrg
3546637ac9abSmrg    if (pOldCursor)
3547f7df2e56Smrg        FreeCursor(pOldCursor, (Cursor) 0);
3548637ac9abSmrg
3549f7df2e56Smrg    /* FIXME: We SHOULD check for an error value here XXX
3550637ac9abSmrg       (comment taken from ChangeWindowAttributes) */
3551f7df2e56Smrg    (*pScreen->ChangeWindowAttributes) (pWin, CWCursor);
3552637ac9abSmrg
3553637ac9abSmrg    return Success;
3554637ac9abSmrg}
3555637ac9abSmrg
3556637ac9abSmrg/* Get device cursor for given device or None if none is set */
35574202a189SmrgCursorPtr
3558637ac9abSmrgWindowGetDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev)
3559637ac9abSmrg{
3560637ac9abSmrg    DevCursorList pList;
3561637ac9abSmrg
3562637ac9abSmrg    if (!pWin->optional || !pWin->optional->deviceCursors)
3563637ac9abSmrg        return NULL;
3564637ac9abSmrg
3565637ac9abSmrg    pList = pWin->optional->deviceCursors;
3566637ac9abSmrg
3567f7df2e56Smrg    while (pList) {
3568f7df2e56Smrg        if (pList->dev == pDev) {
3569f7df2e56Smrg            if (pList->cursor == None)  /* inherited from parent */
3570637ac9abSmrg                return WindowGetDeviceCursor(pWin->parent, pDev);
3571637ac9abSmrg            else
3572637ac9abSmrg                return pList->cursor;
3573637ac9abSmrg        }
3574637ac9abSmrg        pList = pList->next;
3575637ac9abSmrg    }
3576637ac9abSmrg    return NULL;
3577637ac9abSmrg}
3578637ac9abSmrg
3579637ac9abSmrg/* Searches for a DevCursorNode for the given window and device. If one is
3580637ac9abSmrg * found, return True and set pNode and pPrev to the node and to the node
3581637ac9abSmrg * before the node respectively. Otherwise return False.
3582637ac9abSmrg * If the device is the first in list, pPrev is set to NULL.
3583637ac9abSmrg */
3584f7df2e56Smrgstatic Bool
3585f7df2e56SmrgWindowSeekDeviceCursor(WindowPtr pWin,
3586f7df2e56Smrg                       DeviceIntPtr pDev,
3587f7df2e56Smrg                       DevCursNodePtr * pNode, DevCursNodePtr * pPrev)
3588637ac9abSmrg{
3589637ac9abSmrg    DevCursorList pList;
3590637ac9abSmrg
3591637ac9abSmrg    if (!pWin->optional)
3592637ac9abSmrg        return FALSE;
3593637ac9abSmrg
3594637ac9abSmrg    pList = pWin->optional->deviceCursors;
3595637ac9abSmrg
3596f7df2e56Smrg    if (pList && pList->dev == pDev) {
3597637ac9abSmrg        *pNode = pList;
3598637ac9abSmrg        *pPrev = NULL;
3599637ac9abSmrg        return TRUE;
3600637ac9abSmrg    }
3601637ac9abSmrg
3602f7df2e56Smrg    while (pList) {
3603f7df2e56Smrg        if (pList->next) {
3604f7df2e56Smrg            if (pList->next->dev == pDev) {
3605637ac9abSmrg                *pNode = pList->next;
3606637ac9abSmrg                *pPrev = pList;
3607637ac9abSmrg                return TRUE;
3608637ac9abSmrg            }
3609637ac9abSmrg        }
3610637ac9abSmrg        pList = pList->next;
3611637ac9abSmrg    }
3612637ac9abSmrg    return FALSE;
3613637ac9abSmrg}
3614637ac9abSmrg
3615637ac9abSmrg/* Return True if a parent has the same device cursor set or False if
3616f7df2e56Smrg * otherwise
3617f7df2e56Smrg */
3618f7df2e56Smrgstatic Bool
3619f7df2e56SmrgWindowParentHasDeviceCursor(WindowPtr pWin,
3620f7df2e56Smrg                            DeviceIntPtr pDev, CursorPtr pCursor)
3621637ac9abSmrg{
3622637ac9abSmrg    WindowPtr pParent;
3623637ac9abSmrg    DevCursNodePtr pParentNode, pParentPrev;
3624637ac9abSmrg
3625637ac9abSmrg    pParent = pWin->parent;
3626f7df2e56Smrg    while (pParent) {
3627f7df2e56Smrg        if (WindowSeekDeviceCursor(pParent, pDev, &pParentNode, &pParentPrev)) {
3628637ac9abSmrg            /* if there is a node in the list, the win has a dev cursor */
3629f7df2e56Smrg            if (!pParentNode->cursor)   /* inherited. */
36301b684552Smrg                pParent = pParent->parent;
3631f7df2e56Smrg            else if (pParentNode->cursor == pCursor)    /* inherit */
3632637ac9abSmrg                return TRUE;
3633f7df2e56Smrg            else                /* different cursor */
3634637ac9abSmrg                return FALSE;
3635f7df2e56Smrg        }
3636f7df2e56Smrg        else
3637637ac9abSmrg            /* parent does not have a device cursor for our device */
3638637ac9abSmrg            return FALSE;
3639637ac9abSmrg    }
3640637ac9abSmrg    return FALSE;
3641637ac9abSmrg}
3642f7df2e56Smrg
3643f7df2e56Smrg/*
3644f7df2e56Smrg * SetRootClip --
3645f7df2e56Smrg *	Enable or disable rendering to the screen by
3646f7df2e56Smrg *	setting the root clip list and revalidating
3647f7df2e56Smrg *	all of the windows
3648f7df2e56Smrg */
3649f7df2e56Smrgvoid
3650f7df2e56SmrgSetRootClip(ScreenPtr pScreen, int enable)
3651f7df2e56Smrg{
3652f7df2e56Smrg    WindowPtr pWin = pScreen->root;
3653f7df2e56Smrg    WindowPtr pChild;
3654f7df2e56Smrg    Bool WasViewable;
3655f7df2e56Smrg    Bool anyMarked = FALSE;
3656f7df2e56Smrg    WindowPtr pLayerWin;
3657f7df2e56Smrg    BoxRec box;
3658f7df2e56Smrg    enum RootClipMode mode = enable;
3659f7df2e56Smrg
3660f7df2e56Smrg    if (!pWin)
3661f7df2e56Smrg        return;
3662f7df2e56Smrg    WasViewable = (Bool) (pWin->viewable);
3663f7df2e56Smrg    if (WasViewable) {
3664f7df2e56Smrg        for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
3665f7df2e56Smrg            (void) (*pScreen->MarkOverlappedWindows) (pChild,
3666f7df2e56Smrg                                                      pChild, &pLayerWin);
3667f7df2e56Smrg        }
3668f7df2e56Smrg        (*pScreen->MarkWindow) (pWin);
3669f7df2e56Smrg        anyMarked = TRUE;
3670f7df2e56Smrg        if (pWin->valdata) {
3671f7df2e56Smrg            if (HasBorder(pWin)) {
3672f7df2e56Smrg                RegionPtr borderVisible;
3673f7df2e56Smrg
3674f7df2e56Smrg                borderVisible = RegionCreate(NullBox, 1);
3675f7df2e56Smrg                RegionSubtract(borderVisible,
3676f7df2e56Smrg                               &pWin->borderClip, &pWin->winSize);
3677f7df2e56Smrg                pWin->valdata->before.borderVisible = borderVisible;
3678f7df2e56Smrg            }
3679f7df2e56Smrg            pWin->valdata->before.resized = TRUE;
3680f7df2e56Smrg        }
3681f7df2e56Smrg    }
3682f7df2e56Smrg
3683f7df2e56Smrg    if (mode != ROOT_CLIP_NONE) {
3684f7df2e56Smrg        pWin->drawable.width = pScreen->width;
3685f7df2e56Smrg        pWin->drawable.height = pScreen->height;
3686f7df2e56Smrg
3687f7df2e56Smrg        box.x1 = 0;
3688f7df2e56Smrg        box.y1 = 0;
3689f7df2e56Smrg        box.x2 = pScreen->width;
3690f7df2e56Smrg        box.y2 = pScreen->height;
3691f7df2e56Smrg
3692f7df2e56Smrg        RegionInit(&pWin->winSize, &box, 1);
3693f7df2e56Smrg        RegionInit(&pWin->borderSize, &box, 1);
3694f7df2e56Smrg
3695f7df2e56Smrg        /*
3696f7df2e56Smrg         * Use REGION_BREAK to avoid optimizations in ValidateTree
3697f7df2e56Smrg         * that assume the root borderClip can't change well, normally
3698f7df2e56Smrg         * it doesn't...)
3699f7df2e56Smrg         */
3700f7df2e56Smrg        RegionBreak(&pWin->clipList);
3701f7df2e56Smrg
3702f7df2e56Smrg	/* For INPUT_ONLY, empty the borderClip so no rendering will ever
3703f7df2e56Smrg	 * be attempted to the screen pixmap (only redirected windows),
3704f7df2e56Smrg	 * but we keep borderSize as full regardless. */
3705f7df2e56Smrg        if (WasViewable && mode == ROOT_CLIP_FULL)
3706f7df2e56Smrg            RegionReset(&pWin->borderClip, &box);
3707f7df2e56Smrg        else
3708f7df2e56Smrg            RegionEmpty(&pWin->borderClip);
3709f7df2e56Smrg    }
3710f7df2e56Smrg    else {
3711f7df2e56Smrg        RegionEmpty(&pWin->borderClip);
3712f7df2e56Smrg        RegionBreak(&pWin->clipList);
3713f7df2e56Smrg    }
3714f7df2e56Smrg
3715f7df2e56Smrg    ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
3716f7df2e56Smrg
3717f7df2e56Smrg    if (WasViewable) {
3718f7df2e56Smrg        if (pWin->firstChild) {
3719f7df2e56Smrg            anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin->firstChild,
3720f7df2e56Smrg                                                            pWin->firstChild,
3721f7df2e56Smrg                                                            NULL);
3722f7df2e56Smrg        }
3723f7df2e56Smrg        else {
3724f7df2e56Smrg            (*pScreen->MarkWindow) (pWin);
3725f7df2e56Smrg            anyMarked = TRUE;
3726f7df2e56Smrg        }
3727f7df2e56Smrg
3728f7df2e56Smrg        if (anyMarked) {
3729f7df2e56Smrg            (*pScreen->ValidateTree) (pWin, NullWindow, VTOther);
3730f7df2e56Smrg            (*pScreen->HandleExposures) (pWin);
3731f7df2e56Smrg            if (pScreen->PostValidateTree)
3732f7df2e56Smrg                (*pScreen->PostValidateTree) (pWin, NullWindow, VTOther);
3733f7df2e56Smrg        }
3734f7df2e56Smrg    }
3735f7df2e56Smrg    if (pWin->realized)
3736f7df2e56Smrg        WindowsRestructured();
3737f7df2e56Smrg    FlushAllOutput();
3738f7df2e56Smrg}
3739f7df2e56Smrg
3740f7df2e56SmrgVisualPtr
3741f7df2e56SmrgWindowGetVisual(WindowPtr pWin)
3742f7df2e56Smrg{
3743f7df2e56Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
3744f7df2e56Smrg    VisualID vid = wVisual(pWin);
3745f7df2e56Smrg    int i;
3746f7df2e56Smrg
3747f7df2e56Smrg    for (i = 0; i < pScreen->numVisuals; i++)
3748f7df2e56Smrg        if (pScreen->visuals[i].vid == vid)
3749f7df2e56Smrg            return &pScreen->visuals[i];
3750f7df2e56Smrg    return 0;
3751f7df2e56Smrg}
3752