xserver

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

rootlessWindow.c (50751B)


      1 /*
      2  * Rootless window management
      3  */
      4 /*
      5  * Copyright (c) 2001 Greg Parker. All Rights Reserved.
      6  * Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved.
      7  * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
      8  *
      9  * Permission is hereby granted, free of charge, to any person obtaining a
     10  * copy of this software and associated documentation files (the "Software"),
     11  * to deal in the Software without restriction, including without limitation
     12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     13  * and/or sell copies of the Software, and to permit persons to whom the
     14  * Software is furnished to do so, subject to the following conditions:
     15  *
     16  * The above copyright notice and this permission notice shall be included in
     17  * all copies or substantial portions of the Software.
     18  *
     19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     22  * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     23  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     24  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     25  * DEALINGS IN THE SOFTWARE.
     26  *
     27  * Except as contained in this notice, the name(s) of the above copyright
     28  * holders shall not be used in advertising or otherwise to promote the sale,
     29  * use or other dealings in this Software without prior written authorization.
     30  */
     31 
     32 #ifdef HAVE_DIX_CONFIG_H
     33 #include <dix-config.h>
     34 #endif
     35 
     36 #include <stddef.h>             /* For NULL */
     37 #include <limits.h>             /* For CHAR_BIT */
     38 #include <assert.h>
     39 #include <X11/Xatom.h>
     40 #ifdef __APPLE__
     41 #include <Xplugin.h>
     42 #include "mi.h"
     43 #include "pixmapstr.h"
     44 #include "windowstr.h"
     45 //#include <X11/extensions/applewm.h>
     46 extern int darwinMainScreenX, darwinMainScreenY;
     47 extern Bool no_configure_window;
     48 #endif
     49 #include "fb.h"
     50 
     51 #include "rootlessCommon.h"
     52 #include "rootlessWindow.h"
     53 
     54 #define SCREEN_TO_GLOBAL_X \
     55     (pScreen->x + rootlessGlobalOffsetX)
     56 #define SCREEN_TO_GLOBAL_Y \
     57     (pScreen->y + rootlessGlobalOffsetY)
     58 
     59 #define DEFINE_ATOM_HELPER(func,atom_name)                      \
     60   static Atom func (void) {                                       \
     61     static unsigned int generation = 0;                             \
     62     static Atom atom;                                           \
     63     if (generation != serverGeneration) {                       \
     64       generation = serverGeneration;                          \
     65       atom = MakeAtom (atom_name, strlen (atom_name), TRUE);  \
     66     }                                                           \
     67     return atom;                                                \
     68   }
     69 
     70 DEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID")
     71 
     72 static Bool windows_hidden;
     73 
     74 // TODO - abstract xp functions
     75 
     76 #ifdef __APPLE__
     77 
     78 // XXX: identical to x_cvt_vptr_to_uint ?
     79 #define MAKE_WINDOW_ID(x)		((xp_window_id)((size_t)(x)))
     80 
     81 void
     82 RootlessNativeWindowStateChanged(WindowPtr pWin, unsigned int state)
     83 {
     84     RootlessWindowRec *winRec;
     85 
     86     if (pWin == NULL)
     87         return;
     88 
     89     winRec = WINREC(pWin);
     90     if (winRec == NULL)
     91         return;
     92 
     93     winRec->is_offscreen = ((state & XP_WINDOW_STATE_OFFSCREEN) != 0);
     94     winRec->is_obscured = ((state & XP_WINDOW_STATE_OBSCURED) != 0);
     95     pWin->unhittable = winRec->is_offscreen;
     96 }
     97 
     98 void
     99 RootlessNativeWindowMoved(WindowPtr pWin)
    100 {
    101     xp_box bounds;
    102     int sx, sy, err;
    103     XID vlist[2];
    104     Mask mask;
    105     ClientPtr pClient;
    106     RootlessWindowRec *winRec;
    107 
    108     winRec = WINREC(pWin);
    109 
    110     if (xp_get_window_bounds(MAKE_WINDOW_ID(winRec->wid), &bounds) != Success)
    111         return;
    112 
    113     sx = pWin->drawable.pScreen->x + darwinMainScreenX;
    114     sy = pWin->drawable.pScreen->y + darwinMainScreenY;
    115 
    116     /* Fake up a ConfigureWindow packet to resize the window to the current bounds. */
    117     vlist[0] = (INT16) bounds.x1 - sx;
    118     vlist[1] = (INT16) bounds.y1 - sy;
    119     mask = CWX | CWY;
    120 
    121     /* pretend we're the owner of the window! */
    122     err =
    123         dixLookupClient(&pClient, pWin->drawable.id, serverClient,
    124                         DixUnknownAccess);
    125     if (err != Success) {
    126         ErrorF("RootlessNativeWindowMoved(): Failed to lookup window: 0x%x\n",
    127                (unsigned int) pWin->drawable.id);
    128         return;
    129     }
    130 
    131     /* Don't want to do anything to the physical window (avoids
    132        notification-response feedback loops) */
    133 
    134     no_configure_window = TRUE;
    135     ConfigureWindow(pWin, mask, vlist, pClient);
    136     no_configure_window = FALSE;
    137 }
    138 
    139 #endif                          /* __APPLE__ */
    140 
    141 /*
    142  * RootlessCreateWindow
    143  *  For now, don't create a physical window until either the window is
    144  *  realized, or we really need it (e.g. to attach VRAM surfaces to).
    145  *  Do reset the window size so it's not clipped by the root window.
    146  */
    147 Bool
    148 RootlessCreateWindow(WindowPtr pWin)
    149 {
    150     Bool result;
    151     RegionRec saveRoot;
    152 
    153     SETWINREC(pWin, NULL);
    154     dixSetPrivate(&pWin->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL);
    155 
    156     SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow);
    157 
    158     if (!IsRoot(pWin)) {
    159         /* win/border size set by DIX, not by wrapped CreateWindow, so
    160            correct it here. Don't HUGE_ROOT when pWin is the root! */
    161 
    162         HUGE_ROOT(pWin);
    163         SetWinSize(pWin);
    164         SetBorderSize(pWin);
    165     }
    166 
    167     result = pWin->drawable.pScreen->CreateWindow(pWin);
    168 
    169     if (pWin->parent) {
    170         NORMAL_ROOT(pWin);
    171     }
    172 
    173     SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow);
    174 
    175     return result;
    176 }
    177 
    178 /*
    179  * RootlessDestroyFrame
    180  *  Destroy the physical window associated with the given window.
    181  */
    182 static void
    183 RootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec)
    184 {
    185     SCREENREC(pWin->drawable.pScreen)->imp->DestroyFrame(winRec->wid);
    186     free(winRec);
    187     SETWINREC(pWin, NULL);
    188 }
    189 
    190 /*
    191  * RootlessDestroyWindow
    192  *  Destroy the physical window associated with the given window.
    193  */
    194 Bool
    195 RootlessDestroyWindow(WindowPtr pWin)
    196 {
    197     RootlessWindowRec *winRec = WINREC(pWin);
    198     Bool result;
    199 
    200     if (winRec != NULL) {
    201         RootlessDestroyFrame(pWin, winRec);
    202     }
    203 
    204     SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow);
    205     result = pWin->drawable.pScreen->DestroyWindow(pWin);
    206     SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow);
    207 
    208     return result;
    209 }
    210 
    211 static Bool
    212 RootlessGetShape(WindowPtr pWin, RegionPtr pShape)
    213 {
    214     if (wBoundingShape(pWin) == NULL)
    215         return FALSE;
    216 
    217     /* wBoundingShape is relative to *inner* origin of window.
    218        Translate by borderWidth to get the outside-relative position. */
    219 
    220     RegionNull(pShape);
    221     RegionCopy(pShape, wBoundingShape(pWin));
    222     RegionTranslate(pShape, pWin->borderWidth, pWin->borderWidth);
    223 
    224     return TRUE;
    225 }
    226 
    227 /*
    228  * RootlessReshapeFrame
    229  *  Set the frame shape.
    230  */
    231 static void
    232 RootlessReshapeFrame(WindowPtr pWin)
    233 {
    234     RootlessWindowRec *winRec = WINREC(pWin);
    235     RegionRec newShape;
    236     RegionPtr pShape;
    237 
    238     // If the window is not yet framed, do nothing
    239     if (winRec == NULL)
    240         return;
    241 
    242     if (IsRoot(pWin))
    243         return;
    244 
    245     RootlessStopDrawing(pWin, FALSE);
    246 
    247     pShape = RootlessGetShape(pWin, &newShape) ? &newShape : NULL;
    248 
    249 #ifdef ROOTLESSDEBUG
    250     RL_DEBUG_MSG("reshaping...");
    251     if (pShape != NULL) {
    252         RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ",
    253                      RegionNumRects(&newShape),
    254                      newShape.extents.x1, newShape.extents.y1,
    255                      newShape.extents.x2, newShape.extents.y2);
    256     }
    257     else {
    258         RL_DEBUG_MSG("no shape ");
    259     }
    260 #endif
    261 
    262     SCREENREC(pWin->drawable.pScreen)->imp->ReshapeFrame(winRec->wid, pShape);
    263 
    264     if (pShape != NULL)
    265         RegionUninit(&newShape);
    266 }
    267 
    268 /*
    269  * RootlessSetShape
    270  *  Shape is usually set before a window is mapped and the window will
    271  *  not have a frame associated with it. In this case, the frame will be
    272  *  shaped when the window is framed.
    273  */
    274 void
    275 RootlessSetShape(WindowPtr pWin, int kind)
    276 {
    277     ScreenPtr pScreen = pWin->drawable.pScreen;
    278 
    279     SCREEN_UNWRAP(pScreen, SetShape);
    280     pScreen->SetShape(pWin, kind);
    281     SCREEN_WRAP(pScreen, SetShape);
    282 
    283     RootlessReshapeFrame(pWin);
    284 }
    285 
    286 /* Disallow ParentRelative background on top-level windows
    287    because the root window doesn't really have the right background.
    288  */
    289 Bool
    290 RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask)
    291 {
    292     Bool result;
    293     ScreenPtr pScreen = pWin->drawable.pScreen;
    294 
    295     RL_DEBUG_MSG("change window attributes start ");
    296 
    297     SCREEN_UNWRAP(pScreen, ChangeWindowAttributes);
    298     result = pScreen->ChangeWindowAttributes(pWin, vmask);
    299     SCREEN_WRAP(pScreen, ChangeWindowAttributes);
    300 
    301     if (WINREC(pWin)) {
    302         // disallow ParentRelative background state
    303         if (pWin->backgroundState == ParentRelative) {
    304             XID pixel = 0;
    305 
    306             ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
    307         }
    308     }
    309 
    310     RL_DEBUG_MSG("change window attributes end\n");
    311     return result;
    312 }
    313 
    314 /*
    315  * RootlessPositionWindow
    316  *  This is a hook for when DIX moves or resizes a window.
    317  *  Update the frame position now although the physical window is moved
    318  *  in RootlessMoveWindow. (x, y) are *inside* position. After this,
    319  *  mi and fb are expecting the pixmap to be at the new location.
    320  */
    321 Bool
    322 RootlessPositionWindow(WindowPtr pWin, int x, int y)
    323 {
    324     ScreenPtr pScreen = pWin->drawable.pScreen;
    325     RootlessWindowRec *winRec = WINREC(pWin);
    326     Bool result;
    327 
    328     RL_DEBUG_MSG("positionwindow start (win 0x%x @ %i, %i)\n", pWin, x, y);
    329 
    330     if (winRec) {
    331         if (winRec->is_drawing) {
    332             // Reset frame's pixmap and move it to the new position.
    333             int bw = wBorderWidth(pWin);
    334 
    335             winRec->pixmap->devPrivate.ptr = winRec->pixelData;
    336             SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw);
    337         }
    338     }
    339 
    340     SCREEN_UNWRAP(pScreen, PositionWindow);
    341     result = pScreen->PositionWindow(pWin, x, y);
    342     SCREEN_WRAP(pScreen, PositionWindow);
    343 
    344     RL_DEBUG_MSG("positionwindow end\n");
    345     return result;
    346 }
    347 
    348 /*
    349  * RootlessInitializeFrame
    350  *  Initialize some basic attributes of the frame. Note that winRec
    351  *  may already have valid data in it, so don't overwrite anything
    352  *  valuable.
    353  */
    354 static void
    355 RootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec * winRec)
    356 {
    357     DrawablePtr d = &pWin->drawable;
    358     int bw = wBorderWidth(pWin);
    359 
    360     winRec->win = pWin;
    361 
    362     winRec->x = d->x - bw;
    363     winRec->y = d->y - bw;
    364     winRec->width = d->width + 2 * bw;
    365     winRec->height = d->height + 2 * bw;
    366     winRec->borderWidth = bw;
    367 }
    368 
    369 /*
    370  * RootlessEnsureFrame
    371  *  Make sure the given window is framed. If the window doesn't have a
    372  *  physical window associated with it, attempt to create one. If that
    373  *  is unsuccessful, return NULL.
    374  */
    375 static RootlessWindowRec *
    376 RootlessEnsureFrame(WindowPtr pWin)
    377 {
    378     ScreenPtr pScreen = pWin->drawable.pScreen;
    379     RootlessWindowRec *winRec;
    380     RegionRec shape;
    381     RegionPtr pShape = NULL;
    382 
    383     if (WINREC(pWin) != NULL)
    384         return WINREC(pWin);
    385 
    386     if (!IsTopLevel(pWin) && !IsRoot(pWin))
    387         return NULL;
    388 
    389     if (pWin->drawable.class != InputOutput)
    390         return NULL;
    391 
    392     winRec = malloc(sizeof(RootlessWindowRec));
    393 
    394     if (!winRec)
    395         return NULL;
    396 
    397     RootlessInitializeFrame(pWin, winRec);
    398 
    399     winRec->is_drawing = FALSE;
    400     winRec->is_reorder_pending = FALSE;
    401     winRec->pixmap = NULL;
    402     winRec->wid = NULL;
    403     winRec->level = 0;
    404 
    405     SETWINREC(pWin, winRec);
    406 
    407     // Set the frame's shape if the window is shaped
    408     if (RootlessGetShape(pWin, &shape))
    409         pShape = &shape;
    410 
    411     RL_DEBUG_MSG("creating frame ");
    412 
    413     if (!SCREENREC(pScreen)->imp->CreateFrame(winRec, pScreen,
    414                                               winRec->x + SCREEN_TO_GLOBAL_X,
    415                                               winRec->y + SCREEN_TO_GLOBAL_Y,
    416                                               pShape)) {
    417         RL_DEBUG_MSG("implementation failed to create frame!\n");
    418         free(winRec);
    419         SETWINREC(pWin, NULL);
    420         return NULL;
    421     }
    422 
    423     if (pWin->drawable.depth == 8)
    424         RootlessFlushWindowColormap(pWin);
    425 
    426     if (pShape != NULL)
    427         RegionUninit(&shape);
    428 
    429     return winRec;
    430 }
    431 
    432 /*
    433  * RootlessRealizeWindow
    434  *  The frame is usually created here and not in CreateWindow so that
    435  *  windows do not eat memory until they are realized.
    436  */
    437 Bool
    438 RootlessRealizeWindow(WindowPtr pWin)
    439 {
    440     Bool result;
    441     RegionRec saveRoot;
    442     ScreenPtr pScreen = pWin->drawable.pScreen;
    443 
    444     RL_DEBUG_MSG("realizewindow start (win 0x%x) ", pWin);
    445 
    446     if ((IsTopLevel(pWin) && pWin->drawable.class == InputOutput)) {
    447         RootlessWindowRec *winRec;
    448 
    449         winRec = RootlessEnsureFrame(pWin);
    450         if (winRec == NULL)
    451             return FALSE;
    452 
    453         winRec->is_reorder_pending = TRUE;
    454 
    455         RL_DEBUG_MSG("Top level window ");
    456 
    457         // Disallow ParentRelative background state on top-level windows.
    458         // This might have been set before the window was mapped.
    459         if (pWin->backgroundState == ParentRelative) {
    460             XID pixel = 0;
    461 
    462             ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
    463         }
    464     }
    465 
    466     if (!IsRoot(pWin))
    467         HUGE_ROOT(pWin);
    468     SCREEN_UNWRAP(pScreen, RealizeWindow);
    469     result = pScreen->RealizeWindow(pWin);
    470     SCREEN_WRAP(pScreen, RealizeWindow);
    471     if (!IsRoot(pWin))
    472         NORMAL_ROOT(pWin);
    473 
    474     RL_DEBUG_MSG("realizewindow end\n");
    475     return result;
    476 }
    477 
    478 /*
    479  * RootlessFrameForWindow
    480  *  Returns the frame ID for the physical window displaying the given window.
    481  *  If CREATE is true and the window has no frame, attempt to create one.
    482  */
    483 RootlessFrameID
    484 RootlessFrameForWindow(WindowPtr pWin, Bool create)
    485 {
    486     WindowPtr pTopWin;
    487     RootlessWindowRec *winRec;
    488 
    489     pTopWin = TopLevelParent(pWin);
    490     if (pTopWin == NULL)
    491         return NULL;
    492 
    493     winRec = WINREC(pTopWin);
    494 
    495     if (winRec == NULL && create && pWin->drawable.class == InputOutput) {
    496         winRec = RootlessEnsureFrame(pTopWin);
    497     }
    498 
    499     if (winRec == NULL)
    500         return NULL;
    501 
    502     return winRec->wid;
    503 }
    504 
    505 /*
    506  * RootlessUnrealizeWindow
    507  *  Unmap the physical window.
    508  */
    509 Bool
    510 RootlessUnrealizeWindow(WindowPtr pWin)
    511 {
    512     ScreenPtr pScreen = pWin->drawable.pScreen;
    513     RootlessWindowRec *winRec = WINREC(pWin);
    514     Bool result;
    515 
    516     RL_DEBUG_MSG("unrealizewindow start ");
    517 
    518     if (winRec) {
    519         RootlessStopDrawing(pWin, FALSE);
    520 
    521         SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid);
    522 
    523         winRec->is_reorder_pending = FALSE;
    524     }
    525 
    526     SCREEN_UNWRAP(pScreen, UnrealizeWindow);
    527     result = pScreen->UnrealizeWindow(pWin);
    528     SCREEN_WRAP(pScreen, UnrealizeWindow);
    529 
    530     RL_DEBUG_MSG("unrealizewindow end\n");
    531     return result;
    532 }
    533 
    534 /*
    535  * RootlessReorderWindow
    536  *  Reorder the frame associated with the given window so that it's
    537  *  physically above the window below it in the X stacking order.
    538  */
    539 void
    540 RootlessReorderWindow(WindowPtr pWin)
    541 {
    542     RootlessWindowRec *winRec = WINREC(pWin);
    543 
    544     if (pWin->realized && winRec != NULL && !winRec->is_reorder_pending &&
    545         !windows_hidden) {
    546         WindowPtr newPrevW;
    547         RootlessWindowRec *newPrev;
    548         RootlessFrameID newPrevID;
    549         ScreenPtr pScreen = pWin->drawable.pScreen;
    550 
    551         /* Check if the implementation wants the frame to not be reordered
    552            even though the X11 window is restacked. This can be useful if
    553            frames are ordered-in with animation so that the reordering is not
    554            done until the animation is complete. */
    555         if (SCREENREC(pScreen)->imp->DoReorderWindow) {
    556             if (!SCREENREC(pScreen)->imp->DoReorderWindow(winRec))
    557                 return;
    558         }
    559 
    560         RootlessStopDrawing(pWin, FALSE);
    561 
    562         /* Find the next window above this one that has a mapped frame.
    563          * Only include cases where the windows are in the same category of
    564          * hittability to ensure offscreen windows don't get restacked
    565          * relative to onscreen ones (but that the offscreen ones maintain
    566          * their stacking order if they are explicitly asked to Reorder).
    567          */
    568 
    569         newPrevW = pWin->prevSib;
    570         while (newPrevW &&
    571                (WINREC(newPrevW) == NULL || !newPrevW->realized ||
    572                 newPrevW->unhittable != pWin->unhittable))
    573             newPrevW = newPrevW->prevSib;
    574 
    575         newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL;
    576         newPrevID = newPrev != NULL ? newPrev->wid : 0;
    577 
    578         /* If it exists, reorder the frame above us first. */
    579 
    580         if (newPrev && newPrev->is_reorder_pending) {
    581             newPrev->is_reorder_pending = FALSE;
    582             RootlessReorderWindow(newPrevW);
    583         }
    584 
    585         SCREENREC(pScreen)->imp->RestackFrame(winRec->wid, newPrevID);
    586     }
    587 }
    588 
    589 /*
    590  * RootlessRestackWindow
    591  *  This is a hook for when DIX changes the window stacking order.
    592  *  The window has already been inserted into its new position in the
    593  *  DIX window stack. We need to change the order of the physical
    594  *  window to match.
    595  */
    596 void
    597 RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib)
    598 {
    599     RegionRec saveRoot;
    600     RootlessWindowRec *winRec = WINREC(pWin);
    601     ScreenPtr pScreen = pWin->drawable.pScreen;
    602 
    603     RL_DEBUG_MSG("restackwindow start ");
    604     if (winRec)
    605         RL_DEBUG_MSG("restack top level \n");
    606 
    607     HUGE_ROOT(pWin);
    608     SCREEN_UNWRAP(pScreen, RestackWindow);
    609 
    610     if (pScreen->RestackWindow)
    611         pScreen->RestackWindow(pWin, pOldNextSib);
    612 
    613     SCREEN_WRAP(pScreen, RestackWindow);
    614     NORMAL_ROOT(pWin);
    615 
    616     if (winRec && pWin->viewable) {
    617         RootlessReorderWindow(pWin);
    618     }
    619 
    620     RL_DEBUG_MSG("restackwindow end\n");
    621 }
    622 
    623 /*
    624  * Specialized window copy procedures
    625  */
    626 
    627 // Globals needed during window resize and move.
    628 static void *gResizeDeathBits = NULL;
    629 static int gResizeDeathCount = 0;
    630 static PixmapPtr gResizeDeathPix[2] = { NULL, NULL };
    631 
    632 static BoxRec gResizeDeathBounds[2];
    633 static CopyWindowProcPtr gResizeOldCopyWindowProc = NULL;
    634 
    635 /*
    636  * RootlessNoCopyWindow
    637  *  CopyWindow() that doesn't do anything. For MoveWindow() of
    638  *  top-level windows.
    639  */
    640 static void
    641 RootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
    642 {
    643     // some code expects the region to be translated
    644     int dx = ptOldOrg.x - pWin->drawable.x;
    645     int dy = ptOldOrg.y - pWin->drawable.y;
    646 
    647     RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW ");
    648 
    649     RegionTranslate(prgnSrc, -dx, -dy);
    650 }
    651 
    652 /*
    653  * RootlessResizeCopyWindow
    654  *  CopyWindow used during ResizeWindow for gravity moves. Based on
    655  *  fbCopyWindow. The original always draws on the root pixmap, which
    656  *  we don't have. Instead, draw on the parent window's pixmap.
    657  *  Resize version: the old location's pixels are in gResizeCopyWindowSource.
    658  */
    659 static void
    660 RootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
    661                          RegionPtr prgnSrc)
    662 {
    663     ScreenPtr pScreen = pWin->drawable.pScreen;
    664     RegionRec rgnDst;
    665     int dx, dy;
    666 
    667     RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin);
    668 
    669     /* Don't unwrap pScreen->CopyWindow.
    670        The bogus rewrap with RootlessCopyWindow causes a crash if
    671        CopyWindow is called again during the same resize. */
    672 
    673     if (gResizeDeathCount == 0)
    674         return;
    675 
    676     RootlessStartDrawing(pWin);
    677 
    678     dx = ptOldOrg.x - pWin->drawable.x;
    679     dy = ptOldOrg.y - pWin->drawable.y;
    680     RegionTranslate(prgnSrc, -dx, -dy);
    681     RegionNull(&rgnDst);
    682     RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
    683 
    684     if (gResizeDeathCount == 1) {
    685         /* Simple case, we only have a single source pixmap. */
    686 
    687         miCopyRegion(&gResizeDeathPix[0]->drawable,
    688                      &pScreen->GetWindowPixmap(pWin)->drawable, 0,
    689                      &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
    690     }
    691     else {
    692         int i;
    693         RegionRec clip, clipped;
    694 
    695         /* More complex case, N source pixmaps (usually two). So we
    696            intersect the destination with each source and copy those bits. */
    697 
    698         for (i = 0; i < gResizeDeathCount; i++) {
    699             RegionInit(&clip, gResizeDeathBounds + 0, 1);
    700             RegionNull(&clipped);
    701             RegionIntersect(&rgnDst, &clip, &clipped);
    702 
    703             miCopyRegion(&gResizeDeathPix[i]->drawable,
    704                          &pScreen->GetWindowPixmap(pWin)->drawable, 0,
    705                          &clipped, dx, dy, fbCopyWindowProc, 0, 0);
    706 
    707             RegionUninit(&clipped);
    708             RegionUninit(&clip);
    709         }
    710     }
    711 
    712     /* Don't update - resize will update everything */
    713     RegionUninit(&rgnDst);
    714 
    715     fbValidateDrawable(&pWin->drawable);
    716 
    717     RL_DEBUG_MSG("resizecopywindowFB end\n");
    718 }
    719 
    720 /*
    721  * RootlessCopyWindow
    722  *  Update *new* location of window. Old location is redrawn with
    723  *  PaintWindow. Cloned from fbCopyWindow.
    724  *  The original always draws on the root pixmap, which we don't have.
    725  *  Instead, draw on the parent window's pixmap.
    726  */
    727 void
    728 RootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
    729 {
    730     ScreenPtr pScreen = pWin->drawable.pScreen;
    731     RegionRec rgnDst;
    732     int dx, dy;
    733     BoxPtr extents;
    734     int area;
    735 
    736     RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin);
    737 
    738     SCREEN_UNWRAP(pScreen, CopyWindow);
    739 
    740     dx = ptOldOrg.x - pWin->drawable.x;
    741     dy = ptOldOrg.y - pWin->drawable.y;
    742     RegionTranslate(prgnSrc, -dx, -dy);
    743 
    744     RegionNull(&rgnDst);
    745     RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
    746 
    747     extents = RegionExtents(&rgnDst);
    748     area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1);
    749 
    750     /* If the area exceeds threshold, use the implementation's
    751        accelerated version. */
    752     if (area > rootless_CopyWindow_threshold &&
    753         SCREENREC(pScreen)->imp->CopyWindow) {
    754         RootlessWindowRec *winRec;
    755         WindowPtr top;
    756 
    757         top = TopLevelParent(pWin);
    758         if (top == NULL) {
    759             RL_DEBUG_MSG("no parent\n");
    760             goto out;
    761         }
    762 
    763         winRec = WINREC(top);
    764         if (winRec == NULL) {
    765             RL_DEBUG_MSG("not framed\n");
    766             goto out;
    767         }
    768 
    769         /* Move region to window local coords */
    770         RegionTranslate(&rgnDst, -winRec->x, -winRec->y);
    771 
    772         RootlessStopDrawing(pWin, FALSE);
    773 
    774         SCREENREC(pScreen)->imp->CopyWindow(winRec->wid,
    775                                             RegionNumRects(&rgnDst),
    776                                             RegionRects(&rgnDst), dx, dy);
    777     }
    778     else {
    779         RootlessStartDrawing(pWin);
    780 
    781         miCopyRegion((DrawablePtr) pWin, (DrawablePtr) pWin,
    782                      0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
    783 
    784         /* prgnSrc has been translated to dst position */
    785         RootlessDamageRegion(pWin, prgnSrc);
    786     }
    787 
    788  out:
    789     RegionUninit(&rgnDst);
    790     fbValidateDrawable(&pWin->drawable);
    791 
    792     SCREEN_WRAP(pScreen, CopyWindow);
    793 
    794     RL_DEBUG_MSG("copywindowFB end\n");
    795 }
    796 
    797 void
    798 RootlessPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
    799 {
    800     ScreenPtr pScreen = pWin->drawable.pScreen;
    801 
    802     if (IsFramedWindow(pWin)) {
    803         RootlessStartDrawing(pWin);
    804         RootlessDamageRegion(pWin, prgn);
    805 
    806         if (pWin->backgroundState == ParentRelative) {
    807             if ((what == PW_BACKGROUND) ||
    808                 (what == PW_BORDER && !pWin->borderIsPixel))
    809                 RootlessSetPixmapOfAncestors(pWin);
    810         }
    811     }
    812 
    813     SCREEN_UNWRAP(pScreen, PaintWindow);
    814     pScreen->PaintWindow(pWin, prgn, what);
    815     SCREEN_WRAP(pScreen, PaintWindow);
    816 }
    817 
    818 /*
    819  * Window resize procedures
    820  */
    821 
    822 enum {
    823     WIDTH_SMALLER = 1,
    824     HEIGHT_SMALLER = 2,
    825 };
    826 
    827 /*
    828  * ResizeWeighting
    829  *  Choose gravity to avoid local copies. Do that by looking for
    830  *  a corner that doesn't move _relative to the screen_.
    831  */
    832 static inline unsigned int
    833 ResizeWeighting(int oldX1, int oldY1, int oldX2, int oldY2, int oldBW,
    834                 int newX1, int newY1, int newX2, int newY2, int newBW)
    835 {
    836 #ifdef ROOTLESS_RESIZE_GRAVITY
    837     if (newBW != oldBW)
    838         return RL_GRAVITY_NONE;
    839 
    840     if (newX1 == oldX1 && newY1 == oldY1)
    841         return RL_GRAVITY_NORTH_WEST;
    842     else if (newX1 == oldX1 && newY2 == oldY2)
    843         return RL_GRAVITY_SOUTH_WEST;
    844     else if (newX2 == oldX2 && newY2 == oldY2)
    845         return RL_GRAVITY_SOUTH_EAST;
    846     else if (newX2 == oldX2 && newY1 == oldY1)
    847         return RL_GRAVITY_NORTH_EAST;
    848     else
    849         return RL_GRAVITY_NONE;
    850 #else
    851     return RL_GRAVITY_NONE;
    852 #endif
    853 }
    854 
    855 /*
    856  * StartFrameResize
    857  *  Prepare to resize a top-level window. The old window's pixels are
    858  *  saved and the implementation is told to change the window size.
    859  *  (x,y,w,h) is outer frame of window (outside border)
    860  */
    861 static Bool
    862 StartFrameResize(WindowPtr pWin, Bool gravity,
    863                  int oldX, int oldY, int oldW, int oldH, int oldBW,
    864                  int newX, int newY, int newW, int newH, int newBW)
    865 {
    866     ScreenPtr pScreen = pWin->drawable.pScreen;
    867     RootlessWindowRec *winRec = WINREC(pWin);
    868     Bool need_window_source = FALSE, resize_after = FALSE;
    869 
    870     BoxRec rect;
    871     int oldX2, newX2;
    872     int oldY2, newY2;
    873     unsigned int weight;
    874 
    875     oldX2 = oldX + oldW, newX2 = newX + newW;
    876     oldY2 = oldY + oldH, newY2 = newY + newH;
    877 
    878     /* Decide which resize weighting to use */
    879     weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW,
    880                              newX, newY, newW, newH, newBW);
    881 
    882     /* Compute intersection between old and new rects */
    883     rect.x1 = max(oldX, newX);
    884     rect.y1 = max(oldY, newY);
    885     rect.x2 = min(oldX2, newX2);
    886     rect.y2 = min(oldY2, newY2);
    887 
    888     RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity);
    889     RL_DEBUG_MSG("%d %d %d %d %d   %d %d %d %d %d\n",
    890                  oldX, oldY, oldW, oldH, oldBW, newX, newY, newW, newH, newBW);
    891 
    892     RootlessRedisplay(pWin);
    893 
    894     /* If gravity is true, then we need to have a way of recovering all
    895        the original bits in the window for when X rearranges the contents
    896        based on the various gravity settings. The obvious way is to just
    897        snapshot the entire backing store before resizing it, but that
    898        it slow on large windows.
    899 
    900        So the optimization here is to use the implementation's resize
    901        weighting options (if available) to allow us to reason about what
    902        is left in the backing store after the resize. We can then only
    903        copy what won't be there after the resize, and do a two-stage copy
    904        operation.
    905 
    906        Most of these optimizations are only applied when the top-left
    907        corner of the window is fixed, since that's the common case. They
    908        could probably be extended with some thought. */
    909 
    910     gResizeDeathCount = 0;
    911 
    912     if (gravity && weight == RL_GRAVITY_NORTH_WEST) {
    913         unsigned int code = 0;
    914 
    915         /* Top left corner is anchored. We never need to copy the
    916            entire window. */
    917 
    918         need_window_source = TRUE;
    919 
    920         /* These comparisons were chosen to avoid setting bits when the sizes
    921            are the same. (So the fastest case automatically gets taken when
    922            dimensions are unchanging.) */
    923 
    924         if (newW < oldW)
    925             code |= WIDTH_SMALLER;
    926         if (newH < oldH)
    927             code |= HEIGHT_SMALLER;
    928 
    929         if (((code ^ (code >> 1)) & 1) == 0) {
    930             /* Both dimensions are either getting larger, or both
    931                are getting smaller. No need to copy anything. */
    932 
    933             if (code == (WIDTH_SMALLER | HEIGHT_SMALLER)) {
    934                 /* Since the window is getting smaller, we can do gravity
    935                    repair on it with its current size, then resize it
    936                    afterwards. */
    937 
    938                 resize_after = TRUE;
    939             }
    940 
    941             gResizeDeathCount = 1;
    942         }
    943         else {
    944             unsigned int copy_rowbytes, Bpp;
    945             unsigned int copy_rect_width, copy_rect_height;
    946             BoxRec copy_rect;
    947 
    948             /* We can get away with a partial copy. 'rect' is the
    949                intersection between old and new bounds, so copy
    950                everything to the right of or below the intersection. */
    951 
    952             RootlessStartDrawing(pWin);
    953 
    954             if (code == WIDTH_SMALLER) {
    955                 copy_rect.x1 = rect.x2;
    956                 copy_rect.y1 = rect.y1;
    957                 copy_rect.x2 = oldX2;
    958                 copy_rect.y2 = oldY2;
    959             }
    960             else if (code == HEIGHT_SMALLER) {
    961                 copy_rect.x1 = rect.x1;
    962                 copy_rect.y1 = rect.y2;
    963                 copy_rect.x2 = oldX2;
    964                 copy_rect.y2 = oldY2;
    965             }
    966             else
    967                 OsAbort();
    968 
    969             Bpp = winRec->win->drawable.bitsPerPixel / 8;
    970             copy_rect_width = copy_rect.x2 - copy_rect.x1;
    971             copy_rect_height = copy_rect.y2 - copy_rect.y1;
    972             copy_rowbytes = ((copy_rect_width * Bpp) + 31) & ~31;
    973             gResizeDeathBits = xallocarray(copy_rowbytes, copy_rect_height);
    974 
    975             if (copy_rect_width * copy_rect_height >
    976                 rootless_CopyBytes_threshold &&
    977                 SCREENREC(pScreen)->imp->CopyBytes) {
    978                 SCREENREC(pScreen)->imp->CopyBytes(copy_rect_width * Bpp,
    979                                                    copy_rect_height,
    980                                                    ((char *) winRec->pixelData)
    981                                                    +
    982                                                    ((copy_rect.y1 -
    983                                                      oldY) *
    984                                                     winRec->bytesPerRow)
    985                                                    + (copy_rect.x1 -
    986                                                       oldX) * Bpp,
    987                                                    winRec->bytesPerRow,
    988                                                    gResizeDeathBits,
    989                                                    copy_rowbytes);
    990             }
    991             else {
    992                 fbBlt((FbBits *) (winRec->pixelData
    993                                   +
    994                                   ((copy_rect.y1 - oldY) * winRec->bytesPerRow)
    995                                   + (copy_rect.x1 - oldX) * Bpp),
    996                       winRec->bytesPerRow / sizeof(FbBits), 0,
    997                       (FbBits *) gResizeDeathBits,
    998                       copy_rowbytes / sizeof(FbBits), 0, copy_rect_width * Bpp,
    999                       copy_rect_height, GXcopy, FB_ALLONES, Bpp, 0, 0);
   1000             }
   1001 
   1002             gResizeDeathBounds[1] = copy_rect;
   1003             gResizeDeathPix[1]
   1004                 = GetScratchPixmapHeader(pScreen, copy_rect_width,
   1005                                          copy_rect_height,
   1006                                          winRec->win->drawable.depth,
   1007                                          winRec->win->drawable.bitsPerPixel,
   1008                                          winRec->bytesPerRow,
   1009                                          (void *) gResizeDeathBits);
   1010 
   1011             SetPixmapBaseToScreen(gResizeDeathPix[1],
   1012                                   copy_rect.x1, copy_rect.y1);
   1013 
   1014             gResizeDeathCount = 2;
   1015         }
   1016     }
   1017     else if (gravity) {
   1018         /* The general case. Just copy everything. */
   1019 
   1020         RootlessStartDrawing(pWin);
   1021 
   1022         gResizeDeathBits = xallocarray(winRec->bytesPerRow, winRec->height);
   1023 
   1024         memcpy(gResizeDeathBits, winRec->pixelData,
   1025                winRec->bytesPerRow * winRec->height);
   1026 
   1027         gResizeDeathBounds[0] = (BoxRec) {
   1028         oldX, oldY, oldX2, oldY2};
   1029         gResizeDeathPix[0]
   1030             = GetScratchPixmapHeader(pScreen, winRec->width,
   1031                                      winRec->height,
   1032                                      winRec->win->drawable.depth,
   1033                                      winRec->win->drawable.bitsPerPixel,
   1034                                      winRec->bytesPerRow,
   1035                                      (void *) gResizeDeathBits);
   1036 
   1037         SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY);
   1038         gResizeDeathCount = 1;
   1039     }
   1040 
   1041     RootlessStopDrawing(pWin, FALSE);
   1042 
   1043     winRec->x = newX;
   1044     winRec->y = newY;
   1045     winRec->width = newW;
   1046     winRec->height = newH;
   1047     winRec->borderWidth = newBW;
   1048 
   1049     /* Unless both dimensions are getting smaller, Resize the frame
   1050        before doing gravity repair */
   1051 
   1052     if (!resize_after) {
   1053         SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
   1054                                              newX + SCREEN_TO_GLOBAL_X,
   1055                                              newY + SCREEN_TO_GLOBAL_Y,
   1056                                              newW, newH, weight);
   1057     }
   1058 
   1059     RootlessStartDrawing(pWin);
   1060 
   1061     /* If necessary, create a source pixmap pointing at the current
   1062        window bits. */
   1063 
   1064     if (need_window_source) {
   1065         gResizeDeathBounds[0] = (BoxRec) {
   1066         oldX, oldY, oldX2, oldY2};
   1067         gResizeDeathPix[0]
   1068             = GetScratchPixmapHeader(pScreen, oldW, oldH,
   1069                                      winRec->win->drawable.depth,
   1070                                      winRec->win->drawable.bitsPerPixel,
   1071                                      winRec->bytesPerRow, winRec->pixelData);
   1072 
   1073         SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY);
   1074     }
   1075 
   1076     /* Use custom CopyWindow when moving gravity bits around
   1077        ResizeWindow assumes the old window contents are in the same
   1078        pixmap, but here they're in deathPix instead. */
   1079 
   1080     if (gravity) {
   1081         gResizeOldCopyWindowProc = pScreen->CopyWindow;
   1082         pScreen->CopyWindow = RootlessResizeCopyWindow;
   1083     }
   1084 
   1085     /* If we can't rely on the window server preserving the bits we
   1086        need in the position we need, copy the pixels in the
   1087        intersection from src to dst. ResizeWindow assumes these pixels
   1088        are already present when making gravity adjustments. pWin
   1089        currently has new-sized pixmap but is in old position.
   1090 
   1091        FIXME: border width change! (?) */
   1092 
   1093     if (gravity && weight == RL_GRAVITY_NONE) {
   1094         PixmapPtr src, dst;
   1095 
   1096         assert(gResizeDeathCount == 1);
   1097 
   1098         src = gResizeDeathPix[0];
   1099         dst = pScreen->GetWindowPixmap(pWin);
   1100 
   1101         RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n",
   1102                      rect.x1, rect.y1, rect.x2, rect.y2);
   1103 
   1104         /* rect is the intersection of the old location and new location */
   1105         if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL) {
   1106             /* The window drawable still has the old frame position, which
   1107                means that DST doesn't actually point at the origin of our
   1108                physical backing store when adjusted by the drawable.x,y
   1109                position. So sneakily adjust it temporarily while copying.. */
   1110 
   1111             ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData;
   1112             SetPixmapBaseToScreen(dst, newX, newY);
   1113 
   1114             fbCopyWindowProc(&src->drawable, &dst->drawable, NULL,
   1115                              &rect, 1, 0, 0, FALSE, FALSE, 0, 0);
   1116 
   1117             ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData;
   1118             SetPixmapBaseToScreen(dst, oldX, oldY);
   1119         }
   1120     }
   1121 
   1122     return resize_after;
   1123 }
   1124 
   1125 static void
   1126 FinishFrameResize(WindowPtr pWin, Bool gravity, int oldX, int oldY,
   1127                   unsigned int oldW, unsigned int oldH, unsigned int oldBW,
   1128                   int newX, int newY, unsigned int newW, unsigned int newH,
   1129                   unsigned int newBW, Bool resize_now)
   1130 {
   1131     ScreenPtr pScreen = pWin->drawable.pScreen;
   1132     RootlessWindowRec *winRec = WINREC(pWin);
   1133     int i;
   1134 
   1135     RootlessStopDrawing(pWin, FALSE);
   1136 
   1137     if (resize_now) {
   1138         unsigned int weight;
   1139 
   1140         /* We didn't resize anything earlier, so do it now, now that
   1141            we've finished gravitating the bits. */
   1142 
   1143         weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW,
   1144                                  newX, newY, newW, newH, newBW);
   1145 
   1146         SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
   1147                                              newX + SCREEN_TO_GLOBAL_X,
   1148                                              newY + SCREEN_TO_GLOBAL_Y,
   1149                                              newW, newH, weight);
   1150     }
   1151 
   1152     /* Redraw everything. FIXME: there must be times when we don't need
   1153        to do this. Perhaps when top-left weighting and no gravity? */
   1154 
   1155     RootlessDamageRect(pWin, -newBW, -newBW, newW, newH);
   1156 
   1157     for (i = 0; i < 2; i++) {
   1158         if (gResizeDeathPix[i] != NULL) {
   1159             FreeScratchPixmapHeader(gResizeDeathPix[i]);
   1160             gResizeDeathPix[i] = NULL;
   1161         }
   1162     }
   1163 
   1164     free(gResizeDeathBits);
   1165     gResizeDeathBits = NULL;
   1166 
   1167     if (gravity) {
   1168         pScreen->CopyWindow = gResizeOldCopyWindowProc;
   1169     }
   1170 }
   1171 
   1172 /*
   1173  * RootlessMoveWindow
   1174  *  If kind==VTOther, window border is resizing (and borderWidth is
   1175  *  already changed!!@#$)  This case works like window resize, not move.
   1176  */
   1177 void
   1178 RootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
   1179 {
   1180     RootlessWindowRec *winRec = WINREC(pWin);
   1181     ScreenPtr pScreen = pWin->drawable.pScreen;
   1182     CopyWindowProcPtr oldCopyWindowProc = NULL;
   1183     int oldX = 0, oldY = 0, newX = 0, newY = 0;
   1184     unsigned int oldW = 0, oldH = 0, oldBW = 0;
   1185     unsigned int newW = 0, newH = 0, newBW = 0;
   1186     Bool resize_after = FALSE;
   1187     RegionRec saveRoot;
   1188 
   1189     RL_DEBUG_MSG("movewindow start \n");
   1190 
   1191     if (winRec) {
   1192         if (kind == VTMove) {
   1193             oldX = winRec->x;
   1194             oldY = winRec->y;
   1195             RootlessRedisplay(pWin);
   1196             RootlessStartDrawing(pWin);
   1197         }
   1198         else {
   1199             RL_DEBUG_MSG("movewindow border resizing ");
   1200 
   1201             oldBW = winRec->borderWidth;
   1202             oldX = winRec->x;
   1203             oldY = winRec->y;
   1204             oldW = winRec->width;
   1205             oldH = winRec->height;
   1206 
   1207             newBW = wBorderWidth(pWin);
   1208             newX = x;
   1209             newY = y;
   1210             newW = pWin->drawable.width + 2 * newBW;
   1211             newH = pWin->drawable.height + 2 * newBW;
   1212 
   1213             resize_after = StartFrameResize(pWin, FALSE,
   1214                                             oldX, oldY, oldW, oldH, oldBW,
   1215                                             newX, newY, newW, newH, newBW);
   1216         }
   1217     }
   1218 
   1219     HUGE_ROOT(pWin);
   1220     SCREEN_UNWRAP(pScreen, MoveWindow);
   1221 
   1222     if (winRec) {
   1223         oldCopyWindowProc = pScreen->CopyWindow;
   1224         pScreen->CopyWindow = RootlessNoCopyWindow;
   1225     }
   1226     pScreen->MoveWindow(pWin, x, y, pSib, kind);
   1227     if (winRec) {
   1228         pScreen->CopyWindow = oldCopyWindowProc;
   1229     }
   1230 
   1231     NORMAL_ROOT(pWin);
   1232     SCREEN_WRAP(pScreen, MoveWindow);
   1233 
   1234     if (winRec) {
   1235         if (kind == VTMove) {
   1236             winRec->x = x;
   1237             winRec->y = y;
   1238             RootlessStopDrawing(pWin, FALSE);
   1239             SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen,
   1240                                                x + SCREEN_TO_GLOBAL_X,
   1241                                                y + SCREEN_TO_GLOBAL_Y);
   1242         }
   1243         else {
   1244             FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
   1245                               newX, newY, newW, newH, newBW, resize_after);
   1246         }
   1247     }
   1248 
   1249     RL_DEBUG_MSG("movewindow end\n");
   1250 }
   1251 
   1252 /*
   1253  * RootlessResizeWindow
   1254  *  Note: (x, y, w, h) as passed to this procedure don't match the frame
   1255  *  definition. (x,y) is corner of very outer edge, *outside* border.
   1256  *  w,h is width and height *inside* border, *ignoring* border width.
   1257  *  The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw)
   1258  *  is total rect and (x+bw, y+bw, w, h) is inner rect.
   1259  */
   1260 void
   1261 RootlessResizeWindow(WindowPtr pWin, int x, int y,
   1262                      unsigned int w, unsigned int h, WindowPtr pSib)
   1263 {
   1264     RootlessWindowRec *winRec = WINREC(pWin);
   1265     ScreenPtr pScreen = pWin->drawable.pScreen;
   1266     int oldX = 0, oldY = 0, newX = 0, newY = 0;
   1267     unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0;
   1268     Bool resize_after = FALSE;
   1269     RegionRec saveRoot;
   1270 
   1271     RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin);
   1272 
   1273     if (pWin->parent) {
   1274         if (winRec) {
   1275             oldBW = winRec->borderWidth;
   1276             oldX = winRec->x;
   1277             oldY = winRec->y;
   1278             oldW = winRec->width;
   1279             oldH = winRec->height;
   1280 
   1281             newBW = oldBW;
   1282             newX = x;
   1283             newY = y;
   1284             newW = w + 2 * newBW;
   1285             newH = h + 2 * newBW;
   1286 
   1287             resize_after = StartFrameResize(pWin, TRUE,
   1288                                             oldX, oldY, oldW, oldH, oldBW,
   1289                                             newX, newY, newW, newH, newBW);
   1290         }
   1291 
   1292         HUGE_ROOT(pWin);
   1293         SCREEN_UNWRAP(pScreen, ResizeWindow);
   1294         pScreen->ResizeWindow(pWin, x, y, w, h, pSib);
   1295         SCREEN_WRAP(pScreen, ResizeWindow);
   1296         NORMAL_ROOT(pWin);
   1297 
   1298         if (winRec) {
   1299             FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
   1300                               newX, newY, newW, newH, newBW, resize_after);
   1301         }
   1302     }
   1303     else {
   1304         /* Special case for resizing the root window */
   1305         BoxRec box;
   1306 
   1307         pWin->drawable.x = x;
   1308         pWin->drawable.y = y;
   1309         pWin->drawable.width = w;
   1310         pWin->drawable.height = h;
   1311 
   1312         box.x1 = x;
   1313         box.y1 = y;
   1314         box.x2 = x + w;
   1315         box.y2 = y + h;
   1316         RegionUninit(&pWin->winSize);
   1317         RegionInit(&pWin->winSize, &box, 1);
   1318         RegionCopy(&pWin->borderSize, &pWin->winSize);
   1319         RegionCopy(&pWin->clipList, &pWin->winSize);
   1320         RegionCopy(&pWin->borderClip, &pWin->winSize);
   1321 
   1322         if (winRec) {
   1323             SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
   1324                                                  x + SCREEN_TO_GLOBAL_X,
   1325                                                  y + SCREEN_TO_GLOBAL_Y,
   1326                                                  w, h, RL_GRAVITY_NONE);
   1327         }
   1328 
   1329         miSendExposures(pWin, &pWin->borderClip,
   1330                         pWin->drawable.x, pWin->drawable.y);
   1331     }
   1332 
   1333     RL_DEBUG_MSG("resizewindow end\n");
   1334 }
   1335 
   1336 /*
   1337  * RootlessRepositionWindow
   1338  *  Called by the implementation when a window needs to be repositioned to
   1339  *  its correct location on the screen. This routine is typically needed
   1340  *  due to changes in the underlying window system, such as a screen layout
   1341  *  change.
   1342  */
   1343 void
   1344 RootlessRepositionWindow(WindowPtr pWin)
   1345 {
   1346     RootlessWindowRec *winRec = WINREC(pWin);
   1347     ScreenPtr pScreen = pWin->drawable.pScreen;
   1348 
   1349     if (winRec == NULL)
   1350         return;
   1351 
   1352     RootlessStopDrawing(pWin, FALSE);
   1353     SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen,
   1354                                        winRec->x + SCREEN_TO_GLOBAL_X,
   1355                                        winRec->y + SCREEN_TO_GLOBAL_Y);
   1356 
   1357     RootlessReorderWindow(pWin);
   1358 }
   1359 
   1360 /*
   1361  * RootlessReparentWindow
   1362  *  Called after a window has been reparented. Generally windows are not
   1363  *  framed until they are mapped. However, a window may be framed early by the
   1364  *  implementation calling RootlessFrameForWindow. (e.g. this could be needed
   1365  *  to attach a VRAM surface to it.) If the window is subsequently reparented
   1366  *  by the window manager before being mapped, we need to give the frame to
   1367  *  the new top-level window.
   1368  */
   1369 void
   1370 RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent)
   1371 {
   1372     ScreenPtr pScreen = pWin->drawable.pScreen;
   1373     RootlessWindowRec *winRec = WINREC(pWin);
   1374     WindowPtr pTopWin;
   1375 
   1376     /* Check that window is not top-level now, but used to be. */
   1377     if (IsRoot(pWin) || IsRoot(pWin->parent)
   1378         || IsTopLevel(pWin) || winRec == NULL) {
   1379         goto out;
   1380     }
   1381 
   1382     /* If the formerly top-level window has a frame, we want to give the
   1383        frame to its new top-level parent. If we can't do that, we'll just
   1384        have to jettison it... */
   1385 
   1386     pTopWin = TopLevelParent(pWin);
   1387     assert(pTopWin != pWin);
   1388 
   1389     pWin->unhittable = FALSE;
   1390 
   1391     DeleteProperty(serverClient, pWin, xa_native_window_id());
   1392 
   1393     if (WINREC(pTopWin) != NULL) {
   1394         /* We're screwed. */
   1395         RootlessDestroyFrame(pWin, winRec);
   1396     }
   1397     else {
   1398         if (!pTopWin->realized && pWin->realized) {
   1399             SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid);
   1400         }
   1401 
   1402         /* Switch the frame record from one to the other. */
   1403 
   1404         SETWINREC(pWin, NULL);
   1405         SETWINREC(pTopWin, winRec);
   1406 
   1407         RootlessInitializeFrame(pTopWin, winRec);
   1408         RootlessReshapeFrame(pTopWin);
   1409 
   1410         SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
   1411                                              winRec->x + SCREEN_TO_GLOBAL_X,
   1412                                              winRec->y + SCREEN_TO_GLOBAL_Y,
   1413                                              winRec->width, winRec->height,
   1414                                              RL_GRAVITY_NONE);
   1415 
   1416         if (SCREENREC(pScreen)->imp->SwitchWindow) {
   1417             SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin);
   1418         }
   1419 
   1420         if (pTopWin->realized && !pWin->realized)
   1421             winRec->is_reorder_pending = TRUE;
   1422     }
   1423 
   1424  out:
   1425     if (SCREENREC(pScreen)->ReparentWindow) {
   1426         SCREEN_UNWRAP(pScreen, ReparentWindow);
   1427         pScreen->ReparentWindow(pWin, pPriorParent);
   1428         SCREEN_WRAP(pScreen, ReparentWindow);
   1429     }
   1430 }
   1431 
   1432 void
   1433 RootlessFlushWindowColormap(WindowPtr pWin)
   1434 {
   1435     RootlessWindowRec *winRec = WINREC(pWin);
   1436     ScreenPtr pScreen = pWin->drawable.pScreen;
   1437 
   1438     if (winRec == NULL)
   1439         return;
   1440 
   1441     RootlessStopDrawing(pWin, FALSE);
   1442 
   1443     if (SCREENREC(pScreen)->imp->UpdateColormap)
   1444         SCREENREC(pScreen)->imp->UpdateColormap(winRec->wid, pScreen);
   1445 }
   1446 
   1447 /*
   1448  * RootlessChangeBorderWidth
   1449  *  FIXME: untested!
   1450  *  pWin inside corner stays the same; pWin->drawable.[xy] stays the same
   1451  *  Frame moves and resizes.
   1452  */
   1453 void
   1454 RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width)
   1455 {
   1456     RegionRec saveRoot;
   1457     Bool resize_after = FALSE;
   1458 
   1459     RL_DEBUG_MSG("change border width ");
   1460 
   1461     if (width != wBorderWidth(pWin)) {
   1462         RootlessWindowRec *winRec = WINREC(pWin);
   1463         int oldX = 0, oldY = 0, newX = 0, newY = 0;
   1464         unsigned int oldW = 0, oldH = 0, oldBW = 0;
   1465         unsigned int newW = 0, newH = 0, newBW = 0;
   1466 
   1467         if (winRec) {
   1468             oldBW = winRec->borderWidth;
   1469             oldX = winRec->x;
   1470             oldY = winRec->y;
   1471             oldW = winRec->width;
   1472             oldH = winRec->height;
   1473 
   1474             newBW = width;
   1475             newX = pWin->drawable.x - newBW;
   1476             newY = pWin->drawable.y - newBW;
   1477             newW = pWin->drawable.width + 2 * newBW;
   1478             newH = pWin->drawable.height + 2 * newBW;
   1479 
   1480             resize_after = StartFrameResize(pWin, FALSE,
   1481                                             oldX, oldY, oldW, oldH, oldBW,
   1482                                             newX, newY, newW, newH, newBW);
   1483         }
   1484 
   1485         HUGE_ROOT(pWin);
   1486         SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth);
   1487         pWin->drawable.pScreen->ChangeBorderWidth(pWin, width);
   1488         SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth);
   1489         NORMAL_ROOT(pWin);
   1490 
   1491         if (winRec) {
   1492             FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
   1493                               newX, newY, newW, newH, newBW, resize_after);
   1494         }
   1495     }
   1496 
   1497     RL_DEBUG_MSG("change border width end\n");
   1498 }
   1499 
   1500 /*
   1501  * RootlessOrderAllWindows
   1502  * Brings all X11 windows to the top of the window stack
   1503  * (i.e in front of Aqua windows) -- called when X11.app is given focus
   1504  */
   1505 void
   1506 RootlessOrderAllWindows(Bool include_unhitable)
   1507 {
   1508     int i;
   1509     WindowPtr pWin;
   1510 
   1511     if (windows_hidden)
   1512         return;
   1513 
   1514     RL_DEBUG_MSG("RootlessOrderAllWindows() ");
   1515     for (i = 0; i < screenInfo.numScreens; i++) {
   1516         if (screenInfo.screens[i] == NULL)
   1517             continue;
   1518         pWin = screenInfo.screens[i]->root;
   1519         if (pWin == NULL)
   1520             continue;
   1521 
   1522         for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) {
   1523             if (!pWin->realized)
   1524                 continue;
   1525             if (RootlessEnsureFrame(pWin) == NULL)
   1526                 continue;
   1527             if (!include_unhitable && pWin->unhittable)
   1528                 continue;
   1529             RootlessReorderWindow(pWin);
   1530         }
   1531     }
   1532     RL_DEBUG_MSG("RootlessOrderAllWindows() done");
   1533 }
   1534 
   1535 void
   1536 RootlessEnableRoot(ScreenPtr pScreen)
   1537 {
   1538     WindowPtr pRoot;
   1539 
   1540     pRoot = pScreen->root;
   1541 
   1542     RootlessEnsureFrame(pRoot);
   1543     (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE);
   1544     RootlessReorderWindow(pRoot);
   1545 }
   1546 
   1547 void
   1548 RootlessDisableRoot(ScreenPtr pScreen)
   1549 {
   1550     WindowPtr pRoot;
   1551     RootlessWindowRec *winRec;
   1552 
   1553     pRoot = pScreen->root;
   1554     winRec = WINREC(pRoot);
   1555 
   1556     if (NULL == winRec)
   1557         return;
   1558 
   1559     RootlessDestroyFrame(pRoot, winRec);
   1560     DeleteProperty(serverClient, pRoot, xa_native_window_id());
   1561 }
   1562 
   1563 void
   1564 RootlessHideAllWindows(void)
   1565 {
   1566     int i;
   1567     ScreenPtr pScreen;
   1568     WindowPtr pWin;
   1569     RootlessWindowRec *winRec;
   1570 
   1571     if (windows_hidden)
   1572         return;
   1573 
   1574     windows_hidden = TRUE;
   1575 
   1576     for (i = 0; i < screenInfo.numScreens; i++) {
   1577         pScreen = screenInfo.screens[i];
   1578         if (pScreen == NULL)
   1579             continue;
   1580         pWin = pScreen->root;
   1581         if (pWin == NULL)
   1582             continue;
   1583 
   1584         for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) {
   1585             if (!pWin->realized)
   1586                 continue;
   1587 
   1588             RootlessStopDrawing(pWin, FALSE);
   1589 
   1590             winRec = WINREC(pWin);
   1591             if (winRec != NULL) {
   1592                 if (SCREENREC(pScreen)->imp->HideWindow)
   1593                     SCREENREC(pScreen)->imp->HideWindow(winRec->wid);
   1594             }
   1595         }
   1596     }
   1597 }
   1598 
   1599 void
   1600 RootlessShowAllWindows(void)
   1601 {
   1602     int i;
   1603     ScreenPtr pScreen;
   1604     WindowPtr pWin;
   1605     RootlessWindowRec *winRec;
   1606 
   1607     if (!windows_hidden)
   1608         return;
   1609 
   1610     windows_hidden = FALSE;
   1611 
   1612     for (i = 0; i < screenInfo.numScreens; i++) {
   1613         pScreen = screenInfo.screens[i];
   1614         if (pScreen == NULL)
   1615             continue;
   1616         pWin = pScreen->root;
   1617         if (pWin == NULL)
   1618             continue;
   1619 
   1620         for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) {
   1621             if (!pWin->realized)
   1622                 continue;
   1623 
   1624             winRec = RootlessEnsureFrame(pWin);
   1625             if (winRec == NULL)
   1626                 continue;
   1627 
   1628             RootlessReorderWindow(pWin);
   1629         }
   1630 
   1631         RootlessScreenExpose(pScreen);
   1632     }
   1633 }
   1634 
   1635 /*
   1636  * SetPixmapOfAncestors
   1637  *  Set the Pixmaps on all ParentRelative windows up the ancestor chain.
   1638  */
   1639 void
   1640 RootlessSetPixmapOfAncestors(WindowPtr pWin)
   1641 {
   1642     ScreenPtr pScreen = pWin->drawable.pScreen;
   1643     WindowPtr topWin = TopLevelParent(pWin);
   1644     RootlessWindowRec *topWinRec = WINREC(topWin);
   1645 
   1646     while (pWin->backgroundState == ParentRelative) {
   1647         if (pWin == topWin) {
   1648             // disallow ParentRelative background state on top level
   1649             XID pixel = 0;
   1650 
   1651             ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
   1652             RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin);
   1653             break;
   1654         }
   1655 
   1656         pWin = pWin->parent;
   1657         pScreen->SetWindowPixmap(pWin, topWinRec->pixmap);
   1658     }
   1659 }