window.c revision 5a112b11
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 to force no backing store */
472f7df2e56SmrgBool disableBackingStore = FALSE;
473f7df2e56SmrgBool enableBackingStore = FALSE;
47405b261ecSmrg
47505b261ecSmrgstatic void
47605b261ecSmrgSetWindowToDefaults(WindowPtr pWin)
47705b261ecSmrg{
47805b261ecSmrg    pWin->prevSib = NullWindow;
47905b261ecSmrg    pWin->firstChild = NullWindow;
48005b261ecSmrg    pWin->lastChild = NullWindow;
48105b261ecSmrg
482f7df2e56Smrg    pWin->valdata = NULL;
483f7df2e56Smrg    pWin->optional = NULL;
48405b261ecSmrg    pWin->cursorIsNone = TRUE;
48505b261ecSmrg
48605b261ecSmrg    pWin->backingStore = NotUseful;
48705b261ecSmrg
488f7df2e56Smrg    pWin->mapped = FALSE;       /* off */
489f7df2e56Smrg    pWin->realized = FALSE;     /* off */
49005b261ecSmrg    pWin->viewable = FALSE;
49105b261ecSmrg    pWin->visibility = VisibilityNotViewable;
49205b261ecSmrg    pWin->overrideRedirect = FALSE;
49305b261ecSmrg    pWin->saveUnder = FALSE;
49405b261ecSmrg
49505b261ecSmrg    pWin->bitGravity = ForgetGravity;
49605b261ecSmrg    pWin->winGravity = NorthWestGravity;
49705b261ecSmrg
49805b261ecSmrg    pWin->eventMask = 0;
49905b261ecSmrg    pWin->deliverableEvents = 0;
50005b261ecSmrg    pWin->dontPropagate = 0;
50105b261ecSmrg    pWin->redirectDraw = RedirectDrawNone;
502637ac9abSmrg    pWin->forcedBG = FALSE;
503f7df2e56Smrg    pWin->unhittable = FALSE;
50465b04b38Smrg
50565b04b38Smrg#ifdef COMPOSITE
50665b04b38Smrg    pWin->damagedDescendants = FALSE;
50765b04b38Smrg#endif
50805b261ecSmrg}
50905b261ecSmrg
51005b261ecSmrgstatic void
51105b261ecSmrgMakeRootTile(WindowPtr pWin)
51205b261ecSmrg{
51305b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
51405b261ecSmrg    GCPtr pGC;
51505b261ecSmrg    unsigned char back[128];
51605b261ecSmrg    int len = BitmapBytePad(sizeof(long));
51705b261ecSmrg    unsigned char *from, *to;
51805b261ecSmrg    int i, j;
51905b261ecSmrg
520f7df2e56Smrg    pWin->background.pixmap = (*pScreen->CreatePixmap) (pScreen, 4, 4,
521f7df2e56Smrg                                                        pScreen->rootDepth, 0);
52205b261ecSmrg
52305b261ecSmrg    pWin->backgroundState = BackgroundPixmap;
52405b261ecSmrg    pGC = GetScratchGC(pScreen->rootDepth, pScreen);
52505b261ecSmrg    if (!pWin->background.pixmap || !pGC)
526f7df2e56Smrg        FatalError("could not create root tile");
52705b261ecSmrg
52805b261ecSmrg    {
529f7df2e56Smrg        ChangeGCVal attributes[2];
53005b261ecSmrg
531f7df2e56Smrg        attributes[0].val = pScreen->whitePixel;
532f7df2e56Smrg        attributes[1].val = pScreen->blackPixel;
53305b261ecSmrg
534f7df2e56Smrg        (void) ChangeGC(NullClient, pGC, GCForeground | GCBackground,
535f7df2e56Smrg                        attributes);
53605b261ecSmrg    }
53705b261ecSmrg
538f7df2e56Smrg    ValidateGC((DrawablePtr) pWin->background.pixmap, pGC);
53905b261ecSmrg
540f7df2e56Smrg    from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb;
541f7df2e56Smrg    to = back;
54205b261ecSmrg
543f7df2e56Smrg    for (i = 4; i > 0; i--, from++)
544f7df2e56Smrg        for (j = len; j > 0; j--)
545f7df2e56Smrg            *to++ = *from;
54605b261ecSmrg
547f7df2e56Smrg    (*pGC->ops->PutImage) ((DrawablePtr) pWin->background.pixmap, pGC, 1,
548f7df2e56Smrg                           0, 0, len, 4, 0, XYBitmap, (char *) back);
54905b261ecSmrg
550f7df2e56Smrg    FreeScratchGC(pGC);
55105b261ecSmrg
55205b261ecSmrg}
55305b261ecSmrg
55405b261ecSmrg/*****
55505b261ecSmrg * CreateRootWindow
55605b261ecSmrg *    Makes a window at initialization time for specified screen
55705b261ecSmrg *****/
55805b261ecSmrg
55905b261ecSmrgBool
56005b261ecSmrgCreateRootWindow(ScreenPtr pScreen)
56105b261ecSmrg{
562f7df2e56Smrg    WindowPtr pWin;
563f7df2e56Smrg    BoxRec box;
56405b261ecSmrg    PixmapFormatRec *format;
56505b261ecSmrg
566f7df2e56Smrg    pWin = dixAllocateScreenObjectWithPrivates(pScreen, WindowRec, PRIVATE_WINDOW);
56705b261ecSmrg    if (!pWin)
568f7df2e56Smrg        return FALSE;
56905b261ecSmrg
5704202a189Smrg    pScreen->screensaver.pWindow = NULL;
5714202a189Smrg    pScreen->screensaver.wid = FakeClientID(0);
5724202a189Smrg    pScreen->screensaver.ExternalScreenSaver = NULL;
57305b261ecSmrg    screenIsSaved = SCREEN_SAVER_OFF;
57405b261ecSmrg
5754202a189Smrg    pScreen->root = pWin;
57605b261ecSmrg
57705b261ecSmrg    pWin->drawable.pScreen = pScreen;
57805b261ecSmrg    pWin->drawable.type = DRAWABLE_WINDOW;
57905b261ecSmrg
58005b261ecSmrg    pWin->drawable.depth = pScreen->rootDepth;
58105b261ecSmrg    for (format = screenInfo.formats;
582f7df2e56Smrg         format->depth != pScreen->rootDepth; format++);
58305b261ecSmrg    pWin->drawable.bitsPerPixel = format->bitsPerPixel;
58405b261ecSmrg
58505b261ecSmrg    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
58605b261ecSmrg
58705b261ecSmrg    pWin->parent = NullWindow;
58805b261ecSmrg    SetWindowToDefaults(pWin);
58905b261ecSmrg
590f7df2e56Smrg    pWin->optional = malloc(sizeof(WindowOptRec));
59105b261ecSmrg    if (!pWin->optional)
59205b261ecSmrg        return FALSE;
59305b261ecSmrg
59405b261ecSmrg    pWin->optional->dontPropagateMask = 0;
59505b261ecSmrg    pWin->optional->otherEventMasks = 0;
59605b261ecSmrg    pWin->optional->otherClients = NULL;
59705b261ecSmrg    pWin->optional->passiveGrabs = NULL;
59805b261ecSmrg    pWin->optional->userProps = NULL;
59905b261ecSmrg    pWin->optional->backingBitPlanes = ~0L;
60005b261ecSmrg    pWin->optional->backingPixel = 0;
60105b261ecSmrg    pWin->optional->boundingShape = NULL;
60205b261ecSmrg    pWin->optional->clipShape = NULL;
60305b261ecSmrg    pWin->optional->inputShape = NULL;
60405b261ecSmrg    pWin->optional->inputMasks = NULL;
605637ac9abSmrg    pWin->optional->deviceCursors = NULL;
60605b261ecSmrg    pWin->optional->colormap = pScreen->defColormap;
60705b261ecSmrg    pWin->optional->visual = pScreen->rootVisual;
60805b261ecSmrg
60905b261ecSmrg    pWin->nextSib = NullWindow;
61005b261ecSmrg
61105b261ecSmrg    pWin->drawable.id = FakeClientID(0);
61205b261ecSmrg
61305b261ecSmrg    pWin->origin.x = pWin->origin.y = 0;
61405b261ecSmrg    pWin->drawable.height = pScreen->height;
61505b261ecSmrg    pWin->drawable.width = pScreen->width;
61605b261ecSmrg    pWin->drawable.x = pWin->drawable.y = 0;
61705b261ecSmrg
61805b261ecSmrg    box.x1 = 0;
61905b261ecSmrg    box.y1 = 0;
62005b261ecSmrg    box.x2 = pScreen->width;
62105b261ecSmrg    box.y2 = pScreen->height;
6224202a189Smrg    RegionInit(&pWin->clipList, &box, 1);
6234202a189Smrg    RegionInit(&pWin->winSize, &box, 1);
6244202a189Smrg    RegionInit(&pWin->borderSize, &box, 1);
6254202a189Smrg    RegionInit(&pWin->borderClip, &box, 1);
62605b261ecSmrg
62705b261ecSmrg    pWin->drawable.class = InputOutput;
62805b261ecSmrg    pWin->optional->visual = pScreen->rootVisual;
62905b261ecSmrg
63005b261ecSmrg    pWin->backgroundState = BackgroundPixel;
63105b261ecSmrg    pWin->background.pixel = pScreen->whitePixel;
63205b261ecSmrg
63305b261ecSmrg    pWin->borderIsPixel = TRUE;
63405b261ecSmrg    pWin->border.pixel = pScreen->blackPixel;
63505b261ecSmrg    pWin->borderWidth = 0;
63605b261ecSmrg
637637ac9abSmrg    /*  security creation/labeling check
638637ac9abSmrg     */
639637ac9abSmrg    if (XaceHook(XACE_RESOURCE_ACCESS, serverClient, pWin->drawable.id,
640f7df2e56Smrg                 RT_WINDOW, pWin, RT_NONE, NULL, DixCreateAccess))
641f7df2e56Smrg        return FALSE;
642637ac9abSmrg
643f7df2e56Smrg    if (!AddResource(pWin->drawable.id, RT_WINDOW, (void *) pWin))
644f7df2e56Smrg        return FALSE;
64505b261ecSmrg
64605b261ecSmrg    if (disableBackingStore)
647f7df2e56Smrg        pScreen->backingStoreSupport = NotUseful;
64805b261ecSmrg    if (enableBackingStore)
649f7df2e56Smrg        pScreen->backingStoreSupport = WhenMapped;
650f7df2e56Smrg#ifdef COMPOSITE
651f7df2e56Smrg    if (noCompositeExtension)
652f7df2e56Smrg        pScreen->backingStoreSupport = NotUseful;
653f7df2e56Smrg#endif
65405b261ecSmrg
655637ac9abSmrg    pScreen->saveUnderSupport = NotUseful;
65605b261ecSmrg
65705b261ecSmrg    return TRUE;
65805b261ecSmrg}
65905b261ecSmrg
66005b261ecSmrgvoid
66105b261ecSmrgInitRootWindow(WindowPtr pWin)
66205b261ecSmrg{
66305b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
66405b261ecSmrg    int backFlag = CWBorderPixel | CWCursor | CWBackingStore;
66505b261ecSmrg
666f7df2e56Smrg    if (!(*pScreen->CreateWindow) (pWin))
667f7df2e56Smrg        return;                 /* XXX */
668f7df2e56Smrg    (*pScreen->PositionWindow) (pWin, 0, 0);
66905b261ecSmrg
67005b261ecSmrg    pWin->cursorIsNone = FALSE;
671f7df2e56Smrg    pWin->optional->cursor = RefCursor(rootCursor);
672637ac9abSmrg
673637ac9abSmrg    if (party_like_its_1989) {
67405b261ecSmrg        MakeRootTile(pWin);
67505b261ecSmrg        backFlag |= CWBackPixmap;
676f7df2e56Smrg    }
677f7df2e56Smrg    else if (pScreen->canDoBGNoneRoot && bgNoneRoot) {
67865b04b38Smrg        pWin->backgroundState = XaceBackgroundNoneState(pWin);
67965b04b38Smrg        pWin->background.pixel = pScreen->whitePixel;
68065b04b38Smrg        backFlag |= CWBackPixmap;
681f7df2e56Smrg    }
682f7df2e56Smrg    else {
68365b04b38Smrg        pWin->backgroundState = BackgroundPixel;
684f7df2e56Smrg        if (whiteRoot)
68505b261ecSmrg            pWin->background.pixel = pScreen->whitePixel;
686637ac9abSmrg        else
687637ac9abSmrg            pWin->background.pixel = pScreen->blackPixel;
68805b261ecSmrg        backFlag |= CWBackPixel;
689f7df2e56Smrg    }
69005b261ecSmrg
6915a112b11Smrg    pWin->backingStore = NotUseful;
69205b261ecSmrg    /* We SHOULD check for an error value here XXX */
693f7df2e56Smrg    (*pScreen->ChangeWindowAttributes) (pWin, backFlag);
69405b261ecSmrg
69505b261ecSmrg    MapWindow(pWin, serverClient);
69605b261ecSmrg}
69705b261ecSmrg
69805b261ecSmrg/* Set the region to the intersection of the rectangle and the
69905b261ecSmrg * window's winSize.  The window is typically the parent of the
70005b261ecSmrg * window from which the region came.
70105b261ecSmrg */
70205b261ecSmrg
70305b261ecSmrgstatic void
704f7df2e56SmrgClippedRegionFromBox(WindowPtr pWin, RegionPtr Rgn, int x, int y, int w, int h)
70505b261ecSmrg{
7064202a189Smrg    BoxRec box = *RegionExtents(&pWin->winSize);
70705b261ecSmrg
70805b261ecSmrg    /* we do these calculations to avoid overflows */
70905b261ecSmrg    if (x > box.x1)
710f7df2e56Smrg        box.x1 = x;
71105b261ecSmrg    if (y > box.y1)
712f7df2e56Smrg        box.y1 = y;
71305b261ecSmrg    x += w;
71405b261ecSmrg    if (x < box.x2)
715f7df2e56Smrg        box.x2 = x;
71605b261ecSmrg    y += h;
71705b261ecSmrg    if (y < box.y2)
718f7df2e56Smrg        box.y2 = y;
71905b261ecSmrg    if (box.x1 > box.x2)
720f7df2e56Smrg        box.x2 = box.x1;
72105b261ecSmrg    if (box.y1 > box.y2)
722f7df2e56Smrg        box.y2 = box.y1;
7234202a189Smrg    RegionReset(Rgn, &box);
7244202a189Smrg    RegionIntersect(Rgn, Rgn, &pWin->winSize);
72505b261ecSmrg}
72605b261ecSmrg
72705b261ecSmrgstatic RealChildHeadProc realChildHeadProc = NULL;
72805b261ecSmrg
72905b261ecSmrgvoid
730f7df2e56SmrgRegisterRealChildHeadProc(RealChildHeadProc proc)
73105b261ecSmrg{
73205b261ecSmrg    realChildHeadProc = proc;
73305b261ecSmrg}
73405b261ecSmrg
73505b261ecSmrgWindowPtr
73605b261ecSmrgRealChildHead(WindowPtr pWin)
73705b261ecSmrg{
73805b261ecSmrg    if (realChildHeadProc) {
739f7df2e56Smrg        return realChildHeadProc(pWin);
74005b261ecSmrg    }
74105b261ecSmrg
74205b261ecSmrg    if (!pWin->parent &&
743f7df2e56Smrg        (screenIsSaved == SCREEN_SAVER_ON) &&
744f7df2e56Smrg        (HasSaverWindow(pWin->drawable.pScreen)))
745f7df2e56Smrg        return pWin->firstChild;
74605b261ecSmrg    else
747f7df2e56Smrg        return NullWindow;
74805b261ecSmrg}
74905b261ecSmrg
75005b261ecSmrg/*****
75105b261ecSmrg * CreateWindow
752f7df2e56Smrg *    Makes a window in response to client request
75305b261ecSmrg *****/
75405b261ecSmrg
7554202a189SmrgWindowPtr
75605b261ecSmrgCreateWindow(Window wid, WindowPtr pParent, int x, int y, unsigned w,
75705b261ecSmrg             unsigned h, unsigned bw, unsigned class, Mask vmask, XID *vlist,
75805b261ecSmrg             int depth, ClientPtr client, VisualID visual, int *error)
75905b261ecSmrg{
76005b261ecSmrg    WindowPtr pWin;
76105b261ecSmrg    WindowPtr pHead;
76205b261ecSmrg    ScreenPtr pScreen;
76305b261ecSmrg    int idepth, ivisual;
76405b261ecSmrg    Bool fOK;
76505b261ecSmrg    DepthPtr pDepth;
76605b261ecSmrg    PixmapFormatRec *format;
76705b261ecSmrg    WindowOptPtr ancwopt;
76805b261ecSmrg
76905b261ecSmrg    if (class == CopyFromParent)
770f7df2e56Smrg        class = pParent->drawable.class;
77105b261ecSmrg
772f7df2e56Smrg    if ((class != InputOutput) && (class != InputOnly)) {
773f7df2e56Smrg        *error = BadValue;
774f7df2e56Smrg        client->errorValue = class;
775f7df2e56Smrg        return NullWindow;
77605b261ecSmrg    }
77705b261ecSmrg
778f7df2e56Smrg    if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) {
779f7df2e56Smrg        *error = BadMatch;
780f7df2e56Smrg        return NullWindow;
78105b261ecSmrg    }
78205b261ecSmrg
783f7df2e56Smrg    if ((class == InputOnly) && ((bw != 0) || (depth != 0))) {
784f7df2e56Smrg        *error = BadMatch;
785f7df2e56Smrg        return NullWindow;
78605b261ecSmrg    }
78705b261ecSmrg
78805b261ecSmrg    pScreen = pParent->drawable.pScreen;
78905b261ecSmrg    if ((class == InputOutput) && (depth == 0))
790f7df2e56Smrg        depth = pParent->drawable.depth;
79105b261ecSmrg    ancwopt = pParent->optional;
79205b261ecSmrg    if (!ancwopt)
793f7df2e56Smrg        ancwopt = FindWindowWithOptional(pParent)->optional;
79405b261ecSmrg    if (visual == CopyFromParent) {
795f7df2e56Smrg        visual = ancwopt->visual;
79605b261ecSmrg    }
79705b261ecSmrg
79805b261ecSmrg    /* Find out if the depth and visual are acceptable for this Screen */
799f7df2e56Smrg    if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) {
800f7df2e56Smrg        fOK = FALSE;
801f7df2e56Smrg        for (idepth = 0; idepth < pScreen->numDepths; idepth++) {
802f7df2e56Smrg            pDepth = (DepthPtr) &pScreen->allowedDepths[idepth];
803f7df2e56Smrg            if ((depth == pDepth->depth) || (depth == 0)) {
804f7df2e56Smrg                for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) {
805f7df2e56Smrg                    if (visual == pDepth->vids[ivisual]) {
806f7df2e56Smrg                        fOK = TRUE;
807f7df2e56Smrg                        break;
808f7df2e56Smrg                    }
809f7df2e56Smrg                }
810f7df2e56Smrg            }
811f7df2e56Smrg        }
812f7df2e56Smrg        if (fOK == FALSE) {
813f7df2e56Smrg            *error = BadMatch;
814f7df2e56Smrg            return NullWindow;
815f7df2e56Smrg        }
81605b261ecSmrg    }
81705b261ecSmrg
81805b261ecSmrg    if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) &&
819f7df2e56Smrg        (class != InputOnly) && (depth != pParent->drawable.depth)) {
820f7df2e56Smrg        *error = BadMatch;
821f7df2e56Smrg        return NullWindow;
82205b261ecSmrg    }
82305b261ecSmrg
82405b261ecSmrg    if (((vmask & CWColormap) == 0) &&
825f7df2e56Smrg        (class != InputOnly) &&
826f7df2e56Smrg        ((visual != ancwopt->visual) || (ancwopt->colormap == None))) {
827f7df2e56Smrg        *error = BadMatch;
828f7df2e56Smrg        return NullWindow;
82905b261ecSmrg    }
83005b261ecSmrg
831f7df2e56Smrg    pWin = dixAllocateScreenObjectWithPrivates(pScreen, WindowRec, PRIVATE_WINDOW);
832f7df2e56Smrg    if (!pWin) {
833f7df2e56Smrg        *error = BadAlloc;
834f7df2e56Smrg        return NullWindow;
83505b261ecSmrg    }
83605b261ecSmrg    pWin->drawable = pParent->drawable;
83705b261ecSmrg    pWin->drawable.depth = depth;
83805b261ecSmrg    if (depth == pParent->drawable.depth)
839f7df2e56Smrg        pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel;
840f7df2e56Smrg    else {
841f7df2e56Smrg        for (format = screenInfo.formats; format->depth != depth; format++);
842f7df2e56Smrg        pWin->drawable.bitsPerPixel = format->bitsPerPixel;
84305b261ecSmrg    }
84405b261ecSmrg    if (class == InputOnly)
845f7df2e56Smrg        pWin->drawable.type = (short) UNDRAWABLE_WINDOW;
84605b261ecSmrg    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
84705b261ecSmrg
84805b261ecSmrg    pWin->drawable.id = wid;
84905b261ecSmrg    pWin->drawable.class = class;
85005b261ecSmrg
85105b261ecSmrg    pWin->parent = pParent;
85205b261ecSmrg    SetWindowToDefaults(pWin);
85305b261ecSmrg
854f7df2e56Smrg    if (visual != ancwopt->visual) {
855f7df2e56Smrg        if (!MakeWindowOptional(pWin)) {
856f7df2e56Smrg            dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
857f7df2e56Smrg            *error = BadAlloc;
858f7df2e56Smrg            return NullWindow;
859f7df2e56Smrg        }
860f7df2e56Smrg        pWin->optional->visual = visual;
861f7df2e56Smrg        pWin->optional->colormap = None;
86205b261ecSmrg    }
86305b261ecSmrg
86405b261ecSmrg    pWin->borderWidth = bw;
86505b261ecSmrg
866637ac9abSmrg    /*  security creation/labeling check
86705b261ecSmrg     */
868637ac9abSmrg    *error = XaceHook(XACE_RESOURCE_ACCESS, client, wid, RT_WINDOW, pWin,
869f7df2e56Smrg                      RT_WINDOW, pWin->parent,
870f7df2e56Smrg                      DixCreateAccess | DixSetAttrAccess);
871637ac9abSmrg    if (*error != Success) {
872f7df2e56Smrg        dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
873f7df2e56Smrg        return NullWindow;
87405b261ecSmrg    }
87505b261ecSmrg
876637ac9abSmrg    pWin->backgroundState = XaceBackgroundNoneState(pWin);
877637ac9abSmrg    pWin->background.pixel = pScreen->whitePixel;
878637ac9abSmrg
87905b261ecSmrg    pWin->borderIsPixel = pParent->borderIsPixel;
88005b261ecSmrg    pWin->border = pParent->border;
88105b261ecSmrg    if (pWin->borderIsPixel == FALSE)
882f7df2e56Smrg        pWin->border.pixmap->refcnt++;
883f7df2e56Smrg
884f7df2e56Smrg    pWin->origin.x = x + (int) bw;
885f7df2e56Smrg    pWin->origin.y = y + (int) bw;
88605b261ecSmrg    pWin->drawable.width = w;
88705b261ecSmrg    pWin->drawable.height = h;
888f7df2e56Smrg    pWin->drawable.x = pParent->drawable.x + x + (int) bw;
889f7df2e56Smrg    pWin->drawable.y = pParent->drawable.y + y + (int) bw;
89005b261ecSmrg
891f7df2e56Smrg    /* set up clip list correctly for unobscured WindowPtr */
8924202a189Smrg    RegionNull(&pWin->clipList);
8934202a189Smrg    RegionNull(&pWin->borderClip);
8944202a189Smrg    RegionNull(&pWin->winSize);
8954202a189Smrg    RegionNull(&pWin->borderSize);
89605b261ecSmrg
89705b261ecSmrg    pHead = RealChildHead(pParent);
898f7df2e56Smrg    if (pHead) {
899f7df2e56Smrg        pWin->nextSib = pHead->nextSib;
900f7df2e56Smrg        if (pHead->nextSib)
901f7df2e56Smrg            pHead->nextSib->prevSib = pWin;
902f7df2e56Smrg        else
903f7df2e56Smrg            pParent->lastChild = pWin;
904f7df2e56Smrg        pHead->nextSib = pWin;
905f7df2e56Smrg        pWin->prevSib = pHead;
90605b261ecSmrg    }
907f7df2e56Smrg    else {
908f7df2e56Smrg        pWin->nextSib = pParent->firstChild;
909f7df2e56Smrg        if (pParent->firstChild)
910f7df2e56Smrg            pParent->firstChild->prevSib = pWin;
911f7df2e56Smrg        else
912f7df2e56Smrg            pParent->lastChild = pWin;
913f7df2e56Smrg        pParent->firstChild = pWin;
91405b261ecSmrg    }
91505b261ecSmrg
916f7df2e56Smrg    SetWinSize(pWin);
917f7df2e56Smrg    SetBorderSize(pWin);
91805b261ecSmrg
91905b261ecSmrg    /* We SHOULD check for an error value here XXX */
920f7df2e56Smrg    if (!(*pScreen->CreateWindow) (pWin)) {
921f7df2e56Smrg        *error = BadAlloc;
922f7df2e56Smrg        DeleteWindow(pWin, None);
923f7df2e56Smrg        return NullWindow;
92405b261ecSmrg    }
92505b261ecSmrg    /* We SHOULD check for an error value here XXX */
926f7df2e56Smrg    (*pScreen->PositionWindow) (pWin, pWin->drawable.x, pWin->drawable.y);
92705b261ecSmrg
92805b261ecSmrg    if (!(vmask & CWEventMask))
929f7df2e56Smrg        RecalculateDeliverableEvents(pWin);
93005b261ecSmrg
93105b261ecSmrg    if (vmask)
932f7df2e56Smrg        *error = ChangeWindowAttributes(pWin, vmask, vlist, wClient(pWin));
93305b261ecSmrg    else
934f7df2e56Smrg        *error = Success;
93505b261ecSmrg
936f7df2e56Smrg    if (*error != Success) {
937f7df2e56Smrg        DeleteWindow(pWin, None);
938f7df2e56Smrg        return NullWindow;
939f7df2e56Smrg    }
940f7df2e56Smrg
941f7df2e56Smrg    if (SubSend(pParent)) {
942f7df2e56Smrg        xEvent event = {
943f7df2e56Smrg            .u.createNotify.window = wid,
944f7df2e56Smrg            .u.createNotify.parent = pParent->drawable.id,
945f7df2e56Smrg            .u.createNotify.x = x,
946f7df2e56Smrg            .u.createNotify.y = y,
947f7df2e56Smrg            .u.createNotify.width = w,
948f7df2e56Smrg            .u.createNotify.height = h,
949f7df2e56Smrg            .u.createNotify.borderWidth = bw,
950f7df2e56Smrg            .u.createNotify.override = pWin->overrideRedirect
951f7df2e56Smrg        };
952f7df2e56Smrg        event.u.u.type = CreateNotify;
953f7df2e56Smrg        DeliverEvents(pParent, &event, 1, NullWindow);
95405b261ecSmrg    }
95505b261ecSmrg    return pWin;
95605b261ecSmrg}
95705b261ecSmrg
95805b261ecSmrgstatic void
959f7df2e56SmrgDisposeWindowOptional(WindowPtr pWin)
96005b261ecSmrg{
96105b261ecSmrg    if (!pWin->optional)
962f7df2e56Smrg        return;
96305b261ecSmrg    /*
96405b261ecSmrg     * everything is peachy.  Delete the optional record
96505b261ecSmrg     * and clean up
96605b261ecSmrg     */
967f7df2e56Smrg    if (pWin->optional->cursor) {
968f7df2e56Smrg        FreeCursor(pWin->optional->cursor, (Cursor) 0);
969f7df2e56Smrg        pWin->cursorIsNone = FALSE;
97005b261ecSmrg    }
97105b261ecSmrg    else
972f7df2e56Smrg        pWin->cursorIsNone = TRUE;
973637ac9abSmrg
974f7df2e56Smrg    if (pWin->optional->deviceCursors) {
975637ac9abSmrg        DevCursorList pList;
976637ac9abSmrg        DevCursorList pPrev;
977f7df2e56Smrg
978637ac9abSmrg        pList = pWin->optional->deviceCursors;
979f7df2e56Smrg        while (pList) {
980637ac9abSmrg            if (pList->cursor)
981f7df2e56Smrg                FreeCursor(pList->cursor, (XID) 0);
982637ac9abSmrg            pPrev = pList;
983637ac9abSmrg            pList = pList->next;
9844202a189Smrg            free(pPrev);
985637ac9abSmrg        }
986637ac9abSmrg        pWin->optional->deviceCursors = NULL;
987637ac9abSmrg    }
988637ac9abSmrg
9894202a189Smrg    free(pWin->optional);
99005b261ecSmrg    pWin->optional = NULL;
99105b261ecSmrg}
99205b261ecSmrg
99305b261ecSmrgstatic void
99405b261ecSmrgFreeWindowResources(WindowPtr pWin)
99505b261ecSmrg{
99605b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
99705b261ecSmrg
99805b261ecSmrg    DeleteWindowFromAnySaveSet(pWin);
99905b261ecSmrg    DeleteWindowFromAnySelections(pWin);
100005b261ecSmrg    DeleteWindowFromAnyEvents(pWin, TRUE);
10014202a189Smrg    RegionUninit(&pWin->clipList);
10024202a189Smrg    RegionUninit(&pWin->winSize);
10034202a189Smrg    RegionUninit(&pWin->borderClip);
10044202a189Smrg    RegionUninit(&pWin->borderSize);
1005f7df2e56Smrg    if (wBoundingShape(pWin))
1006f7df2e56Smrg        RegionDestroy(wBoundingShape(pWin));
1007f7df2e56Smrg    if (wClipShape(pWin))
1008f7df2e56Smrg        RegionDestroy(wClipShape(pWin));
1009f7df2e56Smrg    if (wInputShape(pWin))
1010f7df2e56Smrg        RegionDestroy(wInputShape(pWin));
101105b261ecSmrg    if (pWin->borderIsPixel == FALSE)
1012f7df2e56Smrg        (*pScreen->DestroyPixmap) (pWin->border.pixmap);
101305b261ecSmrg    if (pWin->backgroundState == BackgroundPixmap)
1014f7df2e56Smrg        (*pScreen->DestroyPixmap) (pWin->background.pixmap);
101505b261ecSmrg
101605b261ecSmrg    DeleteAllWindowProperties(pWin);
101705b261ecSmrg    /* We SHOULD check for an error value here XXX */
1018f7df2e56Smrg    (*pScreen->DestroyWindow) (pWin);
1019f7df2e56Smrg    DisposeWindowOptional(pWin);
102005b261ecSmrg}
102105b261ecSmrg
102205b261ecSmrgstatic void
102305b261ecSmrgCrushTree(WindowPtr pWin)
102405b261ecSmrg{
102505b261ecSmrg    WindowPtr pChild, pSib, pParent;
102605b261ecSmrg    UnrealizeWindowProcPtr UnrealizeWindow;
102705b261ecSmrg
102805b261ecSmrg    if (!(pChild = pWin->firstChild))
1029f7df2e56Smrg        return;
103005b261ecSmrg    UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow;
1031f7df2e56Smrg    while (1) {
1032f7df2e56Smrg        if (pChild->firstChild) {
1033f7df2e56Smrg            pChild = pChild->firstChild;
1034f7df2e56Smrg            continue;
1035f7df2e56Smrg        }
1036f7df2e56Smrg        while (1) {
1037f7df2e56Smrg            pParent = pChild->parent;
1038f7df2e56Smrg            if (SubStrSend(pChild, pParent)) {
1039f7df2e56Smrg                xEvent event = { .u.u.type = DestroyNotify };
1040f7df2e56Smrg                event.u.destroyNotify.window = pChild->drawable.id;
1041f7df2e56Smrg                DeliverEvents(pChild, &event, 1, NullWindow);
1042f7df2e56Smrg            }
1043f7df2e56Smrg            FreeResource(pChild->drawable.id, RT_WINDOW);
1044f7df2e56Smrg            pSib = pChild->nextSib;
1045f7df2e56Smrg            pChild->viewable = FALSE;
1046f7df2e56Smrg            if (pChild->realized) {
1047f7df2e56Smrg                pChild->realized = FALSE;
1048f7df2e56Smrg                (*UnrealizeWindow) (pChild);
1049f7df2e56Smrg            }
1050f7df2e56Smrg            FreeWindowResources(pChild);
1051f7df2e56Smrg            dixFreeObjectWithPrivates(pChild, PRIVATE_WINDOW);
1052f7df2e56Smrg            if ((pChild = pSib))
1053f7df2e56Smrg                break;
1054f7df2e56Smrg            pChild = pParent;
1055f7df2e56Smrg            pChild->firstChild = NullWindow;
1056f7df2e56Smrg            pChild->lastChild = NullWindow;
1057f7df2e56Smrg            if (pChild == pWin)
1058f7df2e56Smrg                return;
1059f7df2e56Smrg        }
1060f7df2e56Smrg    }
1061f7df2e56Smrg}
1062f7df2e56Smrg
106305b261ecSmrg/*****
106405b261ecSmrg *  DeleteWindow
106505b261ecSmrg *	 Deletes child of window then window itself
106605b261ecSmrg *	 If wid is None, don't send any events
106705b261ecSmrg *****/
106805b261ecSmrg
106905b261ecSmrgint
1070f7df2e56SmrgDeleteWindow(void *value, XID wid)
1071f7df2e56Smrg{
107205b261ecSmrg    WindowPtr pParent;
1073f7df2e56Smrg    WindowPtr pWin = (WindowPtr) value;
107405b261ecSmrg
107505b261ecSmrg    UnmapWindow(pWin, FALSE);
107605b261ecSmrg
107705b261ecSmrg    CrushTree(pWin);
107805b261ecSmrg
107905b261ecSmrg    pParent = pWin->parent;
1080f7df2e56Smrg    if (wid && pParent && SubStrSend(pWin, pParent)) {
1081f7df2e56Smrg        xEvent event = { .u.u.type = DestroyNotify };
1082f7df2e56Smrg        event.u.destroyNotify.window = pWin->drawable.id;
1083f7df2e56Smrg        DeliverEvents(pWin, &event, 1, NullWindow);
108405b261ecSmrg    }
108505b261ecSmrg
108605b261ecSmrg    FreeWindowResources(pWin);
1087f7df2e56Smrg    if (pParent) {
1088f7df2e56Smrg        if (pParent->firstChild == pWin)
1089f7df2e56Smrg            pParent->firstChild = pWin->nextSib;
1090f7df2e56Smrg        if (pParent->lastChild == pWin)
1091f7df2e56Smrg            pParent->lastChild = pWin->prevSib;
1092f7df2e56Smrg        if (pWin->nextSib)
1093f7df2e56Smrg            pWin->nextSib->prevSib = pWin->prevSib;
1094f7df2e56Smrg        if (pWin->prevSib)
1095f7df2e56Smrg            pWin->prevSib->nextSib = pWin->nextSib;
109605b261ecSmrg    }
10974202a189Smrg    else
1098f7df2e56Smrg        pWin->drawable.pScreen->root = NULL;
10994202a189Smrg    dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
110005b261ecSmrg    return Success;
110105b261ecSmrg}
110205b261ecSmrg
1103637ac9abSmrgint
110405b261ecSmrgDestroySubwindows(WindowPtr pWin, ClientPtr client)
110505b261ecSmrg{
110605b261ecSmrg    /* XXX
110705b261ecSmrg     * The protocol is quite clear that each window should be
110805b261ecSmrg     * destroyed in turn, however, unmapping all of the first
110905b261ecSmrg     * eliminates most of the calls to ValidateTree.  So,
111005b261ecSmrg     * this implementation is incorrect in that all of the
111105b261ecSmrg     * UnmapNotifies occur before all of the DestroyNotifies.
111205b261ecSmrg     * If you care, simply delete the call to UnmapSubwindows.
111305b261ecSmrg     */
111405b261ecSmrg    UnmapSubwindows(pWin);
1115637ac9abSmrg    while (pWin->lastChild) {
1116f7df2e56Smrg        int rc = XaceHook(XACE_RESOURCE_ACCESS, client,
1117f7df2e56Smrg                          pWin->lastChild->drawable.id, RT_WINDOW,
1118f7df2e56Smrg                          pWin->lastChild, RT_NONE, NULL, DixDestroyAccess);
1119f7df2e56Smrg
1120f7df2e56Smrg        if (rc != Success)
1121f7df2e56Smrg            return rc;
1122f7df2e56Smrg        FreeResource(pWin->lastChild->drawable.id, RT_NONE);
1123637ac9abSmrg    }
1124637ac9abSmrg    return Success;
112505b261ecSmrg}
112605b261ecSmrg
112765b04b38Smrgstatic void
112865b04b38SmrgSetRootWindowBackground(WindowPtr pWin, ScreenPtr pScreen, Mask *index2)
112965b04b38Smrg{
113065b04b38Smrg    /* following the protocol: "Changing the background of a root window to
113165b04b38Smrg     * None or ParentRelative restores the default background pixmap" */
113265b04b38Smrg    if (bgNoneRoot) {
1133f7df2e56Smrg        pWin->backgroundState = XaceBackgroundNoneState(pWin);
1134f7df2e56Smrg        pWin->background.pixel = pScreen->whitePixel;
113565b04b38Smrg    }
113665b04b38Smrg    else if (party_like_its_1989)
1137f7df2e56Smrg        MakeRootTile(pWin);
113865b04b38Smrg    else {
113965b04b38Smrg        pWin->backgroundState = BackgroundPixel;
1140f7df2e56Smrg        if (whiteRoot)
1141f7df2e56Smrg            pWin->background.pixel = pScreen->whitePixel;
1142f7df2e56Smrg        else
1143f7df2e56Smrg            pWin->background.pixel = pScreen->blackPixel;
1144f7df2e56Smrg        *index2 = CWBackPixel;
114565b04b38Smrg    }
114665b04b38Smrg}
114765b04b38Smrg
114805b261ecSmrg/*****
114905b261ecSmrg *  ChangeWindowAttributes
1150f7df2e56Smrg *
115105b261ecSmrg *  The value-mask specifies which attributes are to be changed; the
115205b261ecSmrg *  value-list contains one value for each one bit in the mask, from least
1153f7df2e56Smrg *  to most significant bit in the mask.
115405b261ecSmrg *****/
1155f7df2e56Smrg
11564202a189Smrgint
115705b261ecSmrgChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client)
115805b261ecSmrg{
115905b261ecSmrg    XID *pVlist;
116005b261ecSmrg    PixmapPtr pPixmap;
116105b261ecSmrg    Pixmap pixID;
116205b261ecSmrg    CursorPtr pCursor, pOldCursor;
116305b261ecSmrg    Cursor cursorID;
116405b261ecSmrg    WindowPtr pChild;
116505b261ecSmrg    Colormap cmap;
1166f7df2e56Smrg    ColormapPtr pCmap;
116705b261ecSmrg    xEvent xE;
1168637ac9abSmrg    int error, rc;
116905b261ecSmrg    ScreenPtr pScreen;
1170637ac9abSmrg    Mask index2, tmask, vmaskCopy = 0;
117105b261ecSmrg    unsigned int val;
1172637ac9abSmrg    Bool checkOptional = FALSE, borderRelative = FALSE;
117305b261ecSmrg
1174f7df2e56Smrg    if ((pWin->drawable.class == InputOnly) &&
1175f7df2e56Smrg        (vmask & (~INPUTONLY_LEGAL_MASK)))
1176f7df2e56Smrg        return BadMatch;
117705b261ecSmrg
117805b261ecSmrg    error = Success;
117905b261ecSmrg    pScreen = pWin->drawable.pScreen;
118005b261ecSmrg    pVlist = vlist;
118105b261ecSmrg    tmask = vmask;
1182f7df2e56Smrg    while (tmask) {
1183f7df2e56Smrg        index2 = (Mask) lowbit(tmask);
1184f7df2e56Smrg        tmask &= ~index2;
1185f7df2e56Smrg        switch (index2) {
1186f7df2e56Smrg        case CWBackPixmap:
1187f7df2e56Smrg            pixID = (Pixmap) * pVlist;
1188f7df2e56Smrg            pVlist++;
1189f7df2e56Smrg            if (pWin->backgroundState == ParentRelative)
1190f7df2e56Smrg                borderRelative = TRUE;
1191f7df2e56Smrg            if (pixID == None) {
1192f7df2e56Smrg                if (pWin->backgroundState == BackgroundPixmap)
1193f7df2e56Smrg                    (*pScreen->DestroyPixmap) (pWin->background.pixmap);
1194f7df2e56Smrg                if (!pWin->parent)
1195f7df2e56Smrg                    SetRootWindowBackground(pWin, pScreen, &index2);
1196f7df2e56Smrg                else {
1197f7df2e56Smrg                    pWin->backgroundState = XaceBackgroundNoneState(pWin);
1198f7df2e56Smrg                    pWin->background.pixel = pScreen->whitePixel;
1199f7df2e56Smrg                }
1200f7df2e56Smrg            }
1201f7df2e56Smrg            else if (pixID == ParentRelative) {
1202f7df2e56Smrg                if (pWin->parent &&
1203f7df2e56Smrg                    pWin->drawable.depth != pWin->parent->drawable.depth) {
1204f7df2e56Smrg                    error = BadMatch;
1205f7df2e56Smrg                    goto PatchUp;
1206f7df2e56Smrg                }
1207f7df2e56Smrg                if (pWin->backgroundState == BackgroundPixmap)
1208f7df2e56Smrg                    (*pScreen->DestroyPixmap) (pWin->background.pixmap);
1209f7df2e56Smrg                if (!pWin->parent)
1210f7df2e56Smrg                    SetRootWindowBackground(pWin, pScreen, &index2);
1211f7df2e56Smrg                else
1212f7df2e56Smrg                    pWin->backgroundState = ParentRelative;
1213f7df2e56Smrg                borderRelative = TRUE;
1214f7df2e56Smrg                /* Note that the parent's backgroundTile's refcnt is NOT
1215f7df2e56Smrg                 * incremented. */
1216f7df2e56Smrg            }
1217f7df2e56Smrg            else {
1218f7df2e56Smrg                rc = dixLookupResourceByType((void **) &pPixmap, pixID,
1219f7df2e56Smrg                                             RT_PIXMAP, client, DixReadAccess);
1220f7df2e56Smrg                if (rc == Success) {
1221f7df2e56Smrg                    if ((pPixmap->drawable.depth != pWin->drawable.depth) ||
1222f7df2e56Smrg                        (pPixmap->drawable.pScreen != pScreen)) {
1223f7df2e56Smrg                        error = BadMatch;
1224f7df2e56Smrg                        goto PatchUp;
1225f7df2e56Smrg                    }
1226f7df2e56Smrg                    if (pWin->backgroundState == BackgroundPixmap)
1227f7df2e56Smrg                        (*pScreen->DestroyPixmap) (pWin->background.pixmap);
1228f7df2e56Smrg                    pWin->backgroundState = BackgroundPixmap;
1229f7df2e56Smrg                    pWin->background.pixmap = pPixmap;
1230f7df2e56Smrg                    pPixmap->refcnt++;
1231f7df2e56Smrg                }
1232f7df2e56Smrg                else {
1233f7df2e56Smrg                    error = rc;
1234f7df2e56Smrg                    client->errorValue = pixID;
1235f7df2e56Smrg                    goto PatchUp;
1236f7df2e56Smrg                }
1237f7df2e56Smrg            }
1238f7df2e56Smrg            break;
1239f7df2e56Smrg        case CWBackPixel:
1240f7df2e56Smrg            if (pWin->backgroundState == ParentRelative)
1241f7df2e56Smrg                borderRelative = TRUE;
1242f7df2e56Smrg            if (pWin->backgroundState == BackgroundPixmap)
1243f7df2e56Smrg                (*pScreen->DestroyPixmap) (pWin->background.pixmap);
1244f7df2e56Smrg            pWin->backgroundState = BackgroundPixel;
1245f7df2e56Smrg            pWin->background.pixel = (CARD32) *pVlist;
1246f7df2e56Smrg            /* background pixel overrides background pixmap,
1247f7df2e56Smrg               so don't let the ddx layer see both bits */
1248f7df2e56Smrg            vmaskCopy &= ~CWBackPixmap;
1249f7df2e56Smrg            pVlist++;
1250f7df2e56Smrg            break;
1251f7df2e56Smrg        case CWBorderPixmap:
1252f7df2e56Smrg            pixID = (Pixmap) * pVlist;
1253f7df2e56Smrg            pVlist++;
1254f7df2e56Smrg            if (pixID == CopyFromParent) {
1255f7df2e56Smrg                if (!pWin->parent ||
1256f7df2e56Smrg                    (pWin->drawable.depth != pWin->parent->drawable.depth)) {
1257f7df2e56Smrg                    error = BadMatch;
1258f7df2e56Smrg                    goto PatchUp;
1259f7df2e56Smrg                }
1260f7df2e56Smrg                if (pWin->parent->borderIsPixel == TRUE) {
1261f7df2e56Smrg                    if (pWin->borderIsPixel == FALSE)
1262f7df2e56Smrg                        (*pScreen->DestroyPixmap) (pWin->border.pixmap);
1263f7df2e56Smrg                    pWin->border = pWin->parent->border;
1264f7df2e56Smrg                    pWin->borderIsPixel = TRUE;
1265f7df2e56Smrg                    index2 = CWBorderPixel;
1266f7df2e56Smrg                    break;
1267f7df2e56Smrg                }
1268f7df2e56Smrg                else {
1269f7df2e56Smrg                    pixID = pWin->parent->border.pixmap->drawable.id;
1270f7df2e56Smrg                }
1271f7df2e56Smrg            }
1272f7df2e56Smrg            rc = dixLookupResourceByType((void **) &pPixmap, pixID, RT_PIXMAP,
1273f7df2e56Smrg                                         client, DixReadAccess);
1274f7df2e56Smrg            if (rc == Success) {
1275f7df2e56Smrg                if ((pPixmap->drawable.depth != pWin->drawable.depth) ||
1276f7df2e56Smrg                    (pPixmap->drawable.pScreen != pScreen)) {
1277f7df2e56Smrg                    error = BadMatch;
1278f7df2e56Smrg                    goto PatchUp;
1279f7df2e56Smrg                }
1280f7df2e56Smrg                if (pWin->borderIsPixel == FALSE)
1281f7df2e56Smrg                    (*pScreen->DestroyPixmap) (pWin->border.pixmap);
1282f7df2e56Smrg                pWin->borderIsPixel = FALSE;
1283f7df2e56Smrg                pWin->border.pixmap = pPixmap;
1284f7df2e56Smrg                pPixmap->refcnt++;
1285f7df2e56Smrg            }
1286f7df2e56Smrg            else {
1287f7df2e56Smrg                error = rc;
1288f7df2e56Smrg                client->errorValue = pixID;
1289f7df2e56Smrg                goto PatchUp;
1290f7df2e56Smrg            }
1291f7df2e56Smrg            break;
1292f7df2e56Smrg        case CWBorderPixel:
1293f7df2e56Smrg            if (pWin->borderIsPixel == FALSE)
1294f7df2e56Smrg                (*pScreen->DestroyPixmap) (pWin->border.pixmap);
1295f7df2e56Smrg            pWin->borderIsPixel = TRUE;
1296f7df2e56Smrg            pWin->border.pixel = (CARD32) *pVlist;
1297f7df2e56Smrg            /* border pixel overrides border pixmap,
1298f7df2e56Smrg               so don't let the ddx layer see both bits */
1299f7df2e56Smrg            vmaskCopy &= ~CWBorderPixmap;
1300f7df2e56Smrg            pVlist++;
1301f7df2e56Smrg            break;
1302f7df2e56Smrg        case CWBitGravity:
1303f7df2e56Smrg            val = (CARD8) *pVlist;
1304f7df2e56Smrg            pVlist++;
1305f7df2e56Smrg            if (val > StaticGravity) {
1306f7df2e56Smrg                error = BadValue;
1307f7df2e56Smrg                client->errorValue = val;
1308f7df2e56Smrg                goto PatchUp;
1309f7df2e56Smrg            }
1310f7df2e56Smrg            pWin->bitGravity = val;
1311f7df2e56Smrg            break;
1312f7df2e56Smrg        case CWWinGravity:
1313f7df2e56Smrg            val = (CARD8) *pVlist;
1314f7df2e56Smrg            pVlist++;
1315f7df2e56Smrg            if (val > StaticGravity) {
1316f7df2e56Smrg                error = BadValue;
1317f7df2e56Smrg                client->errorValue = val;
1318f7df2e56Smrg                goto PatchUp;
1319f7df2e56Smrg            }
1320f7df2e56Smrg            pWin->winGravity = val;
1321f7df2e56Smrg            break;
1322f7df2e56Smrg        case CWBackingStore:
1323f7df2e56Smrg            val = (CARD8) *pVlist;
1324f7df2e56Smrg            pVlist++;
1325f7df2e56Smrg            if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) {
1326f7df2e56Smrg                error = BadValue;
1327f7df2e56Smrg                client->errorValue = val;
1328f7df2e56Smrg                goto PatchUp;
1329f7df2e56Smrg            }
13305a112b11Smrg            /* if we're not actually changing the window's state, hide
13315a112b11Smrg             * CWBackingStore from vmaskCopy so it doesn't get passed to
13325a112b11Smrg             * ->ChangeWindowAttributes below
13335a112b11Smrg             */
13345a112b11Smrg            if (pWin->backingStore == val)
13355a112b11Smrg                continue;
1336f7df2e56Smrg            pWin->backingStore = val;
1337f7df2e56Smrg            break;
1338f7df2e56Smrg        case CWBackingPlanes:
1339f7df2e56Smrg            if (pWin->optional || ((CARD32) *pVlist != (CARD32) ~0L)) {
1340f7df2e56Smrg                if (!pWin->optional && !MakeWindowOptional(pWin)) {
1341f7df2e56Smrg                    error = BadAlloc;
1342f7df2e56Smrg                    goto PatchUp;
1343f7df2e56Smrg                }
1344f7df2e56Smrg                pWin->optional->backingBitPlanes = (CARD32) *pVlist;
1345f7df2e56Smrg                if ((CARD32) *pVlist == (CARD32) ~0L)
1346f7df2e56Smrg                    checkOptional = TRUE;
1347f7df2e56Smrg            }
1348f7df2e56Smrg            pVlist++;
1349f7df2e56Smrg            break;
1350f7df2e56Smrg        case CWBackingPixel:
1351f7df2e56Smrg            if (pWin->optional || (CARD32) *pVlist) {
1352f7df2e56Smrg                if (!pWin->optional && !MakeWindowOptional(pWin)) {
1353f7df2e56Smrg                    error = BadAlloc;
1354f7df2e56Smrg                    goto PatchUp;
1355f7df2e56Smrg                }
1356f7df2e56Smrg                pWin->optional->backingPixel = (CARD32) *pVlist;
1357f7df2e56Smrg                if (!*pVlist)
1358f7df2e56Smrg                    checkOptional = TRUE;
1359f7df2e56Smrg            }
1360f7df2e56Smrg            pVlist++;
1361f7df2e56Smrg            break;
1362f7df2e56Smrg        case CWSaveUnder:
1363f7df2e56Smrg            val = (BOOL) * pVlist;
1364f7df2e56Smrg            pVlist++;
1365f7df2e56Smrg            if ((val != xTrue) && (val != xFalse)) {
1366f7df2e56Smrg                error = BadValue;
1367f7df2e56Smrg                client->errorValue = val;
1368f7df2e56Smrg                goto PatchUp;
1369f7df2e56Smrg            }
1370f7df2e56Smrg            pWin->saveUnder = val;
1371f7df2e56Smrg            break;
1372f7df2e56Smrg        case CWEventMask:
1373f7df2e56Smrg            rc = EventSelectForWindow(pWin, client, (Mask) *pVlist);
1374f7df2e56Smrg            if (rc) {
1375f7df2e56Smrg                error = rc;
1376f7df2e56Smrg                goto PatchUp;
1377f7df2e56Smrg            }
1378f7df2e56Smrg            pVlist++;
1379f7df2e56Smrg            break;
1380f7df2e56Smrg        case CWDontPropagate:
1381f7df2e56Smrg            rc = EventSuppressForWindow(pWin, client, (Mask) *pVlist,
1382f7df2e56Smrg                                        &checkOptional);
1383f7df2e56Smrg            if (rc) {
1384f7df2e56Smrg                error = rc;
1385f7df2e56Smrg                goto PatchUp;
1386f7df2e56Smrg            }
1387f7df2e56Smrg            pVlist++;
1388f7df2e56Smrg            break;
1389f7df2e56Smrg        case CWOverrideRedirect:
1390f7df2e56Smrg            val = (BOOL) * pVlist;
1391f7df2e56Smrg            pVlist++;
1392f7df2e56Smrg            if ((val != xTrue) && (val != xFalse)) {
1393f7df2e56Smrg                error = BadValue;
1394f7df2e56Smrg                client->errorValue = val;
1395f7df2e56Smrg                goto PatchUp;
1396f7df2e56Smrg            }
1397f7df2e56Smrg            if (val == xTrue) {
1398f7df2e56Smrg                rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
1399f7df2e56Smrg                              RT_WINDOW, pWin, RT_NONE, NULL, DixGrabAccess);
1400f7df2e56Smrg                if (rc != Success) {
1401f7df2e56Smrg                    error = rc;
1402f7df2e56Smrg                    client->errorValue = pWin->drawable.id;
1403f7df2e56Smrg                    goto PatchUp;
1404f7df2e56Smrg                }
1405f7df2e56Smrg            }
1406f7df2e56Smrg            pWin->overrideRedirect = val;
1407f7df2e56Smrg            break;
1408f7df2e56Smrg        case CWColormap:
1409f7df2e56Smrg            cmap = (Colormap) * pVlist;
1410f7df2e56Smrg            pVlist++;
1411f7df2e56Smrg            if (cmap == CopyFromParent) {
1412f7df2e56Smrg                if (pWin->parent &&
1413f7df2e56Smrg                    (!pWin->optional ||
1414f7df2e56Smrg                     pWin->optional->visual == wVisual(pWin->parent))) {
1415f7df2e56Smrg                    cmap = wColormap(pWin->parent);
1416f7df2e56Smrg                }
1417f7df2e56Smrg                else
1418f7df2e56Smrg                    cmap = None;
1419f7df2e56Smrg            }
1420f7df2e56Smrg            if (cmap == None) {
1421f7df2e56Smrg                error = BadMatch;
1422f7df2e56Smrg                goto PatchUp;
1423f7df2e56Smrg            }
1424f7df2e56Smrg            rc = dixLookupResourceByType((void **) &pCmap, cmap, RT_COLORMAP,
1425f7df2e56Smrg                                         client, DixUseAccess);
1426f7df2e56Smrg            if (rc != Success) {
1427f7df2e56Smrg                error = rc;
1428f7df2e56Smrg                client->errorValue = cmap;
1429f7df2e56Smrg                goto PatchUp;
1430f7df2e56Smrg            }
1431f7df2e56Smrg            if (pCmap->pVisual->vid != wVisual(pWin) ||
1432f7df2e56Smrg                pCmap->pScreen != pScreen) {
1433f7df2e56Smrg                error = BadMatch;
1434f7df2e56Smrg                goto PatchUp;
1435f7df2e56Smrg            }
1436f7df2e56Smrg            if (cmap != wColormap(pWin)) {
1437f7df2e56Smrg                if (!pWin->optional) {
1438f7df2e56Smrg                    if (!MakeWindowOptional(pWin)) {
1439f7df2e56Smrg                        error = BadAlloc;
1440f7df2e56Smrg                        goto PatchUp;
1441f7df2e56Smrg                    }
1442f7df2e56Smrg                }
1443f7df2e56Smrg                else if (pWin->parent && cmap == wColormap(pWin->parent))
1444f7df2e56Smrg                    checkOptional = TRUE;
1445f7df2e56Smrg
1446f7df2e56Smrg                /*
1447f7df2e56Smrg                 * propagate the original colormap to any children
1448f7df2e56Smrg                 * inheriting it
1449f7df2e56Smrg                 */
1450f7df2e56Smrg
1451f7df2e56Smrg                for (pChild = pWin->firstChild; pChild;
1452f7df2e56Smrg                     pChild = pChild->nextSib) {
1453f7df2e56Smrg                    if (!pChild->optional && !MakeWindowOptional(pChild)) {
1454f7df2e56Smrg                        error = BadAlloc;
1455f7df2e56Smrg                        goto PatchUp;
1456f7df2e56Smrg                    }
1457f7df2e56Smrg                }
1458f7df2e56Smrg
1459f7df2e56Smrg                pWin->optional->colormap = cmap;
1460f7df2e56Smrg
1461f7df2e56Smrg                /*
1462f7df2e56Smrg                 * check on any children now matching the new colormap
1463f7df2e56Smrg                 */
1464f7df2e56Smrg
1465f7df2e56Smrg                for (pChild = pWin->firstChild; pChild;
1466f7df2e56Smrg                     pChild = pChild->nextSib) {
1467f7df2e56Smrg                    if (pChild->optional->colormap == cmap)
1468f7df2e56Smrg                        CheckWindowOptionalNeed(pChild);
1469f7df2e56Smrg                }
1470f7df2e56Smrg
1471f7df2e56Smrg                xE = (xEvent) {
1472f7df2e56Smrg                    .u.colormap.window = pWin->drawable.id,
1473f7df2e56Smrg                    .u.colormap.colormap = cmap,
1474f7df2e56Smrg                    .u.colormap.new = xTrue,
1475f7df2e56Smrg                    .u.colormap.state = IsMapInstalled(cmap, pWin)
1476f7df2e56Smrg                };
1477f7df2e56Smrg                xE.u.u.type = ColormapNotify;
1478f7df2e56Smrg                DeliverEvents(pWin, &xE, 1, NullWindow);
1479f7df2e56Smrg            }
1480f7df2e56Smrg            break;
1481f7df2e56Smrg        case CWCursor:
1482f7df2e56Smrg            cursorID = (Cursor) * pVlist;
1483f7df2e56Smrg            pVlist++;
1484f7df2e56Smrg            /*
1485f7df2e56Smrg             * install the new
1486f7df2e56Smrg             */
1487f7df2e56Smrg            if (cursorID == None) {
1488f7df2e56Smrg                if (pWin == pWin->drawable.pScreen->root)
1489f7df2e56Smrg                    pCursor = rootCursor;
1490f7df2e56Smrg                else
1491f7df2e56Smrg                    pCursor = (CursorPtr) None;
1492f7df2e56Smrg            }
1493f7df2e56Smrg            else {
1494f7df2e56Smrg                rc = dixLookupResourceByType((void **) &pCursor, cursorID,
1495f7df2e56Smrg                                             RT_CURSOR, client, DixUseAccess);
1496f7df2e56Smrg                if (rc != Success) {
1497f7df2e56Smrg                    error = rc;
1498f7df2e56Smrg                    client->errorValue = cursorID;
1499f7df2e56Smrg                    goto PatchUp;
1500f7df2e56Smrg                }
1501f7df2e56Smrg            }
1502f7df2e56Smrg
1503f7df2e56Smrg            if (pCursor != wCursor(pWin)) {
1504f7df2e56Smrg                /*
1505f7df2e56Smrg                 * patch up child windows so they don't lose cursors.
1506f7df2e56Smrg                 */
1507f7df2e56Smrg
1508f7df2e56Smrg                for (pChild = pWin->firstChild; pChild;
1509f7df2e56Smrg                     pChild = pChild->nextSib) {
1510f7df2e56Smrg                    if (!pChild->optional && !pChild->cursorIsNone &&
1511f7df2e56Smrg                        !MakeWindowOptional(pChild)) {
1512f7df2e56Smrg                        error = BadAlloc;
1513f7df2e56Smrg                        goto PatchUp;
1514f7df2e56Smrg                    }
1515f7df2e56Smrg                }
1516f7df2e56Smrg
1517f7df2e56Smrg                pOldCursor = 0;
1518f7df2e56Smrg                if (pCursor == (CursorPtr) None) {
1519f7df2e56Smrg                    pWin->cursorIsNone = TRUE;
1520f7df2e56Smrg                    if (pWin->optional) {
1521f7df2e56Smrg                        pOldCursor = pWin->optional->cursor;
1522f7df2e56Smrg                        pWin->optional->cursor = (CursorPtr) None;
1523f7df2e56Smrg                        checkOptional = TRUE;
1524f7df2e56Smrg                    }
1525f7df2e56Smrg                }
1526f7df2e56Smrg                else {
1527f7df2e56Smrg                    if (!pWin->optional) {
1528f7df2e56Smrg                        if (!MakeWindowOptional(pWin)) {
1529f7df2e56Smrg                            error = BadAlloc;
1530f7df2e56Smrg                            goto PatchUp;
1531f7df2e56Smrg                        }
1532f7df2e56Smrg                    }
1533f7df2e56Smrg                    else if (pWin->parent && pCursor == wCursor(pWin->parent))
1534f7df2e56Smrg                        checkOptional = TRUE;
1535f7df2e56Smrg                    pOldCursor = pWin->optional->cursor;
1536f7df2e56Smrg                    pWin->optional->cursor = RefCursor(pCursor);
1537f7df2e56Smrg                    pWin->cursorIsNone = FALSE;
1538f7df2e56Smrg                    /*
1539f7df2e56Smrg                     * check on any children now matching the new cursor
1540f7df2e56Smrg                     */
1541f7df2e56Smrg
1542f7df2e56Smrg                    for (pChild = pWin->firstChild; pChild;
1543f7df2e56Smrg                         pChild = pChild->nextSib) {
1544f7df2e56Smrg                        if (pChild->optional &&
1545f7df2e56Smrg                            (pChild->optional->cursor == pCursor))
1546f7df2e56Smrg                            CheckWindowOptionalNeed(pChild);
1547f7df2e56Smrg                    }
1548f7df2e56Smrg                }
1549f7df2e56Smrg
1550f7df2e56Smrg                CursorVisible = TRUE;
1551f7df2e56Smrg
1552f7df2e56Smrg                if (pWin->realized)
1553f7df2e56Smrg                    WindowHasNewCursor(pWin);
1554f7df2e56Smrg
1555f7df2e56Smrg                /* Can't free cursor until here - old cursor
1556f7df2e56Smrg                 * is needed in WindowHasNewCursor
1557f7df2e56Smrg                 */
1558f7df2e56Smrg                if (pOldCursor)
1559f7df2e56Smrg                    FreeCursor(pOldCursor, (Cursor) 0);
1560f7df2e56Smrg            }
1561f7df2e56Smrg            break;
1562f7df2e56Smrg        default:
1563f7df2e56Smrg            error = BadValue;
1564f7df2e56Smrg            client->errorValue = vmask;
1565f7df2e56Smrg            goto PatchUp;
1566f7df2e56Smrg        }
1567f7df2e56Smrg        vmaskCopy |= index2;
1568f7df2e56Smrg    }
1569f7df2e56Smrg PatchUp:
157005b261ecSmrg    if (checkOptional)
1571f7df2e56Smrg        CheckWindowOptionalNeed(pWin);
157205b261ecSmrg
1573f7df2e56Smrg    /* We SHOULD check for an error value here XXX */
1574f7df2e56Smrg    (*pScreen->ChangeWindowAttributes) (pWin, vmaskCopy);
157505b261ecSmrg
1576f7df2e56Smrg    /*
1577f7df2e56Smrg       If the border contents have changed, redraw the border.
1578f7df2e56Smrg       Note that this has to be done AFTER pScreen->ChangeWindowAttributes
1579f7df2e56Smrg       for the tile to be rotated, and the correct function selected.
1580f7df2e56Smrg     */
158105b261ecSmrg    if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative)
1582f7df2e56Smrg        && pWin->viewable && HasBorder(pWin)) {
1583f7df2e56Smrg        RegionRec exposed;
158405b261ecSmrg
1585f7df2e56Smrg        RegionNull(&exposed);
1586f7df2e56Smrg        RegionSubtract(&exposed, &pWin->borderClip, &pWin->winSize);
1587f7df2e56Smrg        pWin->drawable.pScreen->PaintWindow(pWin, &exposed, PW_BORDER);
1588f7df2e56Smrg        RegionUninit(&exposed);
158905b261ecSmrg    }
159005b261ecSmrg    return error;
159105b261ecSmrg}
159205b261ecSmrg
159305b261ecSmrg/*****
159405b261ecSmrg * GetWindowAttributes
159505b261ecSmrg *    Notice that this is different than ChangeWindowAttributes
159605b261ecSmrg *****/
159705b261ecSmrg
159805b261ecSmrgvoid
1599f7df2e56SmrgGetWindowAttributes(WindowPtr pWin, ClientPtr client,
1600f7df2e56Smrg                    xGetWindowAttributesReply * wa)
160105b261ecSmrg{
160205b261ecSmrg    wa->type = X_Reply;
160305b261ecSmrg    wa->bitGravity = pWin->bitGravity;
160405b261ecSmrg    wa->winGravity = pWin->winGravity;
16055a112b11Smrg    wa->backingStore = pWin->backingStore;
16064202a189Smrg    wa->length = bytes_to_int32(sizeof(xGetWindowAttributesReply) -
1607f7df2e56Smrg                                sizeof(xGenericReply));
160805b261ecSmrg    wa->sequenceNumber = client->sequence;
1609f7df2e56Smrg    wa->backingBitPlanes = wBackingBitPlanes(pWin);
1610f7df2e56Smrg    wa->backingPixel = wBackingPixel(pWin);
1611f7df2e56Smrg    wa->saveUnder = (BOOL) pWin->saveUnder;
161205b261ecSmrg    wa->override = pWin->overrideRedirect;
161305b261ecSmrg    if (!pWin->mapped)
1614f7df2e56Smrg        wa->mapState = IsUnmapped;
161505b261ecSmrg    else if (pWin->realized)
1616f7df2e56Smrg        wa->mapState = IsViewable;
161705b261ecSmrg    else
1618f7df2e56Smrg        wa->mapState = IsUnviewable;
161905b261ecSmrg
1620f7df2e56Smrg    wa->colormap = wColormap(pWin);
162105b261ecSmrg    wa->mapInstalled = (wa->colormap == None) ? xFalse
1622f7df2e56Smrg        : IsMapInstalled(wa->colormap, pWin);
162305b261ecSmrg
162405b261ecSmrg    wa->yourEventMask = EventMaskForClient(pWin, client);
1625f7df2e56Smrg    wa->allEventMasks = pWin->eventMask | wOtherEventMasks(pWin);
1626f7df2e56Smrg    wa->doNotPropagateMask = wDontPropagateMask(pWin);
162705b261ecSmrg    wa->class = pWin->drawable.class;
1628f7df2e56Smrg    wa->visualID = wVisual(pWin);
162905b261ecSmrg}
163005b261ecSmrg
1631637ac9abSmrgWindowPtr
163205b261ecSmrgMoveWindowInStack(WindowPtr pWin, WindowPtr pNextSib)
163305b261ecSmrg{
163405b261ecSmrg    WindowPtr pParent = pWin->parent;
1635f7df2e56Smrg    WindowPtr pFirstChange = pWin;      /* highest window where list changes */
1636f7df2e56Smrg
1637f7df2e56Smrg    if (pWin->nextSib != pNextSib) {
1638f7df2e56Smrg        WindowPtr pOldNextSib = pWin->nextSib;
1639f7df2e56Smrg
1640f7df2e56Smrg        if (!pNextSib) {        /* move to bottom */
1641f7df2e56Smrg            if (pParent->firstChild == pWin)
1642f7df2e56Smrg                pParent->firstChild = pWin->nextSib;
1643f7df2e56Smrg            /* if (pWin->nextSib) *//* is always True: pNextSib == NULL
1644f7df2e56Smrg             * and pWin->nextSib != pNextSib
1645f7df2e56Smrg             * therefore pWin->nextSib != NULL */
1646f7df2e56Smrg            pFirstChange = pWin->nextSib;
1647f7df2e56Smrg            pWin->nextSib->prevSib = pWin->prevSib;
1648f7df2e56Smrg            if (pWin->prevSib)
1649f7df2e56Smrg                pWin->prevSib->nextSib = pWin->nextSib;
1650f7df2e56Smrg            pParent->lastChild->nextSib = pWin;
1651f7df2e56Smrg            pWin->prevSib = pParent->lastChild;
1652f7df2e56Smrg            pWin->nextSib = NullWindow;
1653f7df2e56Smrg            pParent->lastChild = pWin;
1654f7df2e56Smrg        }
1655f7df2e56Smrg        else if (pParent->firstChild == pNextSib) {     /* move to top */
1656f7df2e56Smrg            pFirstChange = pWin;
1657f7df2e56Smrg            if (pParent->lastChild == pWin)
1658f7df2e56Smrg                pParent->lastChild = pWin->prevSib;
1659f7df2e56Smrg            if (pWin->nextSib)
1660f7df2e56Smrg                pWin->nextSib->prevSib = pWin->prevSib;
1661f7df2e56Smrg            if (pWin->prevSib)
1662f7df2e56Smrg                pWin->prevSib->nextSib = pWin->nextSib;
1663f7df2e56Smrg            pWin->nextSib = pParent->firstChild;
1664f7df2e56Smrg            pWin->prevSib = NULL;
1665f7df2e56Smrg            pNextSib->prevSib = pWin;
1666f7df2e56Smrg            pParent->firstChild = pWin;
1667f7df2e56Smrg        }
1668f7df2e56Smrg        else {                  /* move in middle of list */
166905b261ecSmrg
1670f7df2e56Smrg            WindowPtr pOldNext = pWin->nextSib;
1671f7df2e56Smrg
1672f7df2e56Smrg            pFirstChange = NullWindow;
1673f7df2e56Smrg            if (pParent->firstChild == pWin)
1674f7df2e56Smrg                pFirstChange = pParent->firstChild = pWin->nextSib;
1675f7df2e56Smrg            if (pParent->lastChild == pWin) {
1676f7df2e56Smrg                pFirstChange = pWin;
1677f7df2e56Smrg                pParent->lastChild = pWin->prevSib;
1678f7df2e56Smrg            }
1679f7df2e56Smrg            if (pWin->nextSib)
1680f7df2e56Smrg                pWin->nextSib->prevSib = pWin->prevSib;
1681f7df2e56Smrg            if (pWin->prevSib)
1682f7df2e56Smrg                pWin->prevSib->nextSib = pWin->nextSib;
1683f7df2e56Smrg            pWin->nextSib = pNextSib;
1684f7df2e56Smrg            pWin->prevSib = pNextSib->prevSib;
1685f7df2e56Smrg            if (pNextSib->prevSib)
1686f7df2e56Smrg                pNextSib->prevSib->nextSib = pWin;
1687f7df2e56Smrg            pNextSib->prevSib = pWin;
1688f7df2e56Smrg            if (!pFirstChange) {        /* do we know it yet? */
1689f7df2e56Smrg                pFirstChange = pParent->firstChild;     /* no, search from top */
1690f7df2e56Smrg                while ((pFirstChange != pWin) && (pFirstChange != pOldNext))
1691f7df2e56Smrg                    pFirstChange = pFirstChange->nextSib;
1692f7df2e56Smrg            }
1693f7df2e56Smrg        }
1694f7df2e56Smrg        if (pWin->drawable.pScreen->RestackWindow)
1695f7df2e56Smrg            (*pWin->drawable.pScreen->RestackWindow) (pWin, pOldNextSib);
169605b261ecSmrg    }
169705b261ecSmrg
169805b261ecSmrg#ifdef ROOTLESS
169905b261ecSmrg    /*
170005b261ecSmrg     * In rootless mode we can't optimize away window restacks.
170105b261ecSmrg     * There may be non-X windows around, so even if the window
170205b261ecSmrg     * is in the correct position from X's point of view,
170305b261ecSmrg     * the underlying window system may want to reorder it.
170405b261ecSmrg     */
170505b261ecSmrg    else if (pWin->drawable.pScreen->RestackWindow)
1706f7df2e56Smrg        (*pWin->drawable.pScreen->RestackWindow) (pWin, pWin->nextSib);
170705b261ecSmrg#endif
170805b261ecSmrg
17094202a189Smrg    return pFirstChange;
171005b261ecSmrg}
171105b261ecSmrg
1712637ac9abSmrgvoid
1713f7df2e56SmrgSetWinSize(WindowPtr pWin)
171405b261ecSmrg{
171505b261ecSmrg#ifdef COMPOSITE
1716f7df2e56Smrg    if (pWin->redirectDraw != RedirectDrawNone) {
1717f7df2e56Smrg        BoxRec box;
1718f7df2e56Smrg
1719f7df2e56Smrg        /*
1720f7df2e56Smrg         * Redirected clients get clip list equal to their
1721f7df2e56Smrg         * own geometry, not clipped to their parent
1722f7df2e56Smrg         */
1723f7df2e56Smrg        box.x1 = pWin->drawable.x;
1724f7df2e56Smrg        box.y1 = pWin->drawable.y;
1725f7df2e56Smrg        box.x2 = pWin->drawable.x + pWin->drawable.width;
1726f7df2e56Smrg        box.y2 = pWin->drawable.y + pWin->drawable.height;
1727f7df2e56Smrg        RegionReset(&pWin->winSize, &box);
172805b261ecSmrg    }
172905b261ecSmrg    else
173005b261ecSmrg#endif
1731f7df2e56Smrg        ClippedRegionFromBox(pWin->parent, &pWin->winSize,
1732f7df2e56Smrg                             pWin->drawable.x, pWin->drawable.y,
1733f7df2e56Smrg                             (int) pWin->drawable.width,
1734f7df2e56Smrg                             (int) pWin->drawable.height);
1735f7df2e56Smrg    if (wBoundingShape(pWin) || wClipShape(pWin)) {
1736f7df2e56Smrg        RegionTranslate(&pWin->winSize, -pWin->drawable.x, -pWin->drawable.y);
1737f7df2e56Smrg        if (wBoundingShape(pWin))
1738f7df2e56Smrg            RegionIntersect(&pWin->winSize, &pWin->winSize,
1739f7df2e56Smrg                            wBoundingShape(pWin));
1740f7df2e56Smrg        if (wClipShape(pWin))
1741f7df2e56Smrg            RegionIntersect(&pWin->winSize, &pWin->winSize, wClipShape(pWin));
1742f7df2e56Smrg        RegionTranslate(&pWin->winSize, pWin->drawable.x, pWin->drawable.y);
174305b261ecSmrg    }
174405b261ecSmrg}
174505b261ecSmrg
1746637ac9abSmrgvoid
1747f7df2e56SmrgSetBorderSize(WindowPtr pWin)
174805b261ecSmrg{
1749f7df2e56Smrg    int bw;
175005b261ecSmrg
1751f7df2e56Smrg    if (HasBorder(pWin)) {
1752f7df2e56Smrg        bw = wBorderWidth(pWin);
175305b261ecSmrg#ifdef COMPOSITE
1754f7df2e56Smrg        if (pWin->redirectDraw != RedirectDrawNone) {
1755f7df2e56Smrg            BoxRec box;
1756f7df2e56Smrg
1757f7df2e56Smrg            /*
1758f7df2e56Smrg             * Redirected clients get clip list equal to their
1759f7df2e56Smrg             * own geometry, not clipped to their parent
1760f7df2e56Smrg             */
1761f7df2e56Smrg            box.x1 = pWin->drawable.x - bw;
1762f7df2e56Smrg            box.y1 = pWin->drawable.y - bw;
1763f7df2e56Smrg            box.x2 = pWin->drawable.x + pWin->drawable.width + bw;
1764f7df2e56Smrg            box.y2 = pWin->drawable.y + pWin->drawable.height + bw;
1765f7df2e56Smrg            RegionReset(&pWin->borderSize, &box);
1766f7df2e56Smrg        }
1767f7df2e56Smrg        else
176805b261ecSmrg#endif
1769f7df2e56Smrg            ClippedRegionFromBox(pWin->parent, &pWin->borderSize,
1770f7df2e56Smrg                                 pWin->drawable.x - bw, pWin->drawable.y - bw,
1771f7df2e56Smrg                                 (int) (pWin->drawable.width + (bw << 1)),
1772f7df2e56Smrg                                 (int) (pWin->drawable.height + (bw << 1)));
1773f7df2e56Smrg        if (wBoundingShape(pWin)) {
1774f7df2e56Smrg            RegionTranslate(&pWin->borderSize, -pWin->drawable.x,
1775f7df2e56Smrg                            -pWin->drawable.y);
1776f7df2e56Smrg            RegionIntersect(&pWin->borderSize, &pWin->borderSize,
1777f7df2e56Smrg                            wBoundingShape(pWin));
1778f7df2e56Smrg            RegionTranslate(&pWin->borderSize, pWin->drawable.x,
1779f7df2e56Smrg                            pWin->drawable.y);
1780f7df2e56Smrg            RegionUnion(&pWin->borderSize, &pWin->borderSize, &pWin->winSize);
1781f7df2e56Smrg        }
1782f7df2e56Smrg    }
1783f7df2e56Smrg    else {
1784f7df2e56Smrg        RegionCopy(&pWin->borderSize, &pWin->winSize);
178505b261ecSmrg    }
178605b261ecSmrg}
178705b261ecSmrg
178805b261ecSmrg/**
178905b261ecSmrg *
179005b261ecSmrg *  \param x,y          new window position
179105b261ecSmrg *  \param oldx,oldy    old window position
179205b261ecSmrg *  \param destx,desty  position relative to gravity
179305b261ecSmrg */
179405b261ecSmrg
17954202a189Smrgvoid
1796f7df2e56SmrgGravityTranslate(int x, int y, int oldx, int oldy,
1797f7df2e56Smrg                 int dw, int dh, unsigned gravity, int *destx, int *desty)
179805b261ecSmrg{
179905b261ecSmrg    switch (gravity) {
180005b261ecSmrg    case NorthGravity:
1801f7df2e56Smrg        *destx = x + dw / 2;
1802f7df2e56Smrg        *desty = y;
1803f7df2e56Smrg        break;
180405b261ecSmrg    case NorthEastGravity:
1805f7df2e56Smrg        *destx = x + dw;
1806f7df2e56Smrg        *desty = y;
1807f7df2e56Smrg        break;
180805b261ecSmrg    case WestGravity:
1809f7df2e56Smrg        *destx = x;
1810f7df2e56Smrg        *desty = y + dh / 2;
1811f7df2e56Smrg        break;
181205b261ecSmrg    case CenterGravity:
1813f7df2e56Smrg        *destx = x + dw / 2;
1814f7df2e56Smrg        *desty = y + dh / 2;
1815f7df2e56Smrg        break;
181605b261ecSmrg    case EastGravity:
1817f7df2e56Smrg        *destx = x + dw;
1818f7df2e56Smrg        *desty = y + dh / 2;
1819f7df2e56Smrg        break;
182005b261ecSmrg    case SouthWestGravity:
1821f7df2e56Smrg        *destx = x;
1822f7df2e56Smrg        *desty = y + dh;
1823f7df2e56Smrg        break;
182405b261ecSmrg    case SouthGravity:
1825f7df2e56Smrg        *destx = x + dw / 2;
1826f7df2e56Smrg        *desty = y + dh;
1827f7df2e56Smrg        break;
182805b261ecSmrg    case SouthEastGravity:
1829f7df2e56Smrg        *destx = x + dw;
1830f7df2e56Smrg        *desty = y + dh;
1831f7df2e56Smrg        break;
183205b261ecSmrg    case StaticGravity:
1833f7df2e56Smrg        *destx = oldx;
1834f7df2e56Smrg        *desty = oldy;
1835f7df2e56Smrg        break;
183605b261ecSmrg    default:
1837f7df2e56Smrg        *destx = x;
1838f7df2e56Smrg        *desty = y;
1839f7df2e56Smrg        break;
184005b261ecSmrg    }
184105b261ecSmrg}
184205b261ecSmrg
184305b261ecSmrg/* XXX need to retile border on each window with ParentRelative origin */
1844637ac9abSmrgvoid
184505b261ecSmrgResizeChildrenWinSize(WindowPtr pWin, int dx, int dy, int dw, int dh)
184605b261ecSmrg{
184705b261ecSmrg    ScreenPtr pScreen;
184805b261ecSmrg    WindowPtr pSib, pChild;
184905b261ecSmrg    Bool resized = (dw || dh);
185005b261ecSmrg
185105b261ecSmrg    pScreen = pWin->drawable.pScreen;
185205b261ecSmrg
1853f7df2e56Smrg    for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib) {
1854f7df2e56Smrg        if (resized && (pSib->winGravity > NorthWestGravity)) {
1855f7df2e56Smrg            int cwsx, cwsy;
1856f7df2e56Smrg
1857f7df2e56Smrg            cwsx = pSib->origin.x;
1858f7df2e56Smrg            cwsy = pSib->origin.y;
1859f7df2e56Smrg            GravityTranslate(cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh,
1860f7df2e56Smrg                             pSib->winGravity, &cwsx, &cwsy);
1861f7df2e56Smrg            if (cwsx != pSib->origin.x || cwsy != pSib->origin.y) {
1862f7df2e56Smrg                xEvent event = {
1863f7df2e56Smrg                    .u.gravity.window = pSib->drawable.id,
1864f7df2e56Smrg                    .u.gravity.x = cwsx - wBorderWidth(pSib),
1865f7df2e56Smrg                    .u.gravity.y = cwsy - wBorderWidth(pSib)
1866f7df2e56Smrg                };
1867f7df2e56Smrg                event.u.u.type = GravityNotify;
1868f7df2e56Smrg                DeliverEvents(pSib, &event, 1, NullWindow);
1869f7df2e56Smrg                pSib->origin.x = cwsx;
1870f7df2e56Smrg                pSib->origin.y = cwsy;
1871f7df2e56Smrg            }
1872f7df2e56Smrg        }
1873f7df2e56Smrg        pSib->drawable.x = pWin->drawable.x + pSib->origin.x;
1874f7df2e56Smrg        pSib->drawable.y = pWin->drawable.y + pSib->origin.y;
1875f7df2e56Smrg        SetWinSize(pSib);
1876f7df2e56Smrg        SetBorderSize(pSib);
1877f7df2e56Smrg        (*pScreen->PositionWindow) (pSib, pSib->drawable.x, pSib->drawable.y);
1878f7df2e56Smrg
1879f7df2e56Smrg        if ((pChild = pSib->firstChild)) {
1880f7df2e56Smrg            while (1) {
1881f7df2e56Smrg                pChild->drawable.x = pChild->parent->drawable.x +
1882f7df2e56Smrg                    pChild->origin.x;
1883f7df2e56Smrg                pChild->drawable.y = pChild->parent->drawable.y +
1884f7df2e56Smrg                    pChild->origin.y;
1885f7df2e56Smrg                SetWinSize(pChild);
1886f7df2e56Smrg                SetBorderSize(pChild);
1887f7df2e56Smrg                (*pScreen->PositionWindow) (pChild,
1888f7df2e56Smrg                                            pChild->drawable.x,
1889f7df2e56Smrg                                            pChild->drawable.y);
1890f7df2e56Smrg                if (pChild->firstChild) {
1891f7df2e56Smrg                    pChild = pChild->firstChild;
1892f7df2e56Smrg                    continue;
1893f7df2e56Smrg                }
1894f7df2e56Smrg                while (!pChild->nextSib && (pChild != pSib))
1895f7df2e56Smrg                    pChild = pChild->parent;
1896f7df2e56Smrg                if (pChild == pSib)
1897f7df2e56Smrg                    break;
1898f7df2e56Smrg                pChild = pChild->nextSib;
1899f7df2e56Smrg            }
1900f7df2e56Smrg        }
190105b261ecSmrg    }
190205b261ecSmrg}
190305b261ecSmrg
190405b261ecSmrg#define GET_INT16(m, f) \
190505b261ecSmrg	if (m & mask) \
190605b261ecSmrg	  { \
190705b261ecSmrg	     f = (INT16) *pVlist;\
190805b261ecSmrg	    pVlist++; \
190905b261ecSmrg	 }
191005b261ecSmrg#define GET_CARD16(m, f) \
191105b261ecSmrg	if (m & mask) \
191205b261ecSmrg	 { \
191305b261ecSmrg	    f = (CARD16) *pVlist;\
191405b261ecSmrg	    pVlist++;\
191505b261ecSmrg	 }
191605b261ecSmrg
191705b261ecSmrg#define GET_CARD8(m, f) \
191805b261ecSmrg	if (m & mask) \
191905b261ecSmrg	 { \
192005b261ecSmrg	    f = (CARD8) *pVlist;\
192105b261ecSmrg	    pVlist++;\
192205b261ecSmrg	 }
192305b261ecSmrg
192405b261ecSmrg#define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight))
192505b261ecSmrg
192605b261ecSmrg/*
192705b261ecSmrg * IsSiblingAboveMe
1928f7df2e56Smrg *     returns Above if pSib above pMe in stack or Below otherwise
192905b261ecSmrg */
193005b261ecSmrg
193105b261ecSmrgstatic int
1932f7df2e56SmrgIsSiblingAboveMe(WindowPtr pMe, WindowPtr pSib)
193305b261ecSmrg{
193405b261ecSmrg    WindowPtr pWin;
193505b261ecSmrg
193605b261ecSmrg    pWin = pMe->parent->firstChild;
1937f7df2e56Smrg    while (pWin) {
1938f7df2e56Smrg        if (pWin == pSib)
1939f7df2e56Smrg            return Above;
1940f7df2e56Smrg        else if (pWin == pMe)
1941f7df2e56Smrg            return Below;
1942f7df2e56Smrg        pWin = pWin->nextSib;
194305b261ecSmrg    }
19444202a189Smrg    return Below;
194505b261ecSmrg}
194605b261ecSmrg
194705b261ecSmrgstatic BoxPtr
1948f7df2e56SmrgWindowExtents(WindowPtr pWin, BoxPtr pBox)
1949f7df2e56Smrg{
1950f7df2e56Smrg    pBox->x1 = pWin->drawable.x - wBorderWidth(pWin);
1951f7df2e56Smrg    pBox->y1 = pWin->drawable.y - wBorderWidth(pWin);
1952f7df2e56Smrg    pBox->x2 = pWin->drawable.x + (int) pWin->drawable.width
1953f7df2e56Smrg        + wBorderWidth(pWin);
1954f7df2e56Smrg    pBox->y2 = pWin->drawable.y + (int) pWin->drawable.height
1955f7df2e56Smrg        + wBorderWidth(pWin);
19564202a189Smrg    return pBox;
195705b261ecSmrg}
195805b261ecSmrg
1959f7df2e56Smrg#define IS_SHAPED(pWin)	(wBoundingShape (pWin) != NULL)
196005b261ecSmrg
196105b261ecSmrgstatic RegionPtr
1962f7df2e56SmrgMakeBoundingRegion(WindowPtr pWin, BoxPtr pBox)
196305b261ecSmrg{
1964f7df2e56Smrg    RegionPtr pRgn = RegionCreate(pBox, 1);
1965f7df2e56Smrg
1966f7df2e56Smrg    if (wBoundingShape(pWin)) {
1967f7df2e56Smrg        RegionTranslate(pRgn, -pWin->origin.x, -pWin->origin.y);
1968f7df2e56Smrg        RegionIntersect(pRgn, pRgn, wBoundingShape(pWin));
1969f7df2e56Smrg        RegionTranslate(pRgn, pWin->origin.x, pWin->origin.y);
197005b261ecSmrg    }
197105b261ecSmrg    return pRgn;
197205b261ecSmrg}
197305b261ecSmrg
197405b261ecSmrgstatic Bool
1975f7df2e56SmrgShapeOverlap(WindowPtr pWin, BoxPtr pWinBox, WindowPtr pSib, BoxPtr pSibBox)
197605b261ecSmrg{
1977f7df2e56Smrg    RegionPtr pWinRgn, pSibRgn;
1978f7df2e56Smrg    Bool ret;
197905b261ecSmrg
198005b261ecSmrg    if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib))
1981f7df2e56Smrg        return TRUE;
1982f7df2e56Smrg    pWinRgn = MakeBoundingRegion(pWin, pWinBox);
1983f7df2e56Smrg    pSibRgn = MakeBoundingRegion(pSib, pSibBox);
19844202a189Smrg    RegionIntersect(pWinRgn, pWinRgn, pSibRgn);
19854202a189Smrg    ret = RegionNotEmpty(pWinRgn);
19864202a189Smrg    RegionDestroy(pWinRgn);
19874202a189Smrg    RegionDestroy(pSibRgn);
198805b261ecSmrg    return ret;
198905b261ecSmrg}
199005b261ecSmrg
199105b261ecSmrgstatic Bool
1992f7df2e56SmrgAnyWindowOverlapsMe(WindowPtr pWin, WindowPtr pHead, BoxPtr box)
199305b261ecSmrg{
199405b261ecSmrg    WindowPtr pSib;
199505b261ecSmrg    BoxRec sboxrec;
199605b261ecSmrg    BoxPtr sbox;
199705b261ecSmrg
1998f7df2e56Smrg    for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib) {
1999f7df2e56Smrg        if (pSib->mapped) {
2000f7df2e56Smrg            sbox = WindowExtents(pSib, &sboxrec);
2001f7df2e56Smrg            if (BOXES_OVERLAP(sbox, box)
2002f7df2e56Smrg                && ShapeOverlap(pWin, box, pSib, sbox))
2003f7df2e56Smrg                return TRUE;
2004f7df2e56Smrg        }
200505b261ecSmrg    }
20064202a189Smrg    return FALSE;
200705b261ecSmrg}
200805b261ecSmrg
200905b261ecSmrgstatic Bool
2010f7df2e56SmrgIOverlapAnyWindow(WindowPtr pWin, BoxPtr box)
201105b261ecSmrg{
201205b261ecSmrg    WindowPtr pSib;
201305b261ecSmrg    BoxRec sboxrec;
201405b261ecSmrg    BoxPtr sbox;
201505b261ecSmrg
2016f7df2e56Smrg    for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib) {
2017f7df2e56Smrg        if (pSib->mapped) {
2018f7df2e56Smrg            sbox = WindowExtents(pSib, &sboxrec);
2019f7df2e56Smrg            if (BOXES_OVERLAP(sbox, box)
2020f7df2e56Smrg                && ShapeOverlap(pWin, box, pSib, sbox))
2021f7df2e56Smrg                return TRUE;
2022f7df2e56Smrg        }
202305b261ecSmrg    }
20244202a189Smrg    return FALSE;
202505b261ecSmrg}
202605b261ecSmrg
202705b261ecSmrg/*
2028f7df2e56Smrg *   WhereDoIGoInTheStack()
202905b261ecSmrg *	  Given pWin and pSib and the relationshipe smode, return
203005b261ecSmrg *	  the window that pWin should go ABOVE.
203105b261ecSmrg *	  If a pSib is specified:
203205b261ecSmrg *	      Above:  pWin is placed just above pSib
203305b261ecSmrg *	      Below:  pWin is placed just below pSib
203405b261ecSmrg *	      TopIf:  if pSib occludes pWin, then pWin is placed
203505b261ecSmrg *		      at the top of the stack
2036f7df2e56Smrg *	      BottomIf:	 if pWin occludes pSib, then pWin is
203705b261ecSmrg *			 placed at the bottom of the stack
203805b261ecSmrg *	      Opposite: if pSib occludes pWin, then pWin is placed at the
203905b261ecSmrg *			top of the stack, else if pWin occludes pSib, then
204005b261ecSmrg *			pWin is placed at the bottom of the stack
204105b261ecSmrg *
204205b261ecSmrg *	  If pSib is NULL:
204305b261ecSmrg *	      Above:  pWin is placed at the top of the stack
204405b261ecSmrg *	      Below:  pWin is placed at the bottom of the stack
204505b261ecSmrg *	      TopIf:  if any sibling occludes pWin, then pWin is placed at
204605b261ecSmrg *		      the top of the stack
204705b261ecSmrg *	      BottomIf: if pWin occludes any sibline, then pWin is placed at
204805b261ecSmrg *			the bottom of the stack
204905b261ecSmrg *	      Opposite: if any sibling occludes pWin, then pWin is placed at
205005b261ecSmrg *			the top of the stack, else if pWin occludes any
205105b261ecSmrg *			sibling, then pWin is placed at the bottom of the stack
205205b261ecSmrg *
205305b261ecSmrg */
205405b261ecSmrg
205505b261ecSmrgstatic WindowPtr
2056f7df2e56SmrgWhereDoIGoInTheStack(WindowPtr pWin,
2057f7df2e56Smrg                     WindowPtr pSib,
2058f7df2e56Smrg                     short x,
2059f7df2e56Smrg                     short y, unsigned short w, unsigned short h, int smode)
206005b261ecSmrg{
206105b261ecSmrg    BoxRec box;
206205b261ecSmrg    WindowPtr pHead, pFirst;
206305b261ecSmrg
2064f7df2e56Smrg    if ((pWin == pWin->parent->firstChild) && (pWin == pWin->parent->lastChild))
2065f7df2e56Smrg        return NULL;
206605b261ecSmrg    pHead = RealChildHead(pWin->parent);
206705b261ecSmrg    pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild;
206805b261ecSmrg    box.x1 = x;
206905b261ecSmrg    box.y1 = y;
2070f7df2e56Smrg    box.x2 = x + (int) w;
2071f7df2e56Smrg    box.y2 = y + (int) h;
2072f7df2e56Smrg    switch (smode) {
2073f7df2e56Smrg    case Above:
2074f7df2e56Smrg        if (pSib)
2075f7df2e56Smrg            return pSib;
2076f7df2e56Smrg        else if (pWin == pFirst)
2077f7df2e56Smrg            return pWin->nextSib;
2078f7df2e56Smrg        else
2079f7df2e56Smrg            return pFirst;
2080f7df2e56Smrg    case Below:
2081f7df2e56Smrg        if (pSib)
2082f7df2e56Smrg            if (pSib->nextSib != pWin)
2083f7df2e56Smrg                return pSib->nextSib;
2084f7df2e56Smrg            else
2085f7df2e56Smrg                return pWin->nextSib;
2086f7df2e56Smrg        else
2087f7df2e56Smrg            return NullWindow;
2088f7df2e56Smrg    case TopIf:
2089f7df2e56Smrg        if ((!pWin->mapped || (pSib && !pSib->mapped)))
2090f7df2e56Smrg            return pWin->nextSib;
2091f7df2e56Smrg        else if (pSib) {
2092f7df2e56Smrg            if ((IsSiblingAboveMe(pWin, pSib) == Above) &&
2093f7df2e56Smrg                (RegionContainsRect(&pSib->borderSize, &box) != rgnOUT))
2094f7df2e56Smrg                return pFirst;
2095f7df2e56Smrg            else
2096f7df2e56Smrg                return pWin->nextSib;
2097f7df2e56Smrg        }
2098f7df2e56Smrg        else if (AnyWindowOverlapsMe(pWin, pHead, &box))
2099f7df2e56Smrg            return pFirst;
2100f7df2e56Smrg        else
2101f7df2e56Smrg            return pWin->nextSib;
2102f7df2e56Smrg    case BottomIf:
2103f7df2e56Smrg        if ((!pWin->mapped || (pSib && !pSib->mapped)))
2104f7df2e56Smrg            return pWin->nextSib;
2105f7df2e56Smrg        else if (pSib) {
2106f7df2e56Smrg            if ((IsSiblingAboveMe(pWin, pSib) == Below) &&
2107f7df2e56Smrg                (RegionContainsRect(&pSib->borderSize, &box) != rgnOUT))
2108f7df2e56Smrg                return NullWindow;
2109f7df2e56Smrg            else
2110f7df2e56Smrg                return pWin->nextSib;
2111f7df2e56Smrg        }
2112f7df2e56Smrg        else if (IOverlapAnyWindow(pWin, &box))
2113f7df2e56Smrg            return NullWindow;
2114f7df2e56Smrg        else
2115f7df2e56Smrg            return pWin->nextSib;
2116f7df2e56Smrg    case Opposite:
2117f7df2e56Smrg        if ((!pWin->mapped || (pSib && !pSib->mapped)))
2118f7df2e56Smrg            return pWin->nextSib;
2119f7df2e56Smrg        else if (pSib) {
2120f7df2e56Smrg            if (RegionContainsRect(&pSib->borderSize, &box) != rgnOUT) {
2121f7df2e56Smrg                if (IsSiblingAboveMe(pWin, pSib) == Above)
2122f7df2e56Smrg                    return pFirst;
2123f7df2e56Smrg                else
2124f7df2e56Smrg                    return NullWindow;
2125f7df2e56Smrg            }
2126f7df2e56Smrg            else
2127f7df2e56Smrg                return pWin->nextSib;
2128f7df2e56Smrg        }
2129f7df2e56Smrg        else if (AnyWindowOverlapsMe(pWin, pHead, &box)) {
2130f7df2e56Smrg            /* If I'm occluded, I can't possibly be the first child
2131f7df2e56Smrg             * if (pWin == pWin->parent->firstChild)
2132f7df2e56Smrg             *    return pWin->nextSib;
2133f7df2e56Smrg             */
2134f7df2e56Smrg            return pFirst;
2135f7df2e56Smrg        }
2136f7df2e56Smrg        else if (IOverlapAnyWindow(pWin, &box))
2137f7df2e56Smrg            return NullWindow;
2138f7df2e56Smrg        else
2139f7df2e56Smrg            return pWin->nextSib;
2140f7df2e56Smrg    default:
214105b261ecSmrg    {
2142f7df2e56Smrg        /* should never happen; make something up. */
2143f7df2e56Smrg        return pWin->nextSib;
2144f7df2e56Smrg    }
214505b261ecSmrg    }
214605b261ecSmrg}
214705b261ecSmrg
214805b261ecSmrgstatic void
2149f7df2e56SmrgReflectStackChange(WindowPtr pWin, WindowPtr pSib, VTKind kind)
215005b261ecSmrg{
215105b261ecSmrg/* Note that pSib might be NULL */
215205b261ecSmrg
2153f7df2e56Smrg    Bool WasViewable = (Bool) pWin->viewable;
215405b261ecSmrg    Bool anyMarked;
215505b261ecSmrg    WindowPtr pFirstChange;
2156f7df2e56Smrg    WindowPtr pLayerWin;
215705b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
215805b261ecSmrg
215905b261ecSmrg    /* if this is a root window, can't be restacked */
216005b261ecSmrg    if (!pWin->parent)
2161f7df2e56Smrg        return;
216205b261ecSmrg
216305b261ecSmrg    pFirstChange = MoveWindowInStack(pWin, pSib);
216405b261ecSmrg
2165f7df2e56Smrg    if (WasViewable) {
2166f7df2e56Smrg        anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pFirstChange,
2167f7df2e56Smrg                                                       &pLayerWin);
2168f7df2e56Smrg        if (pLayerWin != pWin)
2169f7df2e56Smrg            pFirstChange = pLayerWin;
2170f7df2e56Smrg        if (anyMarked) {
2171f7df2e56Smrg            (*pScreen->ValidateTree) (pLayerWin->parent, pFirstChange, kind);
2172f7df2e56Smrg            (*pScreen->HandleExposures) (pLayerWin->parent);
2173f7df2e56Smrg            if (pWin->drawable.pScreen->PostValidateTree)
2174f7df2e56Smrg                (*pScreen->PostValidateTree) (pLayerWin->parent, pFirstChange,
2175f7df2e56Smrg                                              kind);
2176f7df2e56Smrg        }
217705b261ecSmrg    }
217805b261ecSmrg    if (pWin->realized)
2179f7df2e56Smrg        WindowsRestructured();
218005b261ecSmrg}
218105b261ecSmrg
218205b261ecSmrg/*****
218305b261ecSmrg * ConfigureWindow
218405b261ecSmrg *****/
218505b261ecSmrg
218605b261ecSmrgint
218705b261ecSmrgConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client)
218805b261ecSmrg{
218905b261ecSmrg#define RESTACK_WIN    0
219005b261ecSmrg#define MOVE_WIN       1
219105b261ecSmrg#define RESIZE_WIN     2
219205b261ecSmrg#define REBORDER_WIN   3
219305b261ecSmrg    WindowPtr pSib = NullWindow;
219405b261ecSmrg    WindowPtr pParent = pWin->parent;
219505b261ecSmrg    Window sibwid = 0;
219605b261ecSmrg    Mask index2, tmask;
219705b261ecSmrg    XID *pVlist;
2198f7df2e56Smrg    short x, y, beforeX, beforeY;
219905b261ecSmrg    unsigned short w = pWin->drawable.width,
2200f7df2e56Smrg        h = pWin->drawable.height, bw = pWin->borderWidth;
2201637ac9abSmrg    int rc, action, smode = Above;
220205b261ecSmrg
2203f7df2e56Smrg    if ((pWin->drawable.class == InputOnly) && (mask & CWBorderWidth))
2204f7df2e56Smrg        return BadMatch;
220505b261ecSmrg
220605b261ecSmrg    if ((mask & CWSibling) && !(mask & CWStackMode))
2207f7df2e56Smrg        return BadMatch;
220805b261ecSmrg
220905b261ecSmrg    pVlist = vlist;
221005b261ecSmrg
2211f7df2e56Smrg    if (pParent) {
2212f7df2e56Smrg        x = pWin->drawable.x - pParent->drawable.x - (int) bw;
2213f7df2e56Smrg        y = pWin->drawable.y - pParent->drawable.y - (int) bw;
221405b261ecSmrg    }
2215f7df2e56Smrg    else {
2216f7df2e56Smrg        x = pWin->drawable.x;
2217f7df2e56Smrg        y = pWin->drawable.y;
221805b261ecSmrg    }
221905b261ecSmrg    beforeX = x;
222005b261ecSmrg    beforeY = y;
2221f7df2e56Smrg    action = RESTACK_WIN;
2222f7df2e56Smrg    if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth)))) {
2223f7df2e56Smrg        GET_INT16(CWX, x);
2224f7df2e56Smrg        GET_INT16(CWY, y);
2225f7df2e56Smrg        action = MOVE_WIN;
2226f7df2e56Smrg    }
2227f7df2e56Smrg    /* or should be resized */
2228f7df2e56Smrg    else if (mask & (CWX | CWY | CWWidth | CWHeight)) {
2229f7df2e56Smrg        GET_INT16(CWX, x);
2230f7df2e56Smrg        GET_INT16(CWY, y);
2231f7df2e56Smrg        GET_CARD16(CWWidth, w);
2232f7df2e56Smrg        GET_CARD16(CWHeight, h);
2233f7df2e56Smrg        if (!w || !h) {
2234f7df2e56Smrg            client->errorValue = 0;
2235f7df2e56Smrg            return BadValue;
2236f7df2e56Smrg        }
2237f7df2e56Smrg        action = RESIZE_WIN;
223805b261ecSmrg    }
223905b261ecSmrg    tmask = mask & ~ChangeMask;
2240f7df2e56Smrg    while (tmask) {
2241f7df2e56Smrg        index2 = (Mask) lowbit(tmask);
2242f7df2e56Smrg        tmask &= ~index2;
2243f7df2e56Smrg        switch (index2) {
2244f7df2e56Smrg        case CWBorderWidth:
2245f7df2e56Smrg            GET_CARD16(CWBorderWidth, bw);
2246f7df2e56Smrg            break;
2247f7df2e56Smrg        case CWSibling:
2248f7df2e56Smrg            sibwid = (Window) *pVlist;
2249f7df2e56Smrg            pVlist++;
2250f7df2e56Smrg            rc = dixLookupWindow(&pSib, sibwid, client, DixGetAttrAccess);
2251f7df2e56Smrg            if (rc != Success) {
2252f7df2e56Smrg                client->errorValue = sibwid;
2253f7df2e56Smrg                return rc;
2254f7df2e56Smrg            }
2255f7df2e56Smrg            if (pSib->parent != pParent)
2256f7df2e56Smrg                return BadMatch;
2257f7df2e56Smrg            if (pSib == pWin)
2258f7df2e56Smrg                return BadMatch;
2259f7df2e56Smrg            break;
2260f7df2e56Smrg        case CWStackMode:
2261f7df2e56Smrg            GET_CARD8(CWStackMode, smode);
2262f7df2e56Smrg            if ((smode != TopIf) && (smode != BottomIf) &&
2263f7df2e56Smrg                (smode != Opposite) && (smode != Above) && (smode != Below)) {
2264f7df2e56Smrg                client->errorValue = smode;
2265f7df2e56Smrg                return BadValue;
2266f7df2e56Smrg            }
2267f7df2e56Smrg            break;
2268f7df2e56Smrg        default:
2269f7df2e56Smrg            client->errorValue = mask;
2270f7df2e56Smrg            return BadValue;
2271f7df2e56Smrg        }
2272f7df2e56Smrg    }
2273f7df2e56Smrg    /* root really can't be reconfigured, so just return */
227405b261ecSmrg    if (!pParent)
2275f7df2e56Smrg        return Success;
227605b261ecSmrg
22775a112b11Smrg    /* Figure out if the window should be moved.  Doesn't
22785a112b11Smrg       make the changes to the window if event sent. */
227905b261ecSmrg
228005b261ecSmrg    if (mask & CWStackMode)
2281f7df2e56Smrg        pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x,
2282f7df2e56Smrg                                    pParent->drawable.y + y,
2283f7df2e56Smrg                                    w + (bw << 1), h + (bw << 1), smode);
228405b261ecSmrg    else
2285f7df2e56Smrg        pSib = pWin->nextSib;
2286f7df2e56Smrg
2287f7df2e56Smrg    if ((!pWin->overrideRedirect) && (RedirectSend(pParent))) {
2288f7df2e56Smrg        xEvent event = {
2289f7df2e56Smrg            .u.configureRequest.window = pWin->drawable.id,
2290f7df2e56Smrg            .u.configureRequest.sibling = (mask & CWSibling) ? sibwid : None,
2291f7df2e56Smrg            .u.configureRequest.x = x,
2292f7df2e56Smrg            .u.configureRequest.y = y,
2293f7df2e56Smrg            .u.configureRequest.width = w,
2294f7df2e56Smrg            .u.configureRequest.height = h,
2295f7df2e56Smrg            .u.configureRequest.borderWidth = bw,
2296f7df2e56Smrg            .u.configureRequest.valueMask = mask,
2297f7df2e56Smrg            .u.configureRequest.parent = pParent->drawable.id
2298f7df2e56Smrg        };
2299f7df2e56Smrg        event.u.u.type = ConfigureRequest;
2300f7df2e56Smrg        event.u.u.detail = (mask & CWStackMode) ? smode : Above;
230105b261ecSmrg#ifdef PANORAMIX
2302f7df2e56Smrg        if (!noPanoramiXExtension && (!pParent || !pParent->parent)) {
23034202a189Smrg            event.u.configureRequest.x += screenInfo.screens[0]->x;
23044202a189Smrg            event.u.configureRequest.y += screenInfo.screens[0]->y;
2305f7df2e56Smrg        }
230605b261ecSmrg#endif
2307f7df2e56Smrg        if (MaybeDeliverEventsToClient(pParent, &event, 1,
2308f7df2e56Smrg                                       SubstructureRedirectMask, client) == 1)
2309f7df2e56Smrg            return Success;
231005b261ecSmrg    }
2311f7df2e56Smrg    if (action == RESIZE_WIN) {
2312f7df2e56Smrg        Bool size_change = (w != pWin->drawable.width)
2313f7df2e56Smrg            || (h != pWin->drawable.height);
2314f7df2e56Smrg
2315f7df2e56Smrg        if (size_change &&
2316f7df2e56Smrg            ((pWin->eventMask | wOtherEventMasks(pWin)) & ResizeRedirectMask)) {
2317f7df2e56Smrg            xEvent eventT = {
2318f7df2e56Smrg                .u.resizeRequest.window = pWin->drawable.id,
2319f7df2e56Smrg                .u.resizeRequest.width = w,
2320f7df2e56Smrg                .u.resizeRequest.height = h
2321f7df2e56Smrg            };
2322f7df2e56Smrg            eventT.u.u.type = ResizeRequest;
2323f7df2e56Smrg            if (MaybeDeliverEventsToClient(pWin, &eventT, 1,
2324f7df2e56Smrg                                           ResizeRedirectMask, client) == 1) {
2325f7df2e56Smrg                /* if event is delivered, leave the actual size alone. */
2326f7df2e56Smrg                w = pWin->drawable.width;
2327f7df2e56Smrg                h = pWin->drawable.height;
2328f7df2e56Smrg                size_change = FALSE;
2329f7df2e56Smrg            }
2330f7df2e56Smrg        }
2331f7df2e56Smrg        if (!size_change) {
2332f7df2e56Smrg            if (mask & (CWX | CWY))
2333f7df2e56Smrg                action = MOVE_WIN;
2334f7df2e56Smrg            else if (mask & (CWStackMode | CWBorderWidth))
2335f7df2e56Smrg                action = RESTACK_WIN;
2336f7df2e56Smrg            else                /* really nothing to do */
2337f7df2e56Smrg                return (Success);
2338f7df2e56Smrg        }
233905b261ecSmrg    }
234005b261ecSmrg
234105b261ecSmrg    if (action == RESIZE_WIN)
2342f7df2e56Smrg        /* we've already checked whether there's really a size change */
2343f7df2e56Smrg        goto ActuallyDoSomething;
234405b261ecSmrg    if ((mask & CWX) && (x != beforeX))
2345f7df2e56Smrg        goto ActuallyDoSomething;
234605b261ecSmrg    if ((mask & CWY) && (y != beforeY))
2347f7df2e56Smrg        goto ActuallyDoSomething;
2348f7df2e56Smrg    if ((mask & CWBorderWidth) && (bw != wBorderWidth(pWin)))
2349f7df2e56Smrg        goto ActuallyDoSomething;
2350f7df2e56Smrg    if (mask & CWStackMode) {
235105b261ecSmrg#ifndef ROOTLESS
235205b261ecSmrg        /* See above for why we always reorder in rootless mode. */
2353f7df2e56Smrg        if (pWin->nextSib != pSib)
235405b261ecSmrg#endif
2355f7df2e56Smrg            goto ActuallyDoSomething;
235605b261ecSmrg    }
23574202a189Smrg    return Success;
235805b261ecSmrg
2359f7df2e56Smrg ActuallyDoSomething:
2360f7df2e56Smrg    if (pWin->drawable.pScreen->ConfigNotify) {
2361f7df2e56Smrg        int ret;
2362f7df2e56Smrg
2363f7df2e56Smrg        ret =
2364f7df2e56Smrg            (*pWin->drawable.pScreen->ConfigNotify) (pWin, x, y, w, h, bw,
2365f7df2e56Smrg                                                     pSib);
2366f7df2e56Smrg        if (ret) {
2367f7df2e56Smrg            client->errorValue = 0;
2368f7df2e56Smrg            return ret;
2369f7df2e56Smrg        }
23704202a189Smrg    }
23714202a189Smrg
2372f7df2e56Smrg    if (SubStrSend(pWin, pParent)) {
2373f7df2e56Smrg        xEvent event = {
2374f7df2e56Smrg            .u.configureNotify.window = pWin->drawable.id,
2375f7df2e56Smrg            .u.configureNotify.aboveSibling = pSib ? pSib->drawable.id : None,
2376f7df2e56Smrg            .u.configureNotify.x = x,
2377f7df2e56Smrg            .u.configureNotify.y = y,
2378f7df2e56Smrg            .u.configureNotify.width = w,
2379f7df2e56Smrg            .u.configureNotify.height = h,
2380f7df2e56Smrg            .u.configureNotify.borderWidth = bw,
2381f7df2e56Smrg            .u.configureNotify.override = pWin->overrideRedirect
2382f7df2e56Smrg        };
2383f7df2e56Smrg        event.u.u.type = ConfigureNotify;
238405b261ecSmrg#ifdef PANORAMIX
2385f7df2e56Smrg        if (!noPanoramiXExtension && (!pParent || !pParent->parent)) {
2386f7df2e56Smrg            event.u.configureNotify.x += screenInfo.screens[0]->x;
2387f7df2e56Smrg            event.u.configureNotify.y += screenInfo.screens[0]->y;
2388f7df2e56Smrg        }
238905b261ecSmrg#endif
2390f7df2e56Smrg        DeliverEvents(pWin, &event, 1, NullWindow);
239105b261ecSmrg    }
2392f7df2e56Smrg    if (mask & CWBorderWidth) {
2393f7df2e56Smrg        if (action == RESTACK_WIN) {
2394f7df2e56Smrg            action = MOVE_WIN;
2395f7df2e56Smrg            pWin->borderWidth = bw;
2396f7df2e56Smrg        }
2397f7df2e56Smrg        else if ((action == MOVE_WIN) &&
2398f7df2e56Smrg                 (beforeX + wBorderWidth(pWin) == x + (int) bw) &&
2399f7df2e56Smrg                 (beforeY + wBorderWidth(pWin) == y + (int) bw)) {
2400f7df2e56Smrg            action = REBORDER_WIN;
2401f7df2e56Smrg            (*pWin->drawable.pScreen->ChangeBorderWidth) (pWin, bw);
2402f7df2e56Smrg        }
2403f7df2e56Smrg        else
2404f7df2e56Smrg            pWin->borderWidth = bw;
240505b261ecSmrg    }
240605b261ecSmrg    if (action == MOVE_WIN)
2407f7df2e56Smrg        (*pWin->drawable.pScreen->MoveWindow) (pWin, x, y, pSib,
2408f7df2e56Smrg                                               (mask & CWBorderWidth) ? VTOther
2409f7df2e56Smrg                                               : VTMove);
241005b261ecSmrg    else if (action == RESIZE_WIN)
2411f7df2e56Smrg        (*pWin->drawable.pScreen->ResizeWindow) (pWin, x, y, w, h, pSib);
241205b261ecSmrg    else if (mask & CWStackMode)
2413f7df2e56Smrg        ReflectStackChange(pWin, pSib, VTOther);
241405b261ecSmrg
241505b261ecSmrg    if (action != RESTACK_WIN)
2416f7df2e56Smrg        CheckCursorConfinement(pWin);
24174202a189Smrg    return Success;
241805b261ecSmrg#undef RESTACK_WIN
241905b261ecSmrg#undef MOVE_WIN
242005b261ecSmrg#undef RESIZE_WIN
242105b261ecSmrg#undef REBORDER_WIN
242205b261ecSmrg}
242305b261ecSmrg
242405b261ecSmrg/******
242505b261ecSmrg *
242605b261ecSmrg * CirculateWindow
242705b261ecSmrg *    For RaiseLowest, raises the lowest mapped child (if any) that is
242805b261ecSmrg *    obscured by another child to the top of the stack.  For LowerHighest,
242905b261ecSmrg *    lowers the highest mapped child (if any) that is obscuring another
2430f7df2e56Smrg *    child to the bottom of the stack.	 Exposure processing is performed
243105b261ecSmrg *
243205b261ecSmrg ******/
243305b261ecSmrg
243405b261ecSmrgint
243505b261ecSmrgCirculateWindow(WindowPtr pParent, int direction, ClientPtr client)
243605b261ecSmrg{
243705b261ecSmrg    WindowPtr pWin, pHead, pFirst;
243805b261ecSmrg    xEvent event;
243905b261ecSmrg    BoxRec box;
244005b261ecSmrg
244105b261ecSmrg    pHead = RealChildHead(pParent);
244205b261ecSmrg    pFirst = pHead ? pHead->nextSib : pParent->firstChild;
2443f7df2e56Smrg    if (direction == RaiseLowest) {
2444f7df2e56Smrg        for (pWin = pParent->lastChild;
2445f7df2e56Smrg             (pWin != pHead) &&
2446f7df2e56Smrg             !(pWin->mapped &&
2447f7df2e56Smrg               AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box)));
2448f7df2e56Smrg             pWin = pWin->prevSib);
2449f7df2e56Smrg        if (pWin == pHead)
2450f7df2e56Smrg            return Success;
2451f7df2e56Smrg    }
2452f7df2e56Smrg    else {
2453f7df2e56Smrg        for (pWin = pFirst;
2454f7df2e56Smrg             pWin &&
2455f7df2e56Smrg             !(pWin->mapped &&
2456f7df2e56Smrg               IOverlapAnyWindow(pWin, WindowExtents(pWin, &box)));
2457f7df2e56Smrg             pWin = pWin->nextSib);
2458f7df2e56Smrg        if (!pWin)
2459f7df2e56Smrg            return Success;
246005b261ecSmrg    }
246105b261ecSmrg
2462f7df2e56Smrg    event = (xEvent) {
2463f7df2e56Smrg        .u.circulate.window = pWin->drawable.id,
2464f7df2e56Smrg        .u.circulate.parent = pParent->drawable.id,
2465f7df2e56Smrg        .u.circulate.event = pParent->drawable.id,
2466f7df2e56Smrg        .u.circulate.place = (direction == RaiseLowest) ?
2467f7df2e56Smrg                              PlaceOnTop : PlaceOnBottom,
2468f7df2e56Smrg    };
2469f7df2e56Smrg
2470f7df2e56Smrg    if (RedirectSend(pParent)) {
2471f7df2e56Smrg        event.u.u.type = CirculateRequest;
2472f7df2e56Smrg        if (MaybeDeliverEventsToClient(pParent, &event, 1,
2473f7df2e56Smrg                                       SubstructureRedirectMask, client) == 1)
2474f7df2e56Smrg            return Success;
247505b261ecSmrg    }
247605b261ecSmrg
247705b261ecSmrg    event.u.u.type = CirculateNotify;
247805b261ecSmrg    DeliverEvents(pWin, &event, 1, NullWindow);
247905b261ecSmrg    ReflectStackChange(pWin,
2480f7df2e56Smrg                       (direction == RaiseLowest) ? pFirst : NullWindow,
2481f7df2e56Smrg                       VTStack);
248205b261ecSmrg
24834202a189Smrg    return Success;
248405b261ecSmrg}
248505b261ecSmrg
248605b261ecSmrgstatic int
2487f7df2e56SmrgCompareWIDs(WindowPtr pWin, void *value)
2488f7df2e56Smrg{                               /* must conform to VisitWindowProcPtr */
2489f7df2e56Smrg    Window *wid = (Window *) value;
249005b261ecSmrg
249105b261ecSmrg    if (pWin->drawable.id == *wid)
2492f7df2e56Smrg        return WT_STOPWALKING;
249305b261ecSmrg    else
2494f7df2e56Smrg        return WT_WALKCHILDREN;
249505b261ecSmrg}
249605b261ecSmrg
249705b261ecSmrg/*****
249805b261ecSmrg *  ReparentWindow
249905b261ecSmrg *****/
250005b261ecSmrg
250105b261ecSmrgint
250205b261ecSmrgReparentWindow(WindowPtr pWin, WindowPtr pParent,
250305b261ecSmrg               int x, int y, ClientPtr client)
250405b261ecSmrg{
250505b261ecSmrg    WindowPtr pPrev, pPriorParent;
2506f7df2e56Smrg    Bool WasMapped = (Bool) (pWin->mapped);
250705b261ecSmrg    xEvent event;
2508f7df2e56Smrg    int bw = wBorderWidth(pWin);
250905b261ecSmrg    ScreenPtr pScreen;
251005b261ecSmrg
251105b261ecSmrg    pScreen = pWin->drawable.pScreen;
2512f7df2e56Smrg    if (TraverseTree(pWin, CompareWIDs, (void *) &pParent->drawable.id) ==
2513f7df2e56Smrg        WT_STOPWALKING)
2514f7df2e56Smrg        return BadMatch;
251505b261ecSmrg    if (!MakeWindowOptional(pWin))
2516f7df2e56Smrg        return BadAlloc;
251705b261ecSmrg
251805b261ecSmrg    if (WasMapped)
2519f7df2e56Smrg        UnmapWindow(pWin, FALSE);
2520f7df2e56Smrg
2521f7df2e56Smrg    event = (xEvent) {
2522f7df2e56Smrg        .u.reparent.window = pWin->drawable.id,
2523f7df2e56Smrg        .u.reparent.parent = pParent->drawable.id,
2524f7df2e56Smrg        .u.reparent.x = x,
2525f7df2e56Smrg        .u.reparent.y = y,
2526f7df2e56Smrg        .u.reparent.override = pWin->overrideRedirect
2527f7df2e56Smrg    };
252805b261ecSmrg    event.u.u.type = ReparentNotify;
252905b261ecSmrg#ifdef PANORAMIX
2530f7df2e56Smrg    if (!noPanoramiXExtension && !pParent->parent) {
2531f7df2e56Smrg        event.u.reparent.x += screenInfo.screens[0]->x;
2532f7df2e56Smrg        event.u.reparent.y += screenInfo.screens[0]->y;
253305b261ecSmrg    }
253405b261ecSmrg#endif
253505b261ecSmrg    DeliverEvents(pWin, &event, 1, pParent);
253605b261ecSmrg
253705b261ecSmrg    /* take out of sibling chain */
253805b261ecSmrg
253905b261ecSmrg    pPriorParent = pPrev = pWin->parent;
254005b261ecSmrg    if (pPrev->firstChild == pWin)
2541f7df2e56Smrg        pPrev->firstChild = pWin->nextSib;
254205b261ecSmrg    if (pPrev->lastChild == pWin)
2543f7df2e56Smrg        pPrev->lastChild = pWin->prevSib;
254405b261ecSmrg
254505b261ecSmrg    if (pWin->nextSib)
2546f7df2e56Smrg        pWin->nextSib->prevSib = pWin->prevSib;
254705b261ecSmrg    if (pWin->prevSib)
2548f7df2e56Smrg        pWin->prevSib->nextSib = pWin->nextSib;
254905b261ecSmrg
25505a112b11Smrg    /* insert at beginning of pParent */
255105b261ecSmrg    pWin->parent = pParent;
255205b261ecSmrg    pPrev = RealChildHead(pParent);
2553f7df2e56Smrg    if (pPrev) {
2554f7df2e56Smrg        pWin->nextSib = pPrev->nextSib;
2555f7df2e56Smrg        if (pPrev->nextSib)
2556f7df2e56Smrg            pPrev->nextSib->prevSib = pWin;
2557f7df2e56Smrg        else
2558f7df2e56Smrg            pParent->lastChild = pWin;
2559f7df2e56Smrg        pPrev->nextSib = pWin;
2560f7df2e56Smrg        pWin->prevSib = pPrev;
256105b261ecSmrg    }
2562f7df2e56Smrg    else {
2563f7df2e56Smrg        pWin->nextSib = pParent->firstChild;
2564f7df2e56Smrg        pWin->prevSib = NullWindow;
2565f7df2e56Smrg        if (pParent->firstChild)
2566f7df2e56Smrg            pParent->firstChild->prevSib = pWin;
2567f7df2e56Smrg        else
2568f7df2e56Smrg            pParent->lastChild = pWin;
2569f7df2e56Smrg        pParent->firstChild = pWin;
257005b261ecSmrg    }
257105b261ecSmrg
257205b261ecSmrg    pWin->origin.x = x + bw;
257305b261ecSmrg    pWin->origin.y = y + bw;
257405b261ecSmrg    pWin->drawable.x = x + bw + pParent->drawable.x;
257505b261ecSmrg    pWin->drawable.y = y + bw + pParent->drawable.y;
257605b261ecSmrg
257705b261ecSmrg    /* clip to parent */
2578f7df2e56Smrg    SetWinSize(pWin);
2579f7df2e56Smrg    SetBorderSize(pWin);
258005b261ecSmrg
258105b261ecSmrg    if (pScreen->ReparentWindow)
2582f7df2e56Smrg        (*pScreen->ReparentWindow) (pWin, pPriorParent);
2583f7df2e56Smrg    (*pScreen->PositionWindow) (pWin, pWin->drawable.x, pWin->drawable.y);
258405b261ecSmrg    ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
258505b261ecSmrg
258605b261ecSmrg    CheckWindowOptionalNeed(pWin);
258705b261ecSmrg
258805b261ecSmrg    if (WasMapped)
2589f7df2e56Smrg        MapWindow(pWin, client);
259005b261ecSmrg    RecalculateDeliverableEvents(pWin);
25914202a189Smrg    return Success;
259205b261ecSmrg}
259305b261ecSmrg
259405b261ecSmrgstatic void
259505b261ecSmrgRealizeTree(WindowPtr pWin)
259605b261ecSmrg{
259705b261ecSmrg    WindowPtr pChild;
259805b261ecSmrg    RealizeWindowProcPtr Realize;
259905b261ecSmrg
260005b261ecSmrg    Realize = pWin->drawable.pScreen->RealizeWindow;
260105b261ecSmrg    pChild = pWin;
2602f7df2e56Smrg    while (1) {
2603f7df2e56Smrg        if (pChild->mapped) {
2604f7df2e56Smrg            pChild->realized = TRUE;
2605f7df2e56Smrg            pChild->viewable = (pChild->drawable.class == InputOutput);
2606f7df2e56Smrg            (*Realize) (pChild);
2607f7df2e56Smrg            if (pChild->firstChild) {
2608f7df2e56Smrg                pChild = pChild->firstChild;
2609f7df2e56Smrg                continue;
2610f7df2e56Smrg            }
2611f7df2e56Smrg        }
2612f7df2e56Smrg        while (!pChild->nextSib && (pChild != pWin))
2613f7df2e56Smrg            pChild = pChild->parent;
2614f7df2e56Smrg        if (pChild == pWin)
2615f7df2e56Smrg            return;
2616f7df2e56Smrg        pChild = pChild->nextSib;
2617f7df2e56Smrg    }
261805b261ecSmrg}
261905b261ecSmrg
2620f7df2e56Smrgstatic Bool
2621f7df2e56SmrgMaybeDeliverMapRequest(WindowPtr pWin, WindowPtr pParent, ClientPtr client)
262205b261ecSmrg{
2623f7df2e56Smrg    xEvent event = {
2624f7df2e56Smrg        .u.mapRequest.window = pWin->drawable.id,
2625f7df2e56Smrg        .u.mapRequest.parent = pParent->drawable.id
2626f7df2e56Smrg    };
2627f7df2e56Smrg    event.u.u.type = MapRequest;
2628f7df2e56Smrg
2629f7df2e56Smrg    return MaybeDeliverEventsToClient(pParent, &event, 1,
2630f7df2e56Smrg                                      SubstructureRedirectMask,
2631f7df2e56Smrg                                      client) == 1;
263205b261ecSmrg}
263305b261ecSmrg
2634f7df2e56Smrgstatic void
2635f7df2e56SmrgDeliverMapNotify(WindowPtr pWin)
263605b261ecSmrg{
2637f7df2e56Smrg    xEvent event = {
2638f7df2e56Smrg        .u.mapNotify.window = pWin->drawable.id,
2639f7df2e56Smrg        .u.mapNotify.override = pWin->overrideRedirect,
2640f7df2e56Smrg    };
2641f7df2e56Smrg    event.u.u.type = MapNotify;
2642f7df2e56Smrg    DeliverEvents(pWin, &event, 1, NullWindow);
264305b261ecSmrg}
264405b261ecSmrg
264505b261ecSmrg/*****
264605b261ecSmrg * MapWindow
264705b261ecSmrg *    If some other client has selected SubStructureReDirect on the parent
264805b261ecSmrg *    and override-redirect is xFalse, then a MapRequest event is generated,
264905b261ecSmrg *    but the window remains unmapped.	Otherwise, the window is mapped and a
265005b261ecSmrg *    MapNotify event is generated.
265105b261ecSmrg *****/
265205b261ecSmrg
26534202a189Smrgint
265405b261ecSmrgMapWindow(WindowPtr pWin, ClientPtr client)
265505b261ecSmrg{
265605b261ecSmrg    ScreenPtr pScreen;
265705b261ecSmrg
265805b261ecSmrg    WindowPtr pParent;
2659f7df2e56Smrg    WindowPtr pLayerWin;
266005b261ecSmrg
266105b261ecSmrg    if (pWin->mapped)
2662f7df2e56Smrg        return Success;
266305b261ecSmrg
2664f7df2e56Smrg    /* general check for permission to map window */
2665637ac9abSmrg    if (XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id, RT_WINDOW,
2666f7df2e56Smrg                 pWin, RT_NONE, NULL, DixShowAccess) != Success)
2667f7df2e56Smrg        return Success;
266805b261ecSmrg
266905b261ecSmrg    pScreen = pWin->drawable.pScreen;
2670f7df2e56Smrg    if ((pParent = pWin->parent)) {
2671f7df2e56Smrg        Bool anyMarked;
2672f7df2e56Smrg
2673f7df2e56Smrg        if ((!pWin->overrideRedirect) && (RedirectSend(pParent)))
2674f7df2e56Smrg            if (MaybeDeliverMapRequest(pWin, pParent, client))
2675f7df2e56Smrg                return Success;
2676f7df2e56Smrg
2677f7df2e56Smrg        pWin->mapped = TRUE;
2678f7df2e56Smrg        if (SubStrSend(pWin, pParent))
2679f7df2e56Smrg            DeliverMapNotify(pWin);
2680f7df2e56Smrg
2681f7df2e56Smrg        if (!pParent->realized)
2682f7df2e56Smrg            return Success;
2683f7df2e56Smrg        RealizeTree(pWin);
2684f7df2e56Smrg        if (pWin->viewable) {
2685f7df2e56Smrg            anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin,
2686f7df2e56Smrg                                                           &pLayerWin);
2687f7df2e56Smrg            if (anyMarked) {
2688f7df2e56Smrg                (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTMap);
2689f7df2e56Smrg                (*pScreen->HandleExposures) (pLayerWin->parent);
2690f7df2e56Smrg                if (pScreen->PostValidateTree)
2691f7df2e56Smrg                    (*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin,
2692f7df2e56Smrg                                                  VTMap);
2693f7df2e56Smrg            }
2694f7df2e56Smrg        }
2695f7df2e56Smrg        WindowsRestructured();
269605b261ecSmrg    }
2697f7df2e56Smrg    else {
2698f7df2e56Smrg        RegionRec temp;
2699f7df2e56Smrg
2700f7df2e56Smrg        pWin->mapped = TRUE;
2701f7df2e56Smrg        pWin->realized = TRUE;  /* for roots */
2702f7df2e56Smrg        pWin->viewable = pWin->drawable.class == InputOutput;
2703f7df2e56Smrg        /* We SHOULD check for an error value here XXX */
2704f7df2e56Smrg        (*pScreen->RealizeWindow) (pWin);
2705f7df2e56Smrg        if (pScreen->ClipNotify)
2706f7df2e56Smrg            (*pScreen->ClipNotify) (pWin, 0, 0);
2707f7df2e56Smrg        if (pScreen->PostValidateTree)
2708f7df2e56Smrg            (*pScreen->PostValidateTree) (NullWindow, pWin, VTMap);
2709f7df2e56Smrg        RegionNull(&temp);
2710f7df2e56Smrg        RegionCopy(&temp, &pWin->clipList);
2711f7df2e56Smrg        (*pScreen->WindowExposures) (pWin, &temp);
2712f7df2e56Smrg        RegionUninit(&temp);
271305b261ecSmrg    }
271405b261ecSmrg
27154202a189Smrg    return Success;
271605b261ecSmrg}
271705b261ecSmrg
271805b261ecSmrg/*****
271905b261ecSmrg * MapSubwindows
272005b261ecSmrg *    Performs a MapWindow all unmapped children of the window, in top
272105b261ecSmrg *    to bottom stacking order.
272205b261ecSmrg *****/
272305b261ecSmrg
272405b261ecSmrgvoid
272505b261ecSmrgMapSubwindows(WindowPtr pParent, ClientPtr client)
272605b261ecSmrg{
2727f7df2e56Smrg    WindowPtr pWin;
2728f7df2e56Smrg    WindowPtr pFirstMapped = NullWindow;
2729f7df2e56Smrg    ScreenPtr pScreen;
2730f7df2e56Smrg    Mask parentRedirect;
2731f7df2e56Smrg    Mask parentNotify;
2732f7df2e56Smrg    Bool anyMarked;
2733f7df2e56Smrg    WindowPtr pLayerWin;
273405b261ecSmrg
273505b261ecSmrg    pScreen = pParent->drawable.pScreen;
273605b261ecSmrg    parentRedirect = RedirectSend(pParent);
273705b261ecSmrg    parentNotify = SubSend(pParent);
273805b261ecSmrg    anyMarked = FALSE;
2739f7df2e56Smrg    for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) {
2740f7df2e56Smrg        if (!pWin->mapped) {
2741f7df2e56Smrg            if (parentRedirect && !pWin->overrideRedirect)
2742f7df2e56Smrg                if (MaybeDeliverMapRequest(pWin, pParent, client))
2743f7df2e56Smrg                    continue;
2744f7df2e56Smrg
2745f7df2e56Smrg            pWin->mapped = TRUE;
2746f7df2e56Smrg            if (parentNotify || StrSend(pWin))
2747f7df2e56Smrg                DeliverMapNotify(pWin);
2748f7df2e56Smrg
2749f7df2e56Smrg            if (!pFirstMapped)
2750f7df2e56Smrg                pFirstMapped = pWin;
2751f7df2e56Smrg            if (pParent->realized) {
2752f7df2e56Smrg                RealizeTree(pWin);
2753f7df2e56Smrg                if (pWin->viewable) {
2754f7df2e56Smrg                    anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin,
2755f7df2e56Smrg                                                                    NULL);
2756f7df2e56Smrg                }
2757f7df2e56Smrg            }
2758f7df2e56Smrg        }
2759f7df2e56Smrg    }
2760f7df2e56Smrg
2761f7df2e56Smrg    if (pFirstMapped) {
2762f7df2e56Smrg        pLayerWin = (*pScreen->GetLayerWindow) (pParent);
2763f7df2e56Smrg        if (pLayerWin->parent != pParent) {
2764f7df2e56Smrg            anyMarked |= (*pScreen->MarkOverlappedWindows) (pLayerWin,
2765f7df2e56Smrg                                                            pLayerWin, NULL);
2766f7df2e56Smrg            pFirstMapped = pLayerWin;
2767f7df2e56Smrg        }
2768f7df2e56Smrg        if (anyMarked) {
2769f7df2e56Smrg            (*pScreen->ValidateTree) (pLayerWin->parent, pFirstMapped, VTMap);
2770f7df2e56Smrg            (*pScreen->HandleExposures) (pLayerWin->parent);
2771f7df2e56Smrg            if (pScreen->PostValidateTree)
2772f7df2e56Smrg                (*pScreen->PostValidateTree) (pLayerWin->parent, pFirstMapped,
2773f7df2e56Smrg                                              VTMap);
2774f7df2e56Smrg        }
2775f7df2e56Smrg        WindowsRestructured();
277605b261ecSmrg    }
277705b261ecSmrg}
277805b261ecSmrg
277905b261ecSmrgstatic void
2780f7df2e56SmrgUnrealizeTree(WindowPtr pWin, Bool fromConfigure)
278105b261ecSmrg{
278205b261ecSmrg    WindowPtr pChild;
278305b261ecSmrg    UnrealizeWindowProcPtr Unrealize;
278405b261ecSmrg    MarkUnrealizedWindowProcPtr MarkUnrealizedWindow;
278505b261ecSmrg
278605b261ecSmrg    Unrealize = pWin->drawable.pScreen->UnrealizeWindow;
278705b261ecSmrg    MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow;
278805b261ecSmrg    pChild = pWin;
2789f7df2e56Smrg    while (1) {
2790f7df2e56Smrg        if (pChild->realized) {
2791f7df2e56Smrg            pChild->realized = FALSE;
2792f7df2e56Smrg            pChild->visibility = VisibilityNotViewable;
279305b261ecSmrg#ifdef PANORAMIX
2794f7df2e56Smrg            if (!noPanoramiXExtension && !pChild->drawable.pScreen->myNum) {
2795f7df2e56Smrg                PanoramiXRes *win;
2796f7df2e56Smrg                int rc = dixLookupResourceByType((void **) &win,
2797f7df2e56Smrg                                                 pChild->drawable.id,
2798f7df2e56Smrg                                                 XRT_WINDOW,
2799f7df2e56Smrg                                                 serverClient, DixWriteAccess);
2800f7df2e56Smrg
2801f7df2e56Smrg                if (rc == Success)
2802f7df2e56Smrg                    win->u.win.visibility = VisibilityNotViewable;
2803f7df2e56Smrg            }
280405b261ecSmrg#endif
2805f7df2e56Smrg            (*Unrealize) (pChild);
2806f7df2e56Smrg            DeleteWindowFromAnyEvents(pChild, FALSE);
2807f7df2e56Smrg            if (pChild->viewable) {
2808f7df2e56Smrg                pChild->viewable = FALSE;
2809f7df2e56Smrg                (*MarkUnrealizedWindow) (pChild, pWin, fromConfigure);
2810f7df2e56Smrg                pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
2811f7df2e56Smrg            }
2812f7df2e56Smrg            if (pChild->firstChild) {
2813f7df2e56Smrg                pChild = pChild->firstChild;
2814f7df2e56Smrg                continue;
2815f7df2e56Smrg            }
2816f7df2e56Smrg        }
2817f7df2e56Smrg        while (!pChild->nextSib && (pChild != pWin))
2818f7df2e56Smrg            pChild = pChild->parent;
2819f7df2e56Smrg        if (pChild == pWin)
2820f7df2e56Smrg            return;
2821f7df2e56Smrg        pChild = pChild->nextSib;
282205b261ecSmrg    }
282305b261ecSmrg}
282405b261ecSmrg
2825f7df2e56Smrgstatic void
2826f7df2e56SmrgDeliverUnmapNotify(WindowPtr pWin, Bool fromConfigure)
2827f7df2e56Smrg{
2828f7df2e56Smrg    xEvent event = {
2829f7df2e56Smrg        .u.unmapNotify.window = pWin->drawable.id,
2830f7df2e56Smrg        .u.unmapNotify.fromConfigure = fromConfigure
2831f7df2e56Smrg    };
2832f7df2e56Smrg    event.u.u.type = UnmapNotify;
2833f7df2e56Smrg    DeliverEvents(pWin, &event, 1, NullWindow);
2834f7df2e56Smrg}
2835f7df2e56Smrg
283605b261ecSmrg/*****
283705b261ecSmrg * UnmapWindow
283805b261ecSmrg *    If the window is already unmapped, this request has no effect.
283905b261ecSmrg *    Otherwise, the window is unmapped and an UnMapNotify event is
284005b261ecSmrg *    generated.  Cannot unmap a root window.
284105b261ecSmrg *****/
284205b261ecSmrg
28434202a189Smrgint
284405b261ecSmrgUnmapWindow(WindowPtr pWin, Bool fromConfigure)
284505b261ecSmrg{
284605b261ecSmrg    WindowPtr pParent;
2847f7df2e56Smrg    Bool wasRealized = (Bool) pWin->realized;
2848f7df2e56Smrg    Bool wasViewable = (Bool) pWin->viewable;
284905b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
285005b261ecSmrg    WindowPtr pLayerWin = pWin;
285105b261ecSmrg
285205b261ecSmrg    if ((!pWin->mapped) || (!(pParent = pWin->parent)))
2853f7df2e56Smrg        return Success;
2854f7df2e56Smrg    if (SubStrSend(pWin, pParent))
2855f7df2e56Smrg        DeliverUnmapNotify(pWin, fromConfigure);
2856f7df2e56Smrg    if (wasViewable && !fromConfigure) {
2857f7df2e56Smrg        pWin->valdata = UnmapValData;
2858f7df2e56Smrg        (*pScreen->MarkOverlappedWindows) (pWin, pWin->nextSib, &pLayerWin);
2859f7df2e56Smrg        (*pScreen->MarkWindow) (pLayerWin->parent);
286005b261ecSmrg    }
286105b261ecSmrg    pWin->mapped = FALSE;
286205b261ecSmrg    if (wasRealized)
2863f7df2e56Smrg        UnrealizeTree(pWin, fromConfigure);
28645a112b11Smrg    if (wasViewable && !fromConfigure) {
28655a112b11Smrg        (*pScreen->ValidateTree) (pLayerWin->parent, pWin, VTUnmap);
28665a112b11Smrg        (*pScreen->HandleExposures) (pLayerWin->parent);
28675a112b11Smrg        if (pScreen->PostValidateTree)
28685a112b11Smrg            (*pScreen->PostValidateTree) (pLayerWin->parent, pWin, VTUnmap);
2869f7df2e56Smrg    }
2870f7df2e56Smrg    if (wasRealized && !fromConfigure) {
2871f7df2e56Smrg        WindowsRestructured();
2872f7df2e56Smrg        WindowGone(pWin);
2873f7df2e56Smrg    }
28744202a189Smrg    return Success;
287505b261ecSmrg}
287605b261ecSmrg
287705b261ecSmrg/*****
287805b261ecSmrg * UnmapSubwindows
287905b261ecSmrg *    Performs an UnmapWindow request with the specified mode on all mapped
288005b261ecSmrg *    children of the window, in bottom to top stacking order.
288105b261ecSmrg *****/
288205b261ecSmrg
288305b261ecSmrgvoid
288405b261ecSmrgUnmapSubwindows(WindowPtr pWin)
288505b261ecSmrg{
288605b261ecSmrg    WindowPtr pChild, pHead;
2887f7df2e56Smrg    Bool wasRealized = (Bool) pWin->realized;
2888f7df2e56Smrg    Bool wasViewable = (Bool) pWin->viewable;
288905b261ecSmrg    Bool anyMarked = FALSE;
289005b261ecSmrg    Mask parentNotify;
289105b261ecSmrg    WindowPtr pLayerWin = NULL;
289205b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
289305b261ecSmrg
289405b261ecSmrg    if (!pWin->firstChild)
2895f7df2e56Smrg        return;
289605b261ecSmrg    parentNotify = SubSend(pWin);
289705b261ecSmrg    pHead = RealChildHead(pWin);
289805b261ecSmrg
289905b261ecSmrg    if (wasViewable)
2900f7df2e56Smrg        pLayerWin = (*pScreen->GetLayerWindow) (pWin);
2901f7df2e56Smrg
2902f7df2e56Smrg    for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) {
2903f7df2e56Smrg        if (pChild->mapped) {
2904f7df2e56Smrg            if (parentNotify || StrSend(pChild))
2905f7df2e56Smrg                DeliverUnmapNotify(pChild, xFalse);
2906f7df2e56Smrg            if (pChild->viewable) {
2907f7df2e56Smrg                pChild->valdata = UnmapValData;
2908f7df2e56Smrg                anyMarked = TRUE;
2909f7df2e56Smrg            }
2910f7df2e56Smrg            pChild->mapped = FALSE;
2911f7df2e56Smrg            if (pChild->realized)
2912f7df2e56Smrg                UnrealizeTree(pChild, FALSE);
2913f7df2e56Smrg        }
291405b261ecSmrg    }
29155a112b11Smrg    if (wasViewable && anyMarked) {
29165a112b11Smrg        if (pLayerWin->parent == pWin)
29175a112b11Smrg            (*pScreen->MarkWindow) (pWin);
29185a112b11Smrg        else {
29195a112b11Smrg            WindowPtr ptmp;
2920f7df2e56Smrg
29215a112b11Smrg            (*pScreen->MarkOverlappedWindows) (pWin, pLayerWin, NULL);
29225a112b11Smrg            (*pScreen->MarkWindow) (pLayerWin->parent);
2923f7df2e56Smrg
29245a112b11Smrg            /* Windows between pWin and pLayerWin may not have been marked */
29255a112b11Smrg            ptmp = pWin;
2926f7df2e56Smrg
29275a112b11Smrg            while (ptmp != pLayerWin->parent) {
29285a112b11Smrg                (*pScreen->MarkWindow) (ptmp);
29295a112b11Smrg                ptmp = ptmp->parent;
2930f7df2e56Smrg            }
29315a112b11Smrg            pHead = pWin->firstChild;
2932f7df2e56Smrg        }
29335a112b11Smrg        (*pScreen->ValidateTree) (pLayerWin->parent, pHead, VTUnmap);
29345a112b11Smrg        (*pScreen->HandleExposures) (pLayerWin->parent);
29355a112b11Smrg        if (pScreen->PostValidateTree)
29365a112b11Smrg            (*pScreen->PostValidateTree) (pLayerWin->parent, pHead, VTUnmap);
2937f7df2e56Smrg    }
2938f7df2e56Smrg    if (wasRealized) {
2939f7df2e56Smrg        WindowsRestructured();
2940f7df2e56Smrg        WindowGone(pWin);
294105b261ecSmrg    }
294205b261ecSmrg}
294305b261ecSmrg
294405b261ecSmrgvoid
294505b261ecSmrgHandleSaveSet(ClientPtr client)
294605b261ecSmrg{
294705b261ecSmrg    WindowPtr pParent, pWin;
294805b261ecSmrg    int j;
294905b261ecSmrg
2950f7df2e56Smrg    for (j = 0; j < client->numSaved; j++) {
2951f7df2e56Smrg        pWin = SaveSetWindow(client->saveSet[j]);
2952f7df2e56Smrg        if (SaveSetToRoot(client->saveSet[j]))
2953f7df2e56Smrg            pParent = pWin->drawable.pScreen->root;
2954f7df2e56Smrg        else
2955f7df2e56Smrg        {
2956f7df2e56Smrg            pParent = pWin->parent;
2957f7df2e56Smrg            while (pParent && (wClient(pParent) == client))
2958f7df2e56Smrg                pParent = pParent->parent;
2959f7df2e56Smrg        }
2960f7df2e56Smrg        if (pParent) {
2961f7df2e56Smrg            if (pParent != pWin->parent) {
2962f7df2e56Smrg                /* unmap first so that ReparentWindow doesn't remap */
2963f7df2e56Smrg                if (!SaveSetShouldMap(client->saveSet[j]))
2964f7df2e56Smrg                    UnmapWindow(pWin, FALSE);
2965f7df2e56Smrg                ReparentWindow(pWin, pParent,
2966f7df2e56Smrg                               pWin->drawable.x - wBorderWidth(pWin) -
2967f7df2e56Smrg                               pParent->drawable.x,
2968f7df2e56Smrg                               pWin->drawable.y - wBorderWidth(pWin) -
2969f7df2e56Smrg                               pParent->drawable.y, client);
2970f7df2e56Smrg                if (!pWin->realized && pWin->mapped)
2971f7df2e56Smrg                    pWin->mapped = FALSE;
2972f7df2e56Smrg            }
2973f7df2e56Smrg            if (SaveSetShouldMap(client->saveSet[j]))
2974f7df2e56Smrg                MapWindow(pWin, client);
2975f7df2e56Smrg        }
297605b261ecSmrg    }
29774202a189Smrg    free(client->saveSet);
297805b261ecSmrg    client->numSaved = 0;
2979f7df2e56Smrg    client->saveSet = NULL;
298005b261ecSmrg}
298105b261ecSmrg
298205b261ecSmrg/**
298305b261ecSmrg *
298405b261ecSmrg * \param x,y  in root
298505b261ecSmrg */
298605b261ecSmrgBool
298705b261ecSmrgPointInWindowIsVisible(WindowPtr pWin, int x, int y)
298805b261ecSmrg{
298905b261ecSmrg    BoxRec box;
299005b261ecSmrg
299105b261ecSmrg    if (!pWin->realized)
2992f7df2e56Smrg        return FALSE;
2993f7df2e56Smrg    if (RegionContainsPoint(&pWin->borderClip, x, y, &box)
2994f7df2e56Smrg        && (!wInputShape(pWin) ||
2995f7df2e56Smrg            RegionContainsPoint(wInputShape(pWin),
2996f7df2e56Smrg                                x - pWin->drawable.x,
2997f7df2e56Smrg                                y - pWin->drawable.y, &box)))
2998f7df2e56Smrg        return TRUE;
29994202a189Smrg    return FALSE;
300005b261ecSmrg}
300105b261ecSmrg
30024202a189SmrgRegionPtr
300305b261ecSmrgNotClippedByChildren(WindowPtr pWin)
300405b261ecSmrg{
30054202a189Smrg    RegionPtr pReg = RegionCreate(NullBox, 1);
3006f7df2e56Smrg
300705b261ecSmrg    if (pWin->parent ||
3008f7df2e56Smrg        screenIsSaved != SCREEN_SAVER_ON ||
3009f7df2e56Smrg        !HasSaverWindow(pWin->drawable.pScreen)) {
3010f7df2e56Smrg        RegionIntersect(pReg, &pWin->borderClip, &pWin->winSize);
301105b261ecSmrg    }
30124202a189Smrg    return pReg;
301305b261ecSmrg}
301405b261ecSmrg
3015637ac9abSmrgvoid
301605b261ecSmrgSendVisibilityNotify(WindowPtr pWin)
301705b261ecSmrg{
301805b261ecSmrg    xEvent event;
30194202a189Smrg    unsigned int visibility = pWin->visibility;
30204202a189Smrg
302105b261ecSmrg#ifdef PANORAMIX
302205b261ecSmrg    /* This is not quite correct yet, but it's close */
3023f7df2e56Smrg    if (!noPanoramiXExtension) {
3024f7df2e56Smrg        PanoramiXRes *win;
3025f7df2e56Smrg        WindowPtr pWin2;
3026f7df2e56Smrg        int rc, i, Scrnum;
3027f7df2e56Smrg
3028f7df2e56Smrg        Scrnum = pWin->drawable.pScreen->myNum;
3029f7df2e56Smrg
3030f7df2e56Smrg        win = PanoramiXFindIDByScrnum(XRT_WINDOW, pWin->drawable.id, Scrnum);
3031f7df2e56Smrg
3032f7df2e56Smrg        if (!win || (win->u.win.visibility == visibility))
3033f7df2e56Smrg            return;
3034f7df2e56Smrg
3035f7df2e56Smrg        switch (visibility) {
3036f7df2e56Smrg        case VisibilityUnobscured:
3037f7df2e56Smrg        FOR_NSCREENS(i) {
3038f7df2e56Smrg            if (i == Scrnum)
3039f7df2e56Smrg                continue;
3040f7df2e56Smrg
3041f7df2e56Smrg            rc = dixLookupWindow(&pWin2, win->info[i].id, serverClient,
3042f7df2e56Smrg                                 DixWriteAccess);
3043f7df2e56Smrg
3044f7df2e56Smrg            if (rc == Success) {
3045f7df2e56Smrg                if (pWin2->visibility == VisibilityPartiallyObscured)
3046f7df2e56Smrg                    return;
3047f7df2e56Smrg
3048f7df2e56Smrg                if (!i)
3049f7df2e56Smrg                    pWin = pWin2;
3050f7df2e56Smrg            }
3051f7df2e56Smrg        }
3052f7df2e56Smrg            break;
3053f7df2e56Smrg        case VisibilityPartiallyObscured:
3054f7df2e56Smrg            if (Scrnum) {
3055f7df2e56Smrg                rc = dixLookupWindow(&pWin2, win->info[0].id, serverClient,
3056f7df2e56Smrg                                     DixWriteAccess);
3057f7df2e56Smrg                if (rc == Success)
3058f7df2e56Smrg                    pWin = pWin2;
3059f7df2e56Smrg            }
3060f7df2e56Smrg            break;
3061f7df2e56Smrg        case VisibilityFullyObscured:
3062f7df2e56Smrg        FOR_NSCREENS(i) {
3063f7df2e56Smrg            if (i == Scrnum)
3064f7df2e56Smrg                continue;
3065f7df2e56Smrg
3066f7df2e56Smrg            rc = dixLookupWindow(&pWin2, win->info[i].id, serverClient,
3067f7df2e56Smrg                                 DixWriteAccess);
3068f7df2e56Smrg
3069f7df2e56Smrg            if (rc == Success) {
3070f7df2e56Smrg                if (pWin2->visibility != VisibilityFullyObscured)
3071f7df2e56Smrg                    return;
3072f7df2e56Smrg
3073f7df2e56Smrg                if (!i)
3074f7df2e56Smrg                    pWin = pWin2;
3075f7df2e56Smrg            }
3076f7df2e56Smrg        }
3077f7df2e56Smrg            break;
3078f7df2e56Smrg        }
3079f7df2e56Smrg
3080f7df2e56Smrg        win->u.win.visibility = visibility;
308105b261ecSmrg    }
308205b261ecSmrg#endif
308305b261ecSmrg
3084f7df2e56Smrg    event = (xEvent) {
3085f7df2e56Smrg        .u.visibility.window = pWin->drawable.id,
3086f7df2e56Smrg        .u.visibility.state = visibility
3087f7df2e56Smrg    };
308805b261ecSmrg    event.u.u.type = VisibilityNotify;
308905b261ecSmrg    DeliverEvents(pWin, &event, 1, NullWindow);
309005b261ecSmrg}
309105b261ecSmrg
309205b261ecSmrg#define RANDOM_WIDTH 32
30934202a189Smrgint
3094637ac9abSmrgdixSaveScreens(ClientPtr client, int on, int mode)
309505b261ecSmrg{
3096637ac9abSmrg    int rc, i, what, type;
30975a112b11Smrg    XID vlist[2];
309805b261ecSmrg
3099f7df2e56Smrg    if (on == SCREEN_SAVER_FORCER) {
3100f7df2e56Smrg        if (mode == ScreenSaverReset)
3101f7df2e56Smrg            what = SCREEN_SAVER_OFF;
3102f7df2e56Smrg        else
3103f7df2e56Smrg            what = SCREEN_SAVER_ON;
3104f7df2e56Smrg        type = what;
310505b261ecSmrg    }
3106f7df2e56Smrg    else {
3107f7df2e56Smrg        what = on;
3108f7df2e56Smrg        type = what;
3109f7df2e56Smrg        if (what == screenIsSaved)
3110f7df2e56Smrg            type = SCREEN_SAVER_CYCLE;
311105b261ecSmrg    }
3112637ac9abSmrg
3113637ac9abSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
3114f7df2e56Smrg        rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3115f7df2e56Smrg                      DixShowAccess | DixHideAccess);
3116f7df2e56Smrg        if (rc != Success)
3117f7df2e56Smrg            return rc;
3118637ac9abSmrg    }
3119f7df2e56Smrg    for (i = 0; i < screenInfo.numScreens; i++) {
3120f7df2e56Smrg        ScreenPtr pScreen = screenInfo.screens[i];
3121f7df2e56Smrg
3122f7df2e56Smrg        if (on == SCREEN_SAVER_FORCER)
3123f7df2e56Smrg            (*pScreen->SaveScreen) (pScreen, on);
3124f7df2e56Smrg        if (pScreen->screensaver.ExternalScreenSaver) {
3125f7df2e56Smrg            if ((*pScreen->screensaver.ExternalScreenSaver)
3126f7df2e56Smrg                (pScreen, type, on == SCREEN_SAVER_FORCER))
3127f7df2e56Smrg                continue;
3128f7df2e56Smrg        }
3129f7df2e56Smrg        if (type == screenIsSaved)
3130f7df2e56Smrg            continue;
3131f7df2e56Smrg        switch (type) {
3132f7df2e56Smrg        case SCREEN_SAVER_OFF:
3133f7df2e56Smrg            if (pScreen->screensaver.blanked == SCREEN_IS_BLANKED) {
3134f7df2e56Smrg                (*pScreen->SaveScreen) (pScreen, what);
3135f7df2e56Smrg            }
3136f7df2e56Smrg            else if (HasSaverWindow(pScreen)) {
3137f7df2e56Smrg                pScreen->screensaver.pWindow = NullWindow;
3138f7df2e56Smrg                FreeResource(pScreen->screensaver.wid, RT_NONE);
3139f7df2e56Smrg            }
3140f7df2e56Smrg            break;
3141f7df2e56Smrg        case SCREEN_SAVER_CYCLE:
3142f7df2e56Smrg            if (pScreen->screensaver.blanked == SCREEN_IS_TILED) {
3143f7df2e56Smrg                WindowPtr pWin = pScreen->screensaver.pWindow;
3144f7df2e56Smrg
3145f7df2e56Smrg                /* make it look like screen saver is off, so that
3146f7df2e56Smrg                 * NotClippedByChildren will compute a clip list
3147f7df2e56Smrg                 * for the root window, so PaintWindow works
3148f7df2e56Smrg                 */
3149f7df2e56Smrg                screenIsSaved = SCREEN_SAVER_OFF;
31505a112b11Smrg
31515a112b11Smrg                vlist[0] = -(rand() % RANDOM_WIDTH);
31525a112b11Smrg                vlist[1] = -(rand() % RANDOM_WIDTH);
31535a112b11Smrg                ConfigureWindow(pWin, CWX | CWY, vlist, client);
31545a112b11Smrg
3155f7df2e56Smrg                screenIsSaved = SCREEN_SAVER_ON;
3156f7df2e56Smrg            }
3157f7df2e56Smrg            /*
3158f7df2e56Smrg             * Call the DDX saver in case it wants to do something
3159f7df2e56Smrg             * at cycle time
3160f7df2e56Smrg             */
3161f7df2e56Smrg            else if (pScreen->screensaver.blanked == SCREEN_IS_BLANKED) {
3162f7df2e56Smrg                (*pScreen->SaveScreen) (pScreen, type);
3163f7df2e56Smrg            }
3164f7df2e56Smrg            break;
3165f7df2e56Smrg        case SCREEN_SAVER_ON:
3166f7df2e56Smrg            if (ScreenSaverBlanking != DontPreferBlanking) {
3167f7df2e56Smrg                if ((*pScreen->SaveScreen) (pScreen, what)) {
3168f7df2e56Smrg                    pScreen->screensaver.blanked = SCREEN_IS_BLANKED;
3169f7df2e56Smrg                    continue;
3170f7df2e56Smrg                }
3171f7df2e56Smrg                if ((ScreenSaverAllowExposures != DontAllowExposures) &&
3172f7df2e56Smrg                    TileScreenSaver(pScreen, SCREEN_IS_BLACK)) {
3173f7df2e56Smrg                    pScreen->screensaver.blanked = SCREEN_IS_BLACK;
3174f7df2e56Smrg                    continue;
3175f7df2e56Smrg                }
3176f7df2e56Smrg            }
3177f7df2e56Smrg            if ((ScreenSaverAllowExposures != DontAllowExposures) &&
3178f7df2e56Smrg                TileScreenSaver(pScreen, SCREEN_IS_TILED)) {
3179f7df2e56Smrg                pScreen->screensaver.blanked = SCREEN_IS_TILED;
3180f7df2e56Smrg            }
3181f7df2e56Smrg            else
3182f7df2e56Smrg                pScreen->screensaver.blanked = SCREEN_ISNT_SAVED;
3183f7df2e56Smrg            break;
3184f7df2e56Smrg        }
318505b261ecSmrg    }
318605b261ecSmrg    screenIsSaved = what;
31874202a189Smrg    if (mode == ScreenSaverReset) {
3188f7df2e56Smrg        if (on == SCREEN_SAVER_FORCER) {
3189f7df2e56Smrg            DeviceIntPtr dev;
3190f7df2e56Smrg            UpdateCurrentTimeIf();
3191f7df2e56Smrg            nt_list_for_each_entry(dev, inputInfo.devices, next)
3192f7df2e56Smrg                NoticeTime(dev, currentTime);
3193f7df2e56Smrg        }
3194f7df2e56Smrg        SetScreenSaverTimer();
31954202a189Smrg    }
3196637ac9abSmrg    return Success;
3197637ac9abSmrg}
3198637ac9abSmrg
31994202a189Smrgint
3200637ac9abSmrgSaveScreens(int on, int mode)
3201637ac9abSmrg{
3202637ac9abSmrg    return dixSaveScreens(serverClient, on, mode);
320305b261ecSmrg}
320405b261ecSmrg
320505b261ecSmrgstatic Bool
32064202a189SmrgTileScreenSaver(ScreenPtr pScreen, int kind)
320705b261ecSmrg{
320805b261ecSmrg    int j;
320905b261ecSmrg    int result;
321005b261ecSmrg    XID attributes[3];
321105b261ecSmrg    Mask mask;
3212f7df2e56Smrg    WindowPtr pWin;
321305b261ecSmrg    CursorMetricRec cm;
321405b261ecSmrg    unsigned char *srcbits, *mskbits;
321505b261ecSmrg    CursorPtr cursor;
3216f7df2e56Smrg    XID cursorID = 0;
3217f7df2e56Smrg    int attri;
321805b261ecSmrg
321905b261ecSmrg    mask = 0;
322005b261ecSmrg    attri = 0;
322105b261ecSmrg    switch (kind) {
322205b261ecSmrg    case SCREEN_IS_TILED:
3223f7df2e56Smrg        switch (pScreen->root->backgroundState) {
3224f7df2e56Smrg        case BackgroundPixel:
3225f7df2e56Smrg            attributes[attri++] = pScreen->root->background.pixel;
3226f7df2e56Smrg            mask |= CWBackPixel;
3227f7df2e56Smrg            break;
3228f7df2e56Smrg        case BackgroundPixmap:
3229f7df2e56Smrg            attributes[attri++] = None;
3230f7df2e56Smrg            mask |= CWBackPixmap;
3231f7df2e56Smrg            break;
3232f7df2e56Smrg        default:
3233f7df2e56Smrg            break;
3234f7df2e56Smrg        }
3235f7df2e56Smrg        break;
323605b261ecSmrg    case SCREEN_IS_BLACK:
3237f7df2e56Smrg        attributes[attri++] = pScreen->root->drawable.pScreen->blackPixel;
3238f7df2e56Smrg        mask |= CWBackPixel;
3239f7df2e56Smrg        break;
324005b261ecSmrg    }
324105b261ecSmrg    mask |= CWOverrideRedirect;
324205b261ecSmrg    attributes[attri++] = xTrue;
324305b261ecSmrg
324405b261ecSmrg    /*
324505b261ecSmrg     * create a blank cursor
324605b261ecSmrg     */
324705b261ecSmrg
3248f7df2e56Smrg    cm.width = 16;
3249f7df2e56Smrg    cm.height = 16;
3250f7df2e56Smrg    cm.xhot = 8;
3251f7df2e56Smrg    cm.yhot = 8;
3252f7df2e56Smrg    srcbits = malloc(BitmapBytePad(32) * 16);
3253f7df2e56Smrg    mskbits = malloc(BitmapBytePad(32) * 16);
3254f7df2e56Smrg    if (!srcbits || !mskbits) {
3255f7df2e56Smrg        free(srcbits);
3256f7df2e56Smrg        free(mskbits);
3257f7df2e56Smrg        cursor = 0;
325805b261ecSmrg    }
3259f7df2e56Smrg    else {
3260f7df2e56Smrg        for (j = 0; j < BitmapBytePad(32) * 16; j++)
3261f7df2e56Smrg            srcbits[j] = mskbits[j] = 0x0;
3262f7df2e56Smrg        result = AllocARGBCursor(srcbits, mskbits, NULL, &cm, 0, 0, 0, 0, 0, 0,
3263f7df2e56Smrg                                 &cursor, serverClient, (XID) 0);
3264f7df2e56Smrg        if (cursor) {
3265f7df2e56Smrg            cursorID = FakeClientID(0);
3266f7df2e56Smrg            if (AddResource(cursorID, RT_CURSOR, (void *) cursor)) {
3267f7df2e56Smrg                attributes[attri] = cursorID;
3268f7df2e56Smrg                mask |= CWCursor;
3269f7df2e56Smrg            }
3270f7df2e56Smrg            else
3271f7df2e56Smrg                cursor = 0;
3272f7df2e56Smrg        }
3273f7df2e56Smrg        else {
3274f7df2e56Smrg            free(srcbits);
3275f7df2e56Smrg            free(mskbits);
3276f7df2e56Smrg        }
327705b261ecSmrg    }
327805b261ecSmrg
32794202a189Smrg    pWin = pScreen->screensaver.pWindow =
3280f7df2e56Smrg        CreateWindow(pScreen->screensaver.wid,
3281f7df2e56Smrg                     pScreen->root,
3282f7df2e56Smrg                     -RANDOM_WIDTH, -RANDOM_WIDTH,
3283f7df2e56Smrg                     (unsigned short) pScreen->width + RANDOM_WIDTH,
3284f7df2e56Smrg                     (unsigned short) pScreen->height + RANDOM_WIDTH,
3285f7df2e56Smrg                     0, InputOutput, mask, attributes, 0, serverClient,
3286f7df2e56Smrg                     wVisual(pScreen->root), &result);
328705b261ecSmrg
328805b261ecSmrg    if (cursor)
3289f7df2e56Smrg        FreeResource(cursorID, RT_NONE);
329005b261ecSmrg
329105b261ecSmrg    if (!pWin)
3292f7df2e56Smrg        return FALSE;
329305b261ecSmrg
329405b261ecSmrg    if (!AddResource(pWin->drawable.id, RT_WINDOW,
3295f7df2e56Smrg                     (void *) pScreen->screensaver.pWindow))
3296f7df2e56Smrg        return FALSE;
329705b261ecSmrg
3298f7df2e56Smrg    if (mask & CWBackPixmap) {
3299f7df2e56Smrg        MakeRootTile(pWin);
3300f7df2e56Smrg        (*pWin->drawable.pScreen->ChangeWindowAttributes) (pWin, CWBackPixmap);
330105b261ecSmrg    }
330205b261ecSmrg    MapWindow(pWin, serverClient);
330305b261ecSmrg    return TRUE;
330405b261ecSmrg}
330505b261ecSmrg
330605b261ecSmrg/*
330705b261ecSmrg * FindWindowWithOptional
330805b261ecSmrg *
330905b261ecSmrg * search ancestors of the given window for an entry containing
331005b261ecSmrg * a WindowOpt structure.  Assumptions:	 some parent will
331105b261ecSmrg * contain the structure.
331205b261ecSmrg */
331305b261ecSmrg
33144202a189SmrgWindowPtr
3315f7df2e56SmrgFindWindowWithOptional(WindowPtr w)
331605b261ecSmrg{
331705b261ecSmrg    do
3318f7df2e56Smrg        w = w->parent;
331905b261ecSmrg    while (!w->optional);
332005b261ecSmrg    return w;
332105b261ecSmrg}
332205b261ecSmrg
332305b261ecSmrg/*
332405b261ecSmrg * CheckWindowOptionalNeed
332505b261ecSmrg *
332605b261ecSmrg * check each optional entry in the given window to see if
332705b261ecSmrg * the value is satisfied by the default rules.	 If so,
332805b261ecSmrg * release the optional record
332905b261ecSmrg */
333005b261ecSmrg
33314202a189Smrgvoid
3332f7df2e56SmrgCheckWindowOptionalNeed(WindowPtr w)
333305b261ecSmrg{
333405b261ecSmrg    WindowOptPtr optional;
333505b261ecSmrg    WindowOptPtr parentOptional;
333605b261ecSmrg
33374202a189Smrg    if (!w->parent || !w->optional)
3338f7df2e56Smrg        return;
333905b261ecSmrg    optional = w->optional;
334005b261ecSmrg    if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate])
3341f7df2e56Smrg        return;
334205b261ecSmrg    if (optional->otherEventMasks != 0)
3343f7df2e56Smrg        return;
334405b261ecSmrg    if (optional->otherClients != NULL)
3345f7df2e56Smrg        return;
334605b261ecSmrg    if (optional->passiveGrabs != NULL)
3347f7df2e56Smrg        return;
334805b261ecSmrg    if (optional->userProps != NULL)
3349f7df2e56Smrg        return;
3350f7df2e56Smrg    if (optional->backingBitPlanes != (CARD32)~0L)
3351f7df2e56Smrg        return;
335205b261ecSmrg    if (optional->backingPixel != 0)
3353f7df2e56Smrg        return;
335405b261ecSmrg    if (optional->boundingShape != NULL)
3355f7df2e56Smrg        return;
335605b261ecSmrg    if (optional->clipShape != NULL)
3357f7df2e56Smrg        return;
335805b261ecSmrg    if (optional->inputShape != NULL)
3359f7df2e56Smrg        return;
336005b261ecSmrg    if (optional->inputMasks != NULL)
3361f7df2e56Smrg        return;
3362f7df2e56Smrg    if (optional->deviceCursors != NULL) {
3363637ac9abSmrg        DevCursNodePtr pNode = optional->deviceCursors;
3364f7df2e56Smrg
3365f7df2e56Smrg        while (pNode) {
3366637ac9abSmrg            if (pNode->cursor != None)
3367637ac9abSmrg                return;
3368637ac9abSmrg            pNode = pNode->next;
3369637ac9abSmrg        }
3370637ac9abSmrg    }
3371637ac9abSmrg
337205b261ecSmrg    parentOptional = FindWindowWithOptional(w)->optional;
337305b261ecSmrg    if (optional->visual != parentOptional->visual)
3374f7df2e56Smrg        return;
337505b261ecSmrg    if (optional->cursor != None &&
3376f7df2e56Smrg        (optional->cursor != parentOptional->cursor || w->parent->cursorIsNone))
3377f7df2e56Smrg        return;
337805b261ecSmrg    if (optional->colormap != parentOptional->colormap)
3379f7df2e56Smrg        return;
3380f7df2e56Smrg    DisposeWindowOptional(w);
338105b261ecSmrg}
338205b261ecSmrg
338305b261ecSmrg/*
338405b261ecSmrg * MakeWindowOptional
338505b261ecSmrg *
338605b261ecSmrg * create an optional record and initialize it with the default
338705b261ecSmrg * values.
338805b261ecSmrg */
338905b261ecSmrg
33904202a189SmrgBool
3391f7df2e56SmrgMakeWindowOptional(WindowPtr pWin)
339205b261ecSmrg{
339305b261ecSmrg    WindowOptPtr optional;
339405b261ecSmrg    WindowOptPtr parentOptional;
339505b261ecSmrg
339605b261ecSmrg    if (pWin->optional)
3397f7df2e56Smrg        return TRUE;
3398f7df2e56Smrg    optional = malloc(sizeof(WindowOptRec));
339905b261ecSmrg    if (!optional)
3400f7df2e56Smrg        return FALSE;
340105b261ecSmrg    optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate];
340205b261ecSmrg    optional->otherEventMasks = 0;
340305b261ecSmrg    optional->otherClients = NULL;
340405b261ecSmrg    optional->passiveGrabs = NULL;
340505b261ecSmrg    optional->userProps = NULL;
340605b261ecSmrg    optional->backingBitPlanes = ~0L;
340705b261ecSmrg    optional->backingPixel = 0;
340805b261ecSmrg    optional->boundingShape = NULL;
340905b261ecSmrg    optional->clipShape = NULL;
341005b261ecSmrg    optional->inputShape = NULL;
341105b261ecSmrg    optional->inputMasks = NULL;
3412637ac9abSmrg    optional->deviceCursors = NULL;
3413637ac9abSmrg
341405b261ecSmrg    parentOptional = FindWindowWithOptional(pWin)->optional;
341505b261ecSmrg    optional->visual = parentOptional->visual;
3416f7df2e56Smrg    if (!pWin->cursorIsNone) {
3417f7df2e56Smrg        optional->cursor = RefCursor(parentOptional->cursor);
341805b261ecSmrg    }
3419f7df2e56Smrg    else {
3420f7df2e56Smrg        optional->cursor = None;
342105b261ecSmrg    }
342205b261ecSmrg    optional->colormap = parentOptional->colormap;
342305b261ecSmrg    pWin->optional = optional;
342405b261ecSmrg    return TRUE;
342505b261ecSmrg}
342605b261ecSmrg
3427637ac9abSmrg/*
3428637ac9abSmrg * Changes the cursor struct for the given device and the given window.
3429637ac9abSmrg * A cursor that does not have a device cursor set will use whatever the
3430637ac9abSmrg * standard cursor is for the window. If all devices have a cursor set,
3431637ac9abSmrg * changing the window cursor (e.g. using XDefineCursor()) will not have any
3432637ac9abSmrg * visible effect. Only when one of the device cursors is set to None again,
3433637ac9abSmrg * this device's cursor will display the changed standard cursor.
3434f7df2e56Smrg *
3435637ac9abSmrg * CursorIsNone of the window struct is NOT modified if you set a device
3436f7df2e56Smrg * cursor.
3437637ac9abSmrg *
3438637ac9abSmrg * Assumption: If there is a node for a device in the list, the device has a
3439637ac9abSmrg * cursor. If the cursor is set to None, it is inherited by the parent.
3440637ac9abSmrg */
34414202a189Smrgint
3442f7df2e56SmrgChangeWindowDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev, CursorPtr pCursor)
3443637ac9abSmrg{
3444637ac9abSmrg    DevCursNodePtr pNode, pPrev;
3445637ac9abSmrg    CursorPtr pOldCursor = NULL;
3446637ac9abSmrg    ScreenPtr pScreen;
3447637ac9abSmrg    WindowPtr pChild;
3448637ac9abSmrg
3449637ac9abSmrg    if (!pWin->optional && !MakeWindowOptional(pWin))
3450637ac9abSmrg        return BadAlloc;
3451637ac9abSmrg
3452637ac9abSmrg    /* 1) Check if window has device cursor set
3453637ac9abSmrg     *  Yes: 1.1) swap cursor with given cursor if parent does not have same
3454637ac9abSmrg     *            cursor, free old cursor
3455637ac9abSmrg     *       1.2) free old cursor, use parent cursor
3456637ac9abSmrg     *  No: 1.1) add node to beginning of list.
3457637ac9abSmrg     *      1.2) add cursor to node if parent does not have same cursor
3458637ac9abSmrg     *      1.3) use parent cursor if parent does not have same cursor
3459637ac9abSmrg     *  2) Patch up children if child has a devcursor
3460637ac9abSmrg     *  2.1) if child has cursor None, it inherited from parent, set to old
3461637ac9abSmrg     *  cursor
3462637ac9abSmrg     *  2.2) if child has same cursor as new cursor, remove and set to None
3463637ac9abSmrg     */
3464637ac9abSmrg
3465637ac9abSmrg    pScreen = pWin->drawable.pScreen;
3466637ac9abSmrg
3467f7df2e56Smrg    if (WindowSeekDeviceCursor(pWin, pDev, &pNode, &pPrev)) {
3468637ac9abSmrg        /* has device cursor */
3469637ac9abSmrg
3470637ac9abSmrg        if (pNode->cursor == pCursor)
3471637ac9abSmrg            return Success;
3472637ac9abSmrg
3473637ac9abSmrg        pOldCursor = pNode->cursor;
3474637ac9abSmrg
3475f7df2e56Smrg        if (!pCursor) {         /* remove from list */
3476f7df2e56Smrg            if (pPrev)
3477f7df2e56Smrg                pPrev->next = pNode->next;
3478f7df2e56Smrg            else
3479f7df2e56Smrg                /* first item in list */
3480f7df2e56Smrg                pWin->optional->deviceCursors = pNode->next;
3481637ac9abSmrg
34824202a189Smrg            free(pNode);
34834202a189Smrg            goto out;
3484637ac9abSmrg        }
3485637ac9abSmrg
3486f7df2e56Smrg    }
3487f7df2e56Smrg    else {
3488637ac9abSmrg        /* no device cursor yet */
3489637ac9abSmrg        DevCursNodePtr pNewNode;
3490637ac9abSmrg
3491637ac9abSmrg        if (!pCursor)
3492637ac9abSmrg            return Success;
3493637ac9abSmrg
34944202a189Smrg        pNewNode = malloc(sizeof(DevCursNodeRec));
3495637ac9abSmrg        pNewNode->dev = pDev;
3496637ac9abSmrg        pNewNode->next = pWin->optional->deviceCursors;
3497637ac9abSmrg        pWin->optional->deviceCursors = pNewNode;
3498637ac9abSmrg        pNode = pNewNode;
3499637ac9abSmrg
3500637ac9abSmrg    }
3501637ac9abSmrg
3502637ac9abSmrg    if (pCursor && WindowParentHasDeviceCursor(pWin, pDev, pCursor))
3503637ac9abSmrg        pNode->cursor = None;
3504f7df2e56Smrg    else {
3505f7df2e56Smrg        pNode->cursor = RefCursor(pCursor);
3506637ac9abSmrg    }
3507637ac9abSmrg
3508637ac9abSmrg    pNode = pPrev = NULL;
3509637ac9abSmrg    /* fix up children */
3510f7df2e56Smrg    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
3511f7df2e56Smrg        if (WindowSeekDeviceCursor(pChild, pDev, &pNode, &pPrev)) {
3512f7df2e56Smrg            if (pNode->cursor == None) {        /* inherited from parent */
3513f7df2e56Smrg                pNode->cursor = RefCursor(pOldCursor);
3514f7df2e56Smrg            }
3515f7df2e56Smrg            else if (pNode->cursor == pCursor) {
3516637ac9abSmrg                pNode->cursor = None;
3517f7df2e56Smrg                FreeCursor(pCursor, (Cursor) 0);        /* fix up refcnt */
3518637ac9abSmrg            }
3519637ac9abSmrg        }
3520637ac9abSmrg    }
3521637ac9abSmrg
3522f7df2e56Smrg out:
3523f7df2e56Smrg    CursorVisible = TRUE;
3524f7df2e56Smrg
3525637ac9abSmrg    if (pWin->realized)
3526637ac9abSmrg        WindowHasNewCursor(pWin);
3527637ac9abSmrg
3528637ac9abSmrg    if (pOldCursor)
3529f7df2e56Smrg        FreeCursor(pOldCursor, (Cursor) 0);
3530637ac9abSmrg
3531f7df2e56Smrg    /* FIXME: We SHOULD check for an error value here XXX
3532637ac9abSmrg       (comment taken from ChangeWindowAttributes) */
3533f7df2e56Smrg    (*pScreen->ChangeWindowAttributes) (pWin, CWCursor);
3534637ac9abSmrg
3535637ac9abSmrg    return Success;
3536637ac9abSmrg}
3537637ac9abSmrg
3538637ac9abSmrg/* Get device cursor for given device or None if none is set */
35394202a189SmrgCursorPtr
3540637ac9abSmrgWindowGetDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev)
3541637ac9abSmrg{
3542637ac9abSmrg    DevCursorList pList;
3543637ac9abSmrg
3544637ac9abSmrg    if (!pWin->optional || !pWin->optional->deviceCursors)
3545637ac9abSmrg        return NULL;
3546637ac9abSmrg
3547637ac9abSmrg    pList = pWin->optional->deviceCursors;
3548637ac9abSmrg
3549f7df2e56Smrg    while (pList) {
3550f7df2e56Smrg        if (pList->dev == pDev) {
3551f7df2e56Smrg            if (pList->cursor == None)  /* inherited from parent */
3552637ac9abSmrg                return WindowGetDeviceCursor(pWin->parent, pDev);
3553637ac9abSmrg            else
3554637ac9abSmrg                return pList->cursor;
3555637ac9abSmrg        }
3556637ac9abSmrg        pList = pList->next;
3557637ac9abSmrg    }
3558637ac9abSmrg    return NULL;
3559637ac9abSmrg}
3560637ac9abSmrg
3561637ac9abSmrg/* Searches for a DevCursorNode for the given window and device. If one is
3562637ac9abSmrg * found, return True and set pNode and pPrev to the node and to the node
3563637ac9abSmrg * before the node respectively. Otherwise return False.
3564637ac9abSmrg * If the device is the first in list, pPrev is set to NULL.
3565637ac9abSmrg */
3566f7df2e56Smrgstatic Bool
3567f7df2e56SmrgWindowSeekDeviceCursor(WindowPtr pWin,
3568f7df2e56Smrg                       DeviceIntPtr pDev,
3569f7df2e56Smrg                       DevCursNodePtr * pNode, DevCursNodePtr * pPrev)
3570637ac9abSmrg{
3571637ac9abSmrg    DevCursorList pList;
3572637ac9abSmrg
3573637ac9abSmrg    if (!pWin->optional)
3574637ac9abSmrg        return FALSE;
3575637ac9abSmrg
3576637ac9abSmrg    pList = pWin->optional->deviceCursors;
3577637ac9abSmrg
3578f7df2e56Smrg    if (pList && pList->dev == pDev) {
3579637ac9abSmrg        *pNode = pList;
3580637ac9abSmrg        *pPrev = NULL;
3581637ac9abSmrg        return TRUE;
3582637ac9abSmrg    }
3583637ac9abSmrg
3584f7df2e56Smrg    while (pList) {
3585f7df2e56Smrg        if (pList->next) {
3586f7df2e56Smrg            if (pList->next->dev == pDev) {
3587637ac9abSmrg                *pNode = pList->next;
3588637ac9abSmrg                *pPrev = pList;
3589637ac9abSmrg                return TRUE;
3590637ac9abSmrg            }
3591637ac9abSmrg        }
3592637ac9abSmrg        pList = pList->next;
3593637ac9abSmrg    }
3594637ac9abSmrg    return FALSE;
3595637ac9abSmrg}
3596637ac9abSmrg
3597637ac9abSmrg/* Return True if a parent has the same device cursor set or False if
3598f7df2e56Smrg * otherwise
3599f7df2e56Smrg */
3600f7df2e56Smrgstatic Bool
3601f7df2e56SmrgWindowParentHasDeviceCursor(WindowPtr pWin,
3602f7df2e56Smrg                            DeviceIntPtr pDev, CursorPtr pCursor)
3603637ac9abSmrg{
3604637ac9abSmrg    WindowPtr pParent;
3605637ac9abSmrg    DevCursNodePtr pParentNode, pParentPrev;
3606637ac9abSmrg
3607637ac9abSmrg    pParent = pWin->parent;
3608f7df2e56Smrg    while (pParent) {
3609f7df2e56Smrg        if (WindowSeekDeviceCursor(pParent, pDev, &pParentNode, &pParentPrev)) {
3610637ac9abSmrg            /* if there is a node in the list, the win has a dev cursor */
3611f7df2e56Smrg            if (!pParentNode->cursor)   /* inherited. */
36121b684552Smrg                pParent = pParent->parent;
3613f7df2e56Smrg            else if (pParentNode->cursor == pCursor)    /* inherit */
3614637ac9abSmrg                return TRUE;
3615f7df2e56Smrg            else                /* different cursor */
3616637ac9abSmrg                return FALSE;
3617f7df2e56Smrg        }
3618f7df2e56Smrg        else
3619637ac9abSmrg            /* parent does not have a device cursor for our device */
3620637ac9abSmrg            return FALSE;
3621637ac9abSmrg    }
3622637ac9abSmrg    return FALSE;
3623637ac9abSmrg}
3624f7df2e56Smrg
3625f7df2e56Smrg/*
3626f7df2e56Smrg * SetRootClip --
3627f7df2e56Smrg *	Enable or disable rendering to the screen by
3628f7df2e56Smrg *	setting the root clip list and revalidating
3629f7df2e56Smrg *	all of the windows
3630f7df2e56Smrg */
3631f7df2e56Smrgvoid
3632f7df2e56SmrgSetRootClip(ScreenPtr pScreen, int enable)
3633f7df2e56Smrg{
3634f7df2e56Smrg    WindowPtr pWin = pScreen->root;
3635f7df2e56Smrg    WindowPtr pChild;
3636f7df2e56Smrg    Bool WasViewable;
3637f7df2e56Smrg    Bool anyMarked = FALSE;
3638f7df2e56Smrg    WindowPtr pLayerWin;
3639f7df2e56Smrg    BoxRec box;
3640f7df2e56Smrg    enum RootClipMode mode = enable;
3641f7df2e56Smrg
3642f7df2e56Smrg    if (!pWin)
3643f7df2e56Smrg        return;
3644f7df2e56Smrg    WasViewable = (Bool) (pWin->viewable);
3645f7df2e56Smrg    if (WasViewable) {
3646f7df2e56Smrg        for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
3647f7df2e56Smrg            (void) (*pScreen->MarkOverlappedWindows) (pChild,
3648f7df2e56Smrg                                                      pChild, &pLayerWin);
3649f7df2e56Smrg        }
3650f7df2e56Smrg        (*pScreen->MarkWindow) (pWin);
3651f7df2e56Smrg        anyMarked = TRUE;
3652f7df2e56Smrg        if (pWin->valdata) {
3653f7df2e56Smrg            if (HasBorder(pWin)) {
3654f7df2e56Smrg                RegionPtr borderVisible;
3655f7df2e56Smrg
3656f7df2e56Smrg                borderVisible = RegionCreate(NullBox, 1);
3657f7df2e56Smrg                RegionSubtract(borderVisible,
3658f7df2e56Smrg                               &pWin->borderClip, &pWin->winSize);
3659f7df2e56Smrg                pWin->valdata->before.borderVisible = borderVisible;
3660f7df2e56Smrg            }
3661f7df2e56Smrg            pWin->valdata->before.resized = TRUE;
3662f7df2e56Smrg        }
3663f7df2e56Smrg    }
3664f7df2e56Smrg
3665f7df2e56Smrg    if (mode != ROOT_CLIP_NONE) {
3666f7df2e56Smrg        pWin->drawable.width = pScreen->width;
3667f7df2e56Smrg        pWin->drawable.height = pScreen->height;
3668f7df2e56Smrg
3669f7df2e56Smrg        box.x1 = 0;
3670f7df2e56Smrg        box.y1 = 0;
3671f7df2e56Smrg        box.x2 = pScreen->width;
3672f7df2e56Smrg        box.y2 = pScreen->height;
3673f7df2e56Smrg
3674f7df2e56Smrg        RegionInit(&pWin->winSize, &box, 1);
3675f7df2e56Smrg        RegionInit(&pWin->borderSize, &box, 1);
3676f7df2e56Smrg
3677f7df2e56Smrg        /*
3678f7df2e56Smrg         * Use REGION_BREAK to avoid optimizations in ValidateTree
3679f7df2e56Smrg         * that assume the root borderClip can't change well, normally
3680f7df2e56Smrg         * it doesn't...)
3681f7df2e56Smrg         */
3682f7df2e56Smrg        RegionBreak(&pWin->clipList);
3683f7df2e56Smrg
3684f7df2e56Smrg	/* For INPUT_ONLY, empty the borderClip so no rendering will ever
3685f7df2e56Smrg	 * be attempted to the screen pixmap (only redirected windows),
3686f7df2e56Smrg	 * but we keep borderSize as full regardless. */
3687f7df2e56Smrg        if (WasViewable && mode == ROOT_CLIP_FULL)
3688f7df2e56Smrg            RegionReset(&pWin->borderClip, &box);
3689f7df2e56Smrg        else
3690f7df2e56Smrg            RegionEmpty(&pWin->borderClip);
3691f7df2e56Smrg    }
3692f7df2e56Smrg    else {
3693f7df2e56Smrg        RegionEmpty(&pWin->borderClip);
3694f7df2e56Smrg        RegionBreak(&pWin->clipList);
3695f7df2e56Smrg    }
3696f7df2e56Smrg
3697f7df2e56Smrg    ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
3698f7df2e56Smrg
3699f7df2e56Smrg    if (WasViewable) {
3700f7df2e56Smrg        if (pWin->firstChild) {
3701f7df2e56Smrg            anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin->firstChild,
3702f7df2e56Smrg                                                            pWin->firstChild,
3703f7df2e56Smrg                                                            NULL);
3704f7df2e56Smrg        }
3705f7df2e56Smrg        else {
3706f7df2e56Smrg            (*pScreen->MarkWindow) (pWin);
3707f7df2e56Smrg            anyMarked = TRUE;
3708f7df2e56Smrg        }
3709f7df2e56Smrg
3710f7df2e56Smrg        if (anyMarked) {
3711f7df2e56Smrg            (*pScreen->ValidateTree) (pWin, NullWindow, VTOther);
3712f7df2e56Smrg            (*pScreen->HandleExposures) (pWin);
3713f7df2e56Smrg            if (pScreen->PostValidateTree)
3714f7df2e56Smrg                (*pScreen->PostValidateTree) (pWin, NullWindow, VTOther);
3715f7df2e56Smrg        }
3716f7df2e56Smrg    }
3717f7df2e56Smrg    if (pWin->realized)
3718f7df2e56Smrg        WindowsRestructured();
3719f7df2e56Smrg    FlushAllOutput();
3720f7df2e56Smrg}
3721f7df2e56Smrg
3722f7df2e56SmrgVisualPtr
3723f7df2e56SmrgWindowGetVisual(WindowPtr pWin)
3724f7df2e56Smrg{
3725f7df2e56Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
3726f7df2e56Smrg    VisualID vid = wVisual(pWin);
3727f7df2e56Smrg    int i;
3728f7df2e56Smrg
3729f7df2e56Smrg    for (i = 0; i < pScreen->numVisuals; i++)
3730f7df2e56Smrg        if (pScreen->visuals[i].vid == vid)
3731f7df2e56Smrg            return &pScreen->visuals[i];
3732f7df2e56Smrg    return 0;
3733f7df2e56Smrg}
3734