xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

window.c (117261B)


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