rootlessWindow.c revision 6747b715
105b261ecSmrg/*
205b261ecSmrg * Rootless window management
305b261ecSmrg */
405b261ecSmrg/*
505b261ecSmrg * Copyright (c) 2001 Greg Parker. All Rights Reserved.
605b261ecSmrg * Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved.
705b261ecSmrg * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
805b261ecSmrg *
905b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
1005b261ecSmrg * copy of this software and associated documentation files (the "Software"),
1105b261ecSmrg * to deal in the Software without restriction, including without limitation
1205b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1305b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
1405b261ecSmrg * Software is furnished to do so, subject to the following conditions:
1505b261ecSmrg *
1605b261ecSmrg * The above copyright notice and this permission notice shall be included in
1705b261ecSmrg * all copies or substantial portions of the Software.
1805b261ecSmrg *
1905b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2005b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2105b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2205b261ecSmrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
2305b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2405b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2505b261ecSmrg * DEALINGS IN THE SOFTWARE.
2605b261ecSmrg *
2705b261ecSmrg * Except as contained in this notice, the name(s) of the above copyright
2805b261ecSmrg * holders shall not be used in advertising or otherwise to promote the sale,
2905b261ecSmrg * use or other dealings in this Software without prior written authorization.
3005b261ecSmrg */
3105b261ecSmrg
3205b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
3305b261ecSmrg#include <dix-config.h>
3405b261ecSmrg#endif
3505b261ecSmrg
3605b261ecSmrg#include <stddef.h> /* For NULL */
3705b261ecSmrg#include <limits.h> /* For CHAR_BIT */
3805b261ecSmrg#include <assert.h>
394642e01fSmrg#include <X11/Xatom.h>
406747b715Smrg#ifdef __APPLE__
416747b715Smrg#include <Xplugin.h>
424642e01fSmrg#include "mi.h"
434642e01fSmrg#include "pixmapstr.h"
444642e01fSmrg#include "windowstr.h"
454642e01fSmrg//#include <X11/extensions/applewm.h>
464642e01fSmrgextern int darwinMainScreenX, darwinMainScreenY;
476747b715Smrgextern Bool no_configure_window;
484642e01fSmrg#endif
494642e01fSmrg#include "fb.h"
504642e01fSmrg
5105b261ecSmrg#include "rootlessCommon.h"
5205b261ecSmrg#include "rootlessWindow.h"
5305b261ecSmrg
5405b261ecSmrg#ifdef ROOTLESS_GLOBAL_COORDS
5505b261ecSmrg#define SCREEN_TO_GLOBAL_X \
566747b715Smrg    (pScreen->x + rootlessGlobalOffsetX)
5705b261ecSmrg#define SCREEN_TO_GLOBAL_Y \
586747b715Smrg    (pScreen->y + rootlessGlobalOffsetY)
5905b261ecSmrg#else
6005b261ecSmrg#define SCREEN_TO_GLOBAL_X 0
6105b261ecSmrg#define SCREEN_TO_GLOBAL_Y 0
6205b261ecSmrg#endif
6305b261ecSmrg
644642e01fSmrg#define DEFINE_ATOM_HELPER(func,atom_name)                      \
654642e01fSmrg  static Atom func (void) {                                       \
664642e01fSmrg    static unsigned int generation = 0;                             \
674642e01fSmrg    static Atom atom;                                           \
684642e01fSmrg    if (generation != serverGeneration) {                       \
694642e01fSmrg      generation = serverGeneration;                          \
704642e01fSmrg      atom = MakeAtom (atom_name, strlen (atom_name), TRUE);  \
714642e01fSmrg    }                                                           \
724642e01fSmrg    return atom;                                                \
734642e01fSmrg  }
744642e01fSmrg
754642e01fSmrgDEFINE_ATOM_HELPER (xa_native_window_id, "_NATIVE_WINDOW_ID")
764642e01fSmrg
774642e01fSmrgstatic Bool windows_hidden;
784642e01fSmrg// TODO - abstract xp functions
794642e01fSmrg
806747b715Smrg#ifdef __APPLE__
814642e01fSmrg
826747b715Smrg// XXX: identical to x_cvt_vptr_to_uint ?
836747b715Smrg#define MAKE_WINDOW_ID(x)		((xp_window_id)((size_t)(x)))
844642e01fSmrg
854642e01fSmrgvoid
864642e01fSmrgRootlessNativeWindowStateChanged (WindowPtr pWin, unsigned int state)
874642e01fSmrg{
884642e01fSmrg  RootlessWindowRec *winRec;
894642e01fSmrg
904642e01fSmrg  if (pWin == NULL) return;
914642e01fSmrg
924642e01fSmrg  winRec = WINREC (pWin);
934642e01fSmrg  if (winRec == NULL) return;
944642e01fSmrg
954642e01fSmrg  winRec->is_offscreen = ((state & XP_WINDOW_STATE_OFFSCREEN) != 0);
964642e01fSmrg  winRec->is_obscured = ((state & XP_WINDOW_STATE_OBSCURED) != 0);
974642e01fSmrg  pWin->rootlessUnhittable = winRec->is_offscreen;
984642e01fSmrg}
994642e01fSmrg
1004642e01fSmrgvoid RootlessNativeWindowMoved (WindowPtr pWin) {
1014642e01fSmrg    xp_box bounds;
1024642e01fSmrg    int sx, sy, err;
1034642e01fSmrg    XID vlist[2];
1044642e01fSmrg    Mask mask;
1054642e01fSmrg    ClientPtr pClient;
1064642e01fSmrg    RootlessWindowRec *winRec;
1074642e01fSmrg
1084642e01fSmrg    winRec = WINREC(pWin);
1094642e01fSmrg
1104642e01fSmrg    if (xp_get_window_bounds (MAKE_WINDOW_ID(winRec->wid), &bounds) != Success) return;
1114642e01fSmrg
1126747b715Smrg    sx = pWin->drawable.pScreen->x + darwinMainScreenX;
1136747b715Smrg    sy = pWin->drawable.pScreen->y + darwinMainScreenY;
1144642e01fSmrg
1154642e01fSmrg    /* Fake up a ConfigureWindow packet to resize the window to the current bounds. */
1164642e01fSmrg    vlist[0] = (INT16) bounds.x1 - sx;
1174642e01fSmrg    vlist[1] = (INT16) bounds.y1 - sy;
1184642e01fSmrg    mask = CWX | CWY;
1194642e01fSmrg
1204642e01fSmrg    /* pretend we're the owner of the window! */
1216747b715Smrg    err = dixLookupClient(&pClient, pWin->drawable.id, serverClient, DixUnknownAccess);
1224642e01fSmrg    if(err != Success) {
1234642e01fSmrg        ErrorF("RootlessNativeWindowMoved(): Failed to lookup window: 0x%x\n", (unsigned int)pWin->drawable.id);
1244642e01fSmrg        return;
1254642e01fSmrg    }
1264642e01fSmrg
1274642e01fSmrg    /* Don't want to do anything to the physical window (avoids
1284642e01fSmrg     notification-response feedback loops) */
1294642e01fSmrg
1304642e01fSmrg    no_configure_window = TRUE;
1314642e01fSmrg    ConfigureWindow (pWin, mask, vlist, pClient);
1324642e01fSmrg    no_configure_window = FALSE;
1334642e01fSmrg}
1344642e01fSmrg
1356747b715Smrg#endif /* __APPLE__ */
13605b261ecSmrg
13705b261ecSmrg/*
13805b261ecSmrg * RootlessCreateWindow
13905b261ecSmrg *  For now, don't create a physical window until either the window is
14005b261ecSmrg *  realized, or we really need it (e.g. to attach VRAM surfaces to).
14105b261ecSmrg *  Do reset the window size so it's not clipped by the root window.
14205b261ecSmrg */
14305b261ecSmrgBool
14405b261ecSmrgRootlessCreateWindow(WindowPtr pWin)
14505b261ecSmrg{
14605b261ecSmrg    Bool result;
14705b261ecSmrg    RegionRec saveRoot;
14805b261ecSmrg
1494642e01fSmrg    SETWINREC(pWin, NULL);
1504642e01fSmrg    dixSetPrivate(&pWin->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL);
15105b261ecSmrg
15205b261ecSmrg    SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow);
15305b261ecSmrg
15405b261ecSmrg    if (!IsRoot(pWin)) {
15505b261ecSmrg        /* win/border size set by DIX, not by wrapped CreateWindow, so
15605b261ecSmrg           correct it here. Don't HUGE_ROOT when pWin is the root! */
15705b261ecSmrg
15805b261ecSmrg        HUGE_ROOT(pWin);
15905b261ecSmrg        SetWinSize(pWin);
16005b261ecSmrg        SetBorderSize(pWin);
16105b261ecSmrg    }
16205b261ecSmrg
16305b261ecSmrg    result = pWin->drawable.pScreen->CreateWindow(pWin);
16405b261ecSmrg
16505b261ecSmrg    if (pWin->parent) {
16605b261ecSmrg        NORMAL_ROOT(pWin);
16705b261ecSmrg    }
16805b261ecSmrg
16905b261ecSmrg    SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow);
17005b261ecSmrg
17105b261ecSmrg    return result;
17205b261ecSmrg}
17305b261ecSmrg
17405b261ecSmrg
17505b261ecSmrg/*
17605b261ecSmrg * RootlessDestroyFrame
17705b261ecSmrg *  Destroy the physical window associated with the given window.
17805b261ecSmrg */
17905b261ecSmrgstatic void
18005b261ecSmrgRootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec)
18105b261ecSmrg{
1826747b715Smrg    SCREENREC(pWin->drawable.pScreen)->imp->DestroyFrame(winRec->wid);
18305b261ecSmrg
18405b261ecSmrg#ifdef ROOTLESS_TRACK_DAMAGE
1856747b715Smrg    RegionUninit(&winRec->damage);
18605b261ecSmrg#endif
18705b261ecSmrg
1886747b715Smrg    free(winRec);
1894642e01fSmrg    SETWINREC(pWin, NULL);
19005b261ecSmrg}
19105b261ecSmrg
19205b261ecSmrg
19305b261ecSmrg/*
19405b261ecSmrg * RootlessDestroyWindow
19505b261ecSmrg *  Destroy the physical window associated with the given window.
19605b261ecSmrg */
19705b261ecSmrgBool
19805b261ecSmrgRootlessDestroyWindow(WindowPtr pWin)
19905b261ecSmrg{
20005b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
20105b261ecSmrg    Bool result;
20205b261ecSmrg
20305b261ecSmrg    if (winRec != NULL) {
20405b261ecSmrg        RootlessDestroyFrame(pWin, winRec);
20505b261ecSmrg    }
20605b261ecSmrg
20705b261ecSmrg    SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow);
20805b261ecSmrg    result = pWin->drawable.pScreen->DestroyWindow(pWin);
20905b261ecSmrg    SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow);
21005b261ecSmrg
21105b261ecSmrg    return result;
21205b261ecSmrg}
21305b261ecSmrg
21405b261ecSmrg
21505b261ecSmrg
21605b261ecSmrgstatic Bool
21705b261ecSmrgRootlessGetShape(WindowPtr pWin, RegionPtr pShape)
21805b261ecSmrg{
21905b261ecSmrg    if (wBoundingShape(pWin) == NULL)
22005b261ecSmrg        return FALSE;
22105b261ecSmrg
22205b261ecSmrg    /* wBoundingShape is relative to *inner* origin of window.
22305b261ecSmrg       Translate by borderWidth to get the outside-relative position. */
22405b261ecSmrg
2256747b715Smrg    RegionNull(pShape);
2266747b715Smrg    RegionCopy(pShape, wBoundingShape(pWin));
2276747b715Smrg    RegionTranslate(pShape, pWin->borderWidth, pWin->borderWidth);
22805b261ecSmrg
22905b261ecSmrg    return TRUE;
23005b261ecSmrg}
23105b261ecSmrg
23205b261ecSmrg
23305b261ecSmrg/*
23405b261ecSmrg * RootlessReshapeFrame
23505b261ecSmrg *  Set the frame shape.
23605b261ecSmrg */
23705b261ecSmrgstatic void RootlessReshapeFrame(WindowPtr pWin)
23805b261ecSmrg{
23905b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
24005b261ecSmrg    RegionRec newShape;
24105b261ecSmrg    RegionPtr pShape;
24205b261ecSmrg
24305b261ecSmrg    // If the window is not yet framed, do nothing
24405b261ecSmrg    if (winRec == NULL)
24505b261ecSmrg        return;
24605b261ecSmrg
24705b261ecSmrg    if (IsRoot(pWin))
24805b261ecSmrg        return;
24905b261ecSmrg
25005b261ecSmrg    RootlessStopDrawing(pWin, FALSE);
25105b261ecSmrg
25205b261ecSmrg    pShape = RootlessGetShape(pWin, &newShape) ? &newShape : NULL;
25305b261ecSmrg
25405b261ecSmrg#ifdef ROOTLESSDEBUG
25505b261ecSmrg    RL_DEBUG_MSG("reshaping...");
25605b261ecSmrg    if (pShape != NULL) {
25705b261ecSmrg        RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ",
2586747b715Smrg                     RegionNumRects(&newShape),
25905b261ecSmrg                     newShape.extents.x1, newShape.extents.y1,
26005b261ecSmrg                     newShape.extents.x2, newShape.extents.y2);
26105b261ecSmrg    } else {
26205b261ecSmrg        RL_DEBUG_MSG("no shape ");
26305b261ecSmrg    }
26405b261ecSmrg#endif
26505b261ecSmrg
2666747b715Smrg    SCREENREC(pWin->drawable.pScreen)->imp->ReshapeFrame(winRec->wid, pShape);
26705b261ecSmrg
26805b261ecSmrg    if (pShape != NULL)
2696747b715Smrg        RegionUninit(&newShape);
27005b261ecSmrg}
27105b261ecSmrg
27205b261ecSmrg
27305b261ecSmrg/*
27405b261ecSmrg * RootlessSetShape
27505b261ecSmrg *  Shape is usually set before a window is mapped and the window will
27605b261ecSmrg *  not have a frame associated with it. In this case, the frame will be
27705b261ecSmrg *  shaped when the window is framed.
27805b261ecSmrg */
27905b261ecSmrgvoid
2806747b715SmrgRootlessSetShape(WindowPtr pWin, int kind)
28105b261ecSmrg{
28205b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
28305b261ecSmrg
28405b261ecSmrg    SCREEN_UNWRAP(pScreen, SetShape);
2856747b715Smrg    pScreen->SetShape(pWin, kind);
28605b261ecSmrg    SCREEN_WRAP(pScreen, SetShape);
28705b261ecSmrg
28805b261ecSmrg    RootlessReshapeFrame(pWin);
28905b261ecSmrg}
29005b261ecSmrg
29105b261ecSmrg
29205b261ecSmrg
29305b261ecSmrg/* Disallow ParentRelative background on top-level windows
2944642e01fSmrg   because the root window doesn't really have the right background.
2954642e01fSmrg */
29605b261ecSmrgBool
29705b261ecSmrgRootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask)
29805b261ecSmrg{
29905b261ecSmrg    Bool result;
30005b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
30105b261ecSmrg
30205b261ecSmrg    RL_DEBUG_MSG("change window attributes start ");
30305b261ecSmrg
30405b261ecSmrg    SCREEN_UNWRAP(pScreen, ChangeWindowAttributes);
30505b261ecSmrg    result = pScreen->ChangeWindowAttributes(pWin, vmask);
30605b261ecSmrg    SCREEN_WRAP(pScreen, ChangeWindowAttributes);
30705b261ecSmrg
30805b261ecSmrg    if (WINREC(pWin)) {
30905b261ecSmrg        // disallow ParentRelative background state
31005b261ecSmrg        if (pWin->backgroundState == ParentRelative) {
31105b261ecSmrg            XID pixel = 0;
31205b261ecSmrg            ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
31305b261ecSmrg        }
31405b261ecSmrg    }
31505b261ecSmrg
31605b261ecSmrg    RL_DEBUG_MSG("change window attributes end\n");
31705b261ecSmrg    return result;
31805b261ecSmrg}
31905b261ecSmrg
32005b261ecSmrg
32105b261ecSmrg/*
32205b261ecSmrg * RootlessPositionWindow
32305b261ecSmrg *  This is a hook for when DIX moves or resizes a window.
32405b261ecSmrg *  Update the frame position now although the physical window is moved
32505b261ecSmrg *  in RootlessMoveWindow. (x, y) are *inside* position. After this,
32605b261ecSmrg *  mi and fb are expecting the pixmap to be at the new location.
32705b261ecSmrg */
32805b261ecSmrgBool
32905b261ecSmrgRootlessPositionWindow(WindowPtr pWin, int x, int y)
33005b261ecSmrg{
33105b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
33205b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
33305b261ecSmrg    Bool result;
33405b261ecSmrg
33505b261ecSmrg    RL_DEBUG_MSG("positionwindow start (win 0x%x @ %i, %i)\n", pWin, x, y);
33605b261ecSmrg
33705b261ecSmrg    if (winRec) {
33805b261ecSmrg        if (winRec->is_drawing) {
33905b261ecSmrg            // Reset frame's pixmap and move it to the new position.
34005b261ecSmrg            int bw = wBorderWidth(pWin);
34105b261ecSmrg
34205b261ecSmrg            winRec->pixmap->devPrivate.ptr = winRec->pixelData;
34305b261ecSmrg            SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw);
34405b261ecSmrg
34505b261ecSmrg#ifdef ROOTLESS_TRACK_DAMAGE
34605b261ecSmrg            // Move damaged region to correspond to new window position
3476747b715Smrg            if (RegionNotEmpty(&winRec->damage)) {
3486747b715Smrg                RegionTranslate(&winRec->damage,
34905b261ecSmrg                                 x - bw - winRec->x,
35005b261ecSmrg                                 y - bw - winRec->y);
35105b261ecSmrg            }
35205b261ecSmrg#endif
35305b261ecSmrg        }
35405b261ecSmrg    }
35505b261ecSmrg
35605b261ecSmrg    SCREEN_UNWRAP(pScreen, PositionWindow);
35705b261ecSmrg    result = pScreen->PositionWindow(pWin, x, y);
35805b261ecSmrg    SCREEN_WRAP(pScreen, PositionWindow);
35905b261ecSmrg
36005b261ecSmrg    RL_DEBUG_MSG("positionwindow end\n");
36105b261ecSmrg    return result;
36205b261ecSmrg}
36305b261ecSmrg
36405b261ecSmrg
36505b261ecSmrg/*
36605b261ecSmrg * RootlessInitializeFrame
36705b261ecSmrg *  Initialize some basic attributes of the frame. Note that winRec
36805b261ecSmrg *  may already have valid data in it, so don't overwrite anything
36905b261ecSmrg *  valuable.
37005b261ecSmrg */
37105b261ecSmrgstatic void
37205b261ecSmrgRootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec *winRec)
37305b261ecSmrg{
37405b261ecSmrg    DrawablePtr d = &pWin->drawable;
37505b261ecSmrg    int bw = wBorderWidth(pWin);
37605b261ecSmrg
37705b261ecSmrg    winRec->win = pWin;
37805b261ecSmrg
37905b261ecSmrg    winRec->x = d->x - bw;
38005b261ecSmrg    winRec->y = d->y - bw;
38105b261ecSmrg    winRec->width = d->width + 2*bw;
38205b261ecSmrg    winRec->height = d->height + 2*bw;
38305b261ecSmrg    winRec->borderWidth = bw;
38405b261ecSmrg
38505b261ecSmrg#ifdef ROOTLESS_TRACK_DAMAGE
3866747b715Smrg    RegionNull(&winRec->damage);
38705b261ecSmrg#endif
38805b261ecSmrg}
38905b261ecSmrg
39005b261ecSmrg/*
39105b261ecSmrg * RootlessEnsureFrame
39205b261ecSmrg *  Make sure the given window is framed. If the window doesn't have a
39305b261ecSmrg *  physical window associated with it, attempt to create one. If that
39405b261ecSmrg *  is unsuccessful, return NULL.
39505b261ecSmrg */
39605b261ecSmrgstatic RootlessWindowRec *
39705b261ecSmrgRootlessEnsureFrame(WindowPtr pWin)
39805b261ecSmrg{
39905b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
40005b261ecSmrg    RootlessWindowRec *winRec;
40105b261ecSmrg    RegionRec shape;
40205b261ecSmrg    RegionPtr pShape = NULL;
40305b261ecSmrg
40405b261ecSmrg    if (WINREC(pWin) != NULL)
40505b261ecSmrg        return WINREC(pWin);
40605b261ecSmrg
4074642e01fSmrg    if (!IsTopLevel(pWin) && !IsRoot(pWin))
40805b261ecSmrg        return NULL;
40905b261ecSmrg
41005b261ecSmrg    if (pWin->drawable.class != InputOutput)
41105b261ecSmrg        return NULL;
41205b261ecSmrg
4136747b715Smrg    winRec = malloc(sizeof(RootlessWindowRec));
41405b261ecSmrg
41505b261ecSmrg    if (!winRec)
41605b261ecSmrg        return NULL;
41705b261ecSmrg
41805b261ecSmrg    RootlessInitializeFrame(pWin, winRec);
41905b261ecSmrg
42005b261ecSmrg    winRec->is_drawing = FALSE;
42105b261ecSmrg    winRec->is_reorder_pending = FALSE;
42205b261ecSmrg    winRec->pixmap = NULL;
42305b261ecSmrg    winRec->wid = NULL;
4246747b715Smrg    winRec->level = 0;
42505b261ecSmrg
4264642e01fSmrg    SETWINREC(pWin, winRec);
42705b261ecSmrg
42805b261ecSmrg    // Set the frame's shape if the window is shaped
42905b261ecSmrg    if (RootlessGetShape(pWin, &shape))
43005b261ecSmrg        pShape = &shape;
43105b261ecSmrg
43205b261ecSmrg    RL_DEBUG_MSG("creating frame ");
43305b261ecSmrg
43405b261ecSmrg    if (!SCREENREC(pScreen)->imp->CreateFrame(winRec, pScreen,
43505b261ecSmrg                                              winRec->x + SCREEN_TO_GLOBAL_X,
43605b261ecSmrg                                              winRec->y + SCREEN_TO_GLOBAL_Y,
43705b261ecSmrg                                              pShape))
43805b261ecSmrg    {
43905b261ecSmrg        RL_DEBUG_MSG("implementation failed to create frame!\n");
4406747b715Smrg        free(winRec);
4414642e01fSmrg        SETWINREC(pWin, NULL);
44205b261ecSmrg        return NULL;
44305b261ecSmrg    }
44405b261ecSmrg
4454642e01fSmrg    if (pWin->drawable.depth == 8)
4464642e01fSmrg      RootlessFlushWindowColormap(pWin);
4474642e01fSmrg
44805b261ecSmrg    if (pShape != NULL)
4496747b715Smrg        RegionUninit(&shape);
45005b261ecSmrg
45105b261ecSmrg    return winRec;
45205b261ecSmrg}
45305b261ecSmrg
45405b261ecSmrg
45505b261ecSmrg/*
45605b261ecSmrg * RootlessRealizeWindow
45705b261ecSmrg *  The frame is usually created here and not in CreateWindow so that
45805b261ecSmrg *  windows do not eat memory until they are realized.
45905b261ecSmrg */
46005b261ecSmrgBool
46105b261ecSmrgRootlessRealizeWindow(WindowPtr pWin)
46205b261ecSmrg{
46305b261ecSmrg    Bool result;
46405b261ecSmrg    RegionRec saveRoot;
46505b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
46605b261ecSmrg
46705b261ecSmrg    RL_DEBUG_MSG("realizewindow start (win 0x%x) ", pWin);
46805b261ecSmrg
46905b261ecSmrg    if ((IsTopLevel(pWin) && pWin->drawable.class == InputOutput)) {
47005b261ecSmrg        RootlessWindowRec *winRec;
47105b261ecSmrg
47205b261ecSmrg        winRec = RootlessEnsureFrame(pWin);
47305b261ecSmrg        if (winRec == NULL)
47405b261ecSmrg            return FALSE;
47505b261ecSmrg
47605b261ecSmrg        winRec->is_reorder_pending = TRUE;
47705b261ecSmrg
47805b261ecSmrg        RL_DEBUG_MSG("Top level window ");
47905b261ecSmrg
48005b261ecSmrg        // Disallow ParentRelative background state on top-level windows.
48105b261ecSmrg        // This might have been set before the window was mapped.
48205b261ecSmrg        if (pWin->backgroundState == ParentRelative) {
48305b261ecSmrg            XID pixel = 0;
48405b261ecSmrg            ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
48505b261ecSmrg        }
48605b261ecSmrg    }
48705b261ecSmrg
48805b261ecSmrg    if (!IsRoot(pWin)) HUGE_ROOT(pWin);
48905b261ecSmrg    SCREEN_UNWRAP(pScreen, RealizeWindow);
49005b261ecSmrg    result = pScreen->RealizeWindow(pWin);
49105b261ecSmrg    SCREEN_WRAP(pScreen, RealizeWindow);
49205b261ecSmrg    if (!IsRoot(pWin)) NORMAL_ROOT(pWin);
49305b261ecSmrg
49405b261ecSmrg    RL_DEBUG_MSG("realizewindow end\n");
49505b261ecSmrg    return result;
49605b261ecSmrg}
49705b261ecSmrg
49805b261ecSmrg
49905b261ecSmrg/*
50005b261ecSmrg * RootlessFrameForWindow
50105b261ecSmrg *  Returns the frame ID for the physical window displaying the given window.
50205b261ecSmrg *  If CREATE is true and the window has no frame, attempt to create one.
50305b261ecSmrg */
50405b261ecSmrgRootlessFrameID
50505b261ecSmrgRootlessFrameForWindow(WindowPtr pWin, Bool create)
50605b261ecSmrg{
50705b261ecSmrg    WindowPtr pTopWin;
50805b261ecSmrg    RootlessWindowRec *winRec;
50905b261ecSmrg
51005b261ecSmrg    pTopWin = TopLevelParent(pWin);
51105b261ecSmrg    if (pTopWin == NULL)
51205b261ecSmrg        return NULL;
51305b261ecSmrg
51405b261ecSmrg    winRec = WINREC(pTopWin);
51505b261ecSmrg
51605b261ecSmrg    if (winRec == NULL && create && pWin->drawable.class == InputOutput) {
51705b261ecSmrg        winRec = RootlessEnsureFrame(pTopWin);
51805b261ecSmrg    }
51905b261ecSmrg
52005b261ecSmrg    if (winRec == NULL)
52105b261ecSmrg        return NULL;
52205b261ecSmrg
52305b261ecSmrg    return winRec->wid;
52405b261ecSmrg}
52505b261ecSmrg
52605b261ecSmrg
52705b261ecSmrg/*
52805b261ecSmrg * RootlessUnrealizeWindow
52905b261ecSmrg *  Unmap the physical window.
53005b261ecSmrg */
53105b261ecSmrgBool
53205b261ecSmrgRootlessUnrealizeWindow(WindowPtr pWin)
53305b261ecSmrg{
53405b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
53505b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
53605b261ecSmrg    Bool result;
53705b261ecSmrg
53805b261ecSmrg    RL_DEBUG_MSG("unrealizewindow start ");
53905b261ecSmrg
54005b261ecSmrg    if (winRec) {
54105b261ecSmrg        RootlessStopDrawing(pWin, FALSE);
54205b261ecSmrg
54305b261ecSmrg        SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid);
54405b261ecSmrg
54505b261ecSmrg        winRec->is_reorder_pending = FALSE;
54605b261ecSmrg    }
54705b261ecSmrg
54805b261ecSmrg    SCREEN_UNWRAP(pScreen, UnrealizeWindow);
54905b261ecSmrg    result = pScreen->UnrealizeWindow(pWin);
55005b261ecSmrg    SCREEN_WRAP(pScreen, UnrealizeWindow);
55105b261ecSmrg
55205b261ecSmrg    RL_DEBUG_MSG("unrealizewindow end\n");
55305b261ecSmrg    return result;
55405b261ecSmrg}
55505b261ecSmrg
55605b261ecSmrg
55705b261ecSmrg/*
55805b261ecSmrg * RootlessReorderWindow
55905b261ecSmrg *  Reorder the frame associated with the given window so that it's
56005b261ecSmrg *  physically above the window below it in the X stacking order.
56105b261ecSmrg */
56205b261ecSmrgvoid
56305b261ecSmrgRootlessReorderWindow(WindowPtr pWin)
56405b261ecSmrg{
56505b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
56605b261ecSmrg
5674642e01fSmrg    if (pWin->realized && winRec != NULL && !winRec->is_reorder_pending && !windows_hidden) {
56805b261ecSmrg        WindowPtr newPrevW;
56905b261ecSmrg        RootlessWindowRec *newPrev;
57005b261ecSmrg        RootlessFrameID newPrevID;
57105b261ecSmrg        ScreenPtr pScreen = pWin->drawable.pScreen;
57205b261ecSmrg
57305b261ecSmrg        /* Check if the implementation wants the frame to not be reordered
57405b261ecSmrg           even though the X11 window is restacked. This can be useful if
57505b261ecSmrg           frames are ordered-in with animation so that the reordering is not
57605b261ecSmrg           done until the animation is complete. */
57705b261ecSmrg        if (SCREENREC(pScreen)->imp->DoReorderWindow) {
57805b261ecSmrg            if (!SCREENREC(pScreen)->imp->DoReorderWindow(winRec))
57905b261ecSmrg                return;
58005b261ecSmrg        }
58105b261ecSmrg
58205b261ecSmrg        RootlessStopDrawing(pWin, FALSE);
58305b261ecSmrg
5846747b715Smrg        /* Find the next window above this one that has a mapped frame.
5856747b715Smrg         * Only include cases where the windows are in the same category of
5866747b715Smrg         * hittability to ensure offscreen windows dont get restacked
5876747b715Smrg         * relative to onscreen ones (but that the offscreen ones maintain
5886747b715Smrg         * their stacking order if they are explicitly asked to Reorder
5896747b715Smrg         */
59005b261ecSmrg
59105b261ecSmrg        newPrevW = pWin->prevSib;
5926747b715Smrg        while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized || newPrevW->rootlessUnhittable != pWin->rootlessUnhittable))
59305b261ecSmrg            newPrevW = newPrevW->prevSib;
59405b261ecSmrg
59505b261ecSmrg        newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL;
59605b261ecSmrg        newPrevID = newPrev != NULL ? newPrev->wid : 0;
59705b261ecSmrg
59805b261ecSmrg        /* If it exists, reorder the frame above us first. */
59905b261ecSmrg
60005b261ecSmrg        if (newPrev && newPrev->is_reorder_pending) {
60105b261ecSmrg            newPrev->is_reorder_pending = FALSE;
60205b261ecSmrg            RootlessReorderWindow(newPrevW);
60305b261ecSmrg        }
60405b261ecSmrg
60505b261ecSmrg        SCREENREC(pScreen)->imp->RestackFrame(winRec->wid, newPrevID);
60605b261ecSmrg    }
60705b261ecSmrg}
60805b261ecSmrg
60905b261ecSmrg
61005b261ecSmrg/*
61105b261ecSmrg * RootlessRestackWindow
61205b261ecSmrg *  This is a hook for when DIX changes the window stacking order.
61305b261ecSmrg *  The window has already been inserted into its new position in the
61405b261ecSmrg *  DIX window stack. We need to change the order of the physical
61505b261ecSmrg *  window to match.
61605b261ecSmrg */
61705b261ecSmrgvoid
61805b261ecSmrgRootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib)
61905b261ecSmrg{
62005b261ecSmrg    RegionRec saveRoot;
62105b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
62205b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
62305b261ecSmrg
62405b261ecSmrg    RL_DEBUG_MSG("restackwindow start ");
62505b261ecSmrg    if (winRec)
62605b261ecSmrg        RL_DEBUG_MSG("restack top level \n");
62705b261ecSmrg
62805b261ecSmrg    HUGE_ROOT(pWin);
62905b261ecSmrg    SCREEN_UNWRAP(pScreen, RestackWindow);
63005b261ecSmrg
63105b261ecSmrg    if (pScreen->RestackWindow)
63205b261ecSmrg        pScreen->RestackWindow(pWin, pOldNextSib);
63305b261ecSmrg
63405b261ecSmrg    SCREEN_WRAP(pScreen, RestackWindow);
63505b261ecSmrg    NORMAL_ROOT(pWin);
63605b261ecSmrg
63705b261ecSmrg    if (winRec && pWin->viewable) {
63805b261ecSmrg        RootlessReorderWindow(pWin);
63905b261ecSmrg    }
64005b261ecSmrg
64105b261ecSmrg    RL_DEBUG_MSG("restackwindow end\n");
64205b261ecSmrg}
64305b261ecSmrg
64405b261ecSmrg/*
64505b261ecSmrg * Specialized window copy procedures
64605b261ecSmrg */
64705b261ecSmrg
64805b261ecSmrg// Globals needed during window resize and move.
64905b261ecSmrgstatic pointer gResizeDeathBits = NULL;
65005b261ecSmrgstatic int gResizeDeathCount = 0;
65105b261ecSmrgstatic PixmapPtr gResizeDeathPix[2] = {NULL, NULL};
65205b261ecSmrgstatic BoxRec gResizeDeathBounds[2];
65305b261ecSmrgstatic CopyWindowProcPtr gResizeOldCopyWindowProc = NULL;
65405b261ecSmrg
65505b261ecSmrg/*
65605b261ecSmrg * RootlessNoCopyWindow
65705b261ecSmrg *  CopyWindow() that doesn't do anything. For MoveWindow() of
65805b261ecSmrg *  top-level windows.
65905b261ecSmrg */
66005b261ecSmrgstatic void
66105b261ecSmrgRootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
66205b261ecSmrg                     RegionPtr prgnSrc)
66305b261ecSmrg{
66405b261ecSmrg    // some code expects the region to be translated
66505b261ecSmrg    int dx = ptOldOrg.x - pWin->drawable.x;
66605b261ecSmrg    int dy = ptOldOrg.y - pWin->drawable.y;
66705b261ecSmrg
66805b261ecSmrg    RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW ");
66905b261ecSmrg
6706747b715Smrg    RegionTranslate(prgnSrc, -dx, -dy);
67105b261ecSmrg}
67205b261ecSmrg
67305b261ecSmrg
67405b261ecSmrg/*
67505b261ecSmrg * RootlessResizeCopyWindow
67605b261ecSmrg *  CopyWindow used during ResizeWindow for gravity moves. Based on
67705b261ecSmrg *  fbCopyWindow. The original always draws on the root pixmap, which
67805b261ecSmrg *  we don't have. Instead, draw on the parent window's pixmap.
67905b261ecSmrg *  Resize version: the old location's pixels are in gResizeCopyWindowSource.
68005b261ecSmrg */
68105b261ecSmrgstatic void
68205b261ecSmrgRootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
68305b261ecSmrg                         RegionPtr prgnSrc)
68405b261ecSmrg{
68505b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
68605b261ecSmrg    RegionRec   rgnDst;
68705b261ecSmrg    int         dx, dy;
68805b261ecSmrg
68905b261ecSmrg    RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin);
69005b261ecSmrg
69105b261ecSmrg    /* Don't unwrap pScreen->CopyWindow.
69205b261ecSmrg       The bogus rewrap with RootlessCopyWindow causes a crash if
69305b261ecSmrg       CopyWindow is called again during the same resize. */
69405b261ecSmrg
69505b261ecSmrg    if (gResizeDeathCount == 0)
69605b261ecSmrg        return;
69705b261ecSmrg
69805b261ecSmrg    RootlessStartDrawing(pWin);
69905b261ecSmrg
70005b261ecSmrg    dx = ptOldOrg.x - pWin->drawable.x;
70105b261ecSmrg    dy = ptOldOrg.y - pWin->drawable.y;
7026747b715Smrg    RegionTranslate(prgnSrc, -dx, -dy);
7036747b715Smrg    RegionNull(&rgnDst);
7046747b715Smrg    RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
70505b261ecSmrg
70605b261ecSmrg    if (gResizeDeathCount == 1) {
70705b261ecSmrg        /* Simple case, we only have a single source pixmap. */
70805b261ecSmrg
70905b261ecSmrg        fbCopyRegion(&gResizeDeathPix[0]->drawable,
71005b261ecSmrg                     &pScreen->GetWindowPixmap(pWin)->drawable, 0,
71105b261ecSmrg                     &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
71205b261ecSmrg    }
71305b261ecSmrg    else {
71405b261ecSmrg        int i;
71505b261ecSmrg        RegionRec clip, clipped;
71605b261ecSmrg
71705b261ecSmrg        /* More complex case, N source pixmaps (usually two). So we
71805b261ecSmrg           intersect the destination with each source and copy those bits. */
71905b261ecSmrg
72005b261ecSmrg        for (i = 0; i < gResizeDeathCount; i++) {
7216747b715Smrg            RegionInit(&clip, gResizeDeathBounds + 0, 1);
7226747b715Smrg            RegionNull(&clipped);
7236747b715Smrg            RegionIntersect(&rgnDst, &clip, &clipped);
72405b261ecSmrg
72505b261ecSmrg            fbCopyRegion(&gResizeDeathPix[i]->drawable,
72605b261ecSmrg                         &pScreen->GetWindowPixmap(pWin)->drawable, 0,
72705b261ecSmrg                         &clipped, dx, dy, fbCopyWindowProc, 0, 0);
72805b261ecSmrg
7296747b715Smrg            RegionUninit(&clipped);
7306747b715Smrg            RegionUninit(&clip);
73105b261ecSmrg        }
73205b261ecSmrg    }
73305b261ecSmrg
73405b261ecSmrg    /* Don't update - resize will update everything */
7356747b715Smrg    RegionUninit(&rgnDst);
73605b261ecSmrg
73705b261ecSmrg    fbValidateDrawable(&pWin->drawable);
73805b261ecSmrg
73905b261ecSmrg    RL_DEBUG_MSG("resizecopywindowFB end\n");
74005b261ecSmrg}
74105b261ecSmrg
74205b261ecSmrg
74305b261ecSmrg/*
74405b261ecSmrg * RootlessCopyWindow
74505b261ecSmrg *  Update *new* location of window. Old location is redrawn with
7464642e01fSmrg *  miPaintWindow. Cloned from fbCopyWindow.
74705b261ecSmrg *  The original always draws on the root pixmap, which we don't have.
74805b261ecSmrg *  Instead, draw on the parent window's pixmap.
74905b261ecSmrg */
75005b261ecSmrgvoid
75105b261ecSmrgRootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
75205b261ecSmrg{
75305b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
75405b261ecSmrg    RegionRec   rgnDst;
75505b261ecSmrg    int         dx, dy;
75605b261ecSmrg    BoxPtr extents;
75705b261ecSmrg    int area;
75805b261ecSmrg
75905b261ecSmrg    RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin);
76005b261ecSmrg
76105b261ecSmrg    SCREEN_UNWRAP(pScreen, CopyWindow);
76205b261ecSmrg
76305b261ecSmrg    dx = ptOldOrg.x - pWin->drawable.x;
76405b261ecSmrg    dy = ptOldOrg.y - pWin->drawable.y;
7656747b715Smrg    RegionTranslate(prgnSrc, -dx, -dy);
76605b261ecSmrg
7676747b715Smrg    RegionNull(&rgnDst);
7686747b715Smrg    RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
76905b261ecSmrg
7706747b715Smrg    extents = RegionExtents(&rgnDst);
77105b261ecSmrg    area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1);
77205b261ecSmrg
77305b261ecSmrg    /* If the area exceeds threshold, use the implementation's
77405b261ecSmrg       accelerated version. */
77505b261ecSmrg    if (area > rootless_CopyWindow_threshold &&
77605b261ecSmrg        SCREENREC(pScreen)->imp->CopyWindow)
77705b261ecSmrg    {
77805b261ecSmrg        RootlessWindowRec *winRec;
77905b261ecSmrg        WindowPtr top;
78005b261ecSmrg
78105b261ecSmrg        top = TopLevelParent(pWin);
78205b261ecSmrg        if (top == NULL) {
78305b261ecSmrg            RL_DEBUG_MSG("no parent\n");
7844642e01fSmrg            goto out;
78505b261ecSmrg        }
78605b261ecSmrg
78705b261ecSmrg        winRec = WINREC(top);
78805b261ecSmrg        if (winRec == NULL) {
78905b261ecSmrg            RL_DEBUG_MSG("not framed\n");
7904642e01fSmrg            goto out;
79105b261ecSmrg        }
79205b261ecSmrg
79305b261ecSmrg        /* Move region to window local coords */
7946747b715Smrg        RegionTranslate(&rgnDst, -winRec->x, -winRec->y);
79505b261ecSmrg
79605b261ecSmrg        RootlessStopDrawing(pWin, FALSE);
79705b261ecSmrg
79805b261ecSmrg        SCREENREC(pScreen)->imp->CopyWindow(winRec->wid,
7996747b715Smrg                                            RegionNumRects(&rgnDst),
8006747b715Smrg                                            RegionRects(&rgnDst),
80105b261ecSmrg                                            dx, dy);
80205b261ecSmrg    }
80305b261ecSmrg    else {
80405b261ecSmrg        RootlessStartDrawing(pWin);
80505b261ecSmrg
80605b261ecSmrg        fbCopyRegion((DrawablePtr) pWin, (DrawablePtr) pWin,
80705b261ecSmrg                     0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
80805b261ecSmrg
80905b261ecSmrg        /* prgnSrc has been translated to dst position */
81005b261ecSmrg        RootlessDamageRegion(pWin, prgnSrc);
81105b261ecSmrg    }
81205b261ecSmrg
8134642e01fSmrgout:
8146747b715Smrg    RegionUninit(&rgnDst);
81505b261ecSmrg    fbValidateDrawable(&pWin->drawable);
81605b261ecSmrg
81705b261ecSmrg    SCREEN_WRAP(pScreen, CopyWindow);
81805b261ecSmrg
81905b261ecSmrg    RL_DEBUG_MSG("copywindowFB end\n");
82005b261ecSmrg}
82105b261ecSmrg
82205b261ecSmrg
82305b261ecSmrg/*
82405b261ecSmrg * Window resize procedures
82505b261ecSmrg */
82605b261ecSmrg
82705b261ecSmrgenum {
82805b261ecSmrg    WIDTH_SMALLER = 1,
82905b261ecSmrg    HEIGHT_SMALLER = 2,
83005b261ecSmrg};
83105b261ecSmrg
83205b261ecSmrg
83305b261ecSmrg/*
83405b261ecSmrg * ResizeWeighting
83505b261ecSmrg *  Choose gravity to avoid local copies. Do that by looking for
83605b261ecSmrg *  a corner that doesn't move _relative to the screen_.
83705b261ecSmrg */
83805b261ecSmrgstatic inline unsigned int
83905b261ecSmrgResizeWeighting(int oldX1, int oldY1, int oldX2, int oldY2, int oldBW,
84005b261ecSmrg                int newX1, int newY1, int newX2, int newY2, int newBW)
84105b261ecSmrg{
84205b261ecSmrg#ifdef ROOTLESS_RESIZE_GRAVITY
84305b261ecSmrg    if (newBW != oldBW)
84405b261ecSmrg        return RL_GRAVITY_NONE;
84505b261ecSmrg
84605b261ecSmrg    if (newX1 == oldX1 && newY1 == oldY1)
84705b261ecSmrg        return RL_GRAVITY_NORTH_WEST;
84805b261ecSmrg    else if (newX1 == oldX1 && newY2 == oldY2)
84905b261ecSmrg        return RL_GRAVITY_SOUTH_WEST;
85005b261ecSmrg    else if (newX2 == oldX2 && newY2 == oldY2)
85105b261ecSmrg        return RL_GRAVITY_SOUTH_EAST;
85205b261ecSmrg    else if (newX2 == oldX2 && newY1 == oldY1)
85305b261ecSmrg        return RL_GRAVITY_NORTH_EAST;
85405b261ecSmrg    else
85505b261ecSmrg        return RL_GRAVITY_NONE;
85605b261ecSmrg#else
85705b261ecSmrg    return RL_GRAVITY_NONE;
85805b261ecSmrg#endif
85905b261ecSmrg}
86005b261ecSmrg
86105b261ecSmrg
86205b261ecSmrg/*
86305b261ecSmrg * StartFrameResize
86405b261ecSmrg *  Prepare to resize a top-level window. The old window's pixels are
86505b261ecSmrg *  saved and the implementation is told to change the window size.
86605b261ecSmrg *  (x,y,w,h) is outer frame of window (outside border)
86705b261ecSmrg */
86805b261ecSmrgstatic Bool
86905b261ecSmrgStartFrameResize(WindowPtr pWin, Bool gravity,
87005b261ecSmrg                 int oldX, int oldY, int oldW, int oldH, int oldBW,
87105b261ecSmrg                 int newX, int newY, int newW, int newH, int newBW)
87205b261ecSmrg{
87305b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
87405b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
87505b261ecSmrg    Bool need_window_source = FALSE, resize_after = FALSE;
87605b261ecSmrg
87705b261ecSmrg    BoxRec rect;
87805b261ecSmrg    int oldX2, newX2;
87905b261ecSmrg    int oldY2, newY2;
88005b261ecSmrg    unsigned int weight;
88105b261ecSmrg
88205b261ecSmrg    oldX2 = oldX + oldW, newX2 = newX + newW;
88305b261ecSmrg    oldY2 = oldY + oldH, newY2 = newY + newH;
88405b261ecSmrg
88505b261ecSmrg    /* Decide which resize weighting to use */
88605b261ecSmrg    weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW,
88705b261ecSmrg                             newX, newY, newW, newH, newBW);
88805b261ecSmrg
88905b261ecSmrg    /* Compute intersection between old and new rects */
89005b261ecSmrg    rect.x1 = max(oldX, newX);
89105b261ecSmrg    rect.y1 = max(oldY, newY);
89205b261ecSmrg    rect.x2 = min(oldX2, newX2);
89305b261ecSmrg    rect.y2 = min(oldY2, newY2);
89405b261ecSmrg
89505b261ecSmrg    RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity);
89605b261ecSmrg    RL_DEBUG_MSG("%d %d %d %d %d   %d %d %d %d %d\n",
89705b261ecSmrg                 oldX, oldY, oldW, oldH, oldBW,
89805b261ecSmrg                 newX, newY, newW, newH, newBW);
89905b261ecSmrg
90005b261ecSmrg    RootlessRedisplay(pWin);
90105b261ecSmrg
90205b261ecSmrg    /* If gravity is true, then we need to have a way of recovering all
90305b261ecSmrg       the original bits in the window for when X rearranges the contents
90405b261ecSmrg       based on the various gravity settings. The obvious way is to just
90505b261ecSmrg       snapshot the entire backing store before resizing it, but that
90605b261ecSmrg       it slow on large windows.
90705b261ecSmrg
90805b261ecSmrg       So the optimization here is to use the implementation's resize
90905b261ecSmrg       weighting options (if available) to allow us to reason about what
91005b261ecSmrg       is left in the backing store after the resize. We can then only
91105b261ecSmrg       copy what won't be there after the resize, and do a two-stage copy
91205b261ecSmrg       operation.
91305b261ecSmrg
91405b261ecSmrg       Most of these optimizations are only applied when the top-left
91505b261ecSmrg       corner of the window is fixed, since that's the common case. They
91605b261ecSmrg       could probably be extended with some thought. */
91705b261ecSmrg
91805b261ecSmrg    gResizeDeathCount = 0;
91905b261ecSmrg
92005b261ecSmrg    if (gravity && weight == RL_GRAVITY_NORTH_WEST) {
92105b261ecSmrg        unsigned int code = 0;
92205b261ecSmrg
92305b261ecSmrg        /* Top left corner is anchored. We never need to copy the
92405b261ecSmrg           entire window. */
92505b261ecSmrg
92605b261ecSmrg        need_window_source = TRUE;
92705b261ecSmrg
92805b261ecSmrg        /* These comparisons were chosen to avoid setting bits when the sizes
92905b261ecSmrg        are the same. (So the fastest case automatically gets taken when
93005b261ecSmrg        dimensions are unchanging.) */
93105b261ecSmrg
93205b261ecSmrg        if (newW < oldW)
93305b261ecSmrg            code |= WIDTH_SMALLER;
93405b261ecSmrg        if (newH < oldH)
93505b261ecSmrg            code |= HEIGHT_SMALLER;
93605b261ecSmrg
93705b261ecSmrg        if (((code ^ (code >> 1)) & 1) == 0) {
93805b261ecSmrg            /* Both dimensions are either getting larger, or both
93905b261ecSmrg               are getting smaller. No need to copy anything. */
94005b261ecSmrg
94105b261ecSmrg            if (code == (WIDTH_SMALLER | HEIGHT_SMALLER)) {
94205b261ecSmrg                /* Since the window is getting smaller, we can do gravity
94305b261ecSmrg                   repair on it with it's current size, then resize it
94405b261ecSmrg                   afterwards. */
94505b261ecSmrg
94605b261ecSmrg                resize_after = TRUE;
94705b261ecSmrg            }
94805b261ecSmrg
94905b261ecSmrg            gResizeDeathCount = 1;
95005b261ecSmrg        }
95105b261ecSmrg        else {
95205b261ecSmrg            unsigned int copy_rowbytes, Bpp;
95305b261ecSmrg            unsigned int copy_rect_width, copy_rect_height;
95405b261ecSmrg            BoxRec copy_rect;
95505b261ecSmrg
95605b261ecSmrg            /* We can get away with a partial copy. 'rect' is the
95705b261ecSmrg               intersection between old and new bounds, so copy
95805b261ecSmrg               everything to the right of or below the intersection. */
95905b261ecSmrg
96005b261ecSmrg            RootlessStartDrawing(pWin);
96105b261ecSmrg
96205b261ecSmrg            if (code == WIDTH_SMALLER) {
96305b261ecSmrg                copy_rect.x1 = rect.x2;
96405b261ecSmrg                copy_rect.y1 = rect.y1;
96505b261ecSmrg                copy_rect.x2 = oldX2;
96605b261ecSmrg                copy_rect.y2 = oldY2;
96705b261ecSmrg            }
96805b261ecSmrg            else if (code == HEIGHT_SMALLER) {
96905b261ecSmrg                copy_rect.x1 = rect.x1;
97005b261ecSmrg                copy_rect.y1 = rect.y2;
97105b261ecSmrg                copy_rect.x2 = oldX2;
97205b261ecSmrg                copy_rect.y2 = oldY2;
97305b261ecSmrg            }
97405b261ecSmrg            else
9756747b715Smrg                OsAbort();
97605b261ecSmrg
97705b261ecSmrg            Bpp = winRec->win->drawable.bitsPerPixel / 8;
97805b261ecSmrg            copy_rect_width = copy_rect.x2 - copy_rect.x1;
97905b261ecSmrg            copy_rect_height = copy_rect.y2 - copy_rect.y1;
98005b261ecSmrg            copy_rowbytes = ((copy_rect_width * Bpp) + 31) & ~31;
9816747b715Smrg            gResizeDeathBits = malloc(copy_rowbytes
98205b261ecSmrg                                      * copy_rect_height);
98305b261ecSmrg
98405b261ecSmrg            if (copy_rect_width * copy_rect_height >
98505b261ecSmrg                        rootless_CopyBytes_threshold &&
98605b261ecSmrg                SCREENREC(pScreen)->imp->CopyBytes)
98705b261ecSmrg            {
98805b261ecSmrg                SCREENREC(pScreen)->imp->CopyBytes(
98905b261ecSmrg                    copy_rect_width * Bpp, copy_rect_height,
99005b261ecSmrg                    ((char *) winRec->pixelData)
99105b261ecSmrg                    + ((copy_rect.y1 - oldY) * winRec->bytesPerRow)
99205b261ecSmrg                    + (copy_rect.x1 - oldX) * Bpp, winRec->bytesPerRow,
99305b261ecSmrg                    gResizeDeathBits, copy_rowbytes);
99405b261ecSmrg            } else {
99505b261ecSmrg                fbBlt((FbBits *) (winRec->pixelData
99605b261ecSmrg                      + ((copy_rect.y1 - oldY) * winRec->bytesPerRow)
99705b261ecSmrg                      + (copy_rect.x1 - oldX) * Bpp),
99805b261ecSmrg                      winRec->bytesPerRow / sizeof(FbBits), 0,
99905b261ecSmrg                      (FbBits *) gResizeDeathBits,
100005b261ecSmrg                      copy_rowbytes / sizeof(FbBits), 0,
100105b261ecSmrg                      copy_rect_width * Bpp, copy_rect_height,
100205b261ecSmrg                      GXcopy, FB_ALLONES, Bpp, 0, 0);
100305b261ecSmrg            }
100405b261ecSmrg
100505b261ecSmrg            gResizeDeathBounds[1] = copy_rect;
100605b261ecSmrg            gResizeDeathPix[1]
100705b261ecSmrg                = GetScratchPixmapHeader(pScreen, copy_rect_width,
100805b261ecSmrg                                         copy_rect_height,
100905b261ecSmrg                                         winRec->win->drawable.depth,
101005b261ecSmrg                                         winRec->win->drawable.bitsPerPixel,
101105b261ecSmrg                                         winRec->bytesPerRow,
101205b261ecSmrg                                         (void *) gResizeDeathBits);
101305b261ecSmrg
101405b261ecSmrg            SetPixmapBaseToScreen(gResizeDeathPix[1],
101505b261ecSmrg                                  copy_rect.x1, copy_rect.y1);
101605b261ecSmrg
101705b261ecSmrg            gResizeDeathCount = 2;
101805b261ecSmrg        }
101905b261ecSmrg    }
102005b261ecSmrg    else if (gravity) {
102105b261ecSmrg        /* The general case. Just copy everything. */
102205b261ecSmrg
102305b261ecSmrg        RootlessStartDrawing(pWin);
102405b261ecSmrg
10256747b715Smrg        gResizeDeathBits = malloc(winRec->bytesPerRow * winRec->height);
102605b261ecSmrg
102705b261ecSmrg        memcpy(gResizeDeathBits, winRec->pixelData,
102805b261ecSmrg               winRec->bytesPerRow * winRec->height);
102905b261ecSmrg
103005b261ecSmrg        gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
103105b261ecSmrg        gResizeDeathPix[0]
103205b261ecSmrg            = GetScratchPixmapHeader(pScreen, winRec->width,
103305b261ecSmrg                                     winRec->height,
103405b261ecSmrg                                     winRec->win->drawable.depth,
103505b261ecSmrg                                     winRec->win->drawable.bitsPerPixel,
103605b261ecSmrg                                     winRec->bytesPerRow,
103705b261ecSmrg                                     (void *) gResizeDeathBits);
103805b261ecSmrg
103905b261ecSmrg        SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY);
104005b261ecSmrg        gResizeDeathCount = 1;
104105b261ecSmrg    }
104205b261ecSmrg
104305b261ecSmrg    RootlessStopDrawing(pWin, FALSE);
104405b261ecSmrg
104505b261ecSmrg    winRec->x = newX;
104605b261ecSmrg    winRec->y = newY;
104705b261ecSmrg    winRec->width = newW;
104805b261ecSmrg    winRec->height = newH;
104905b261ecSmrg    winRec->borderWidth = newBW;
105005b261ecSmrg
105105b261ecSmrg    /* Unless both dimensions are getting smaller, Resize the frame
105205b261ecSmrg       before doing gravity repair */
105305b261ecSmrg
105405b261ecSmrg    if (!resize_after) {
105505b261ecSmrg        SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
105605b261ecSmrg                                             newX + SCREEN_TO_GLOBAL_X,
105705b261ecSmrg                                             newY + SCREEN_TO_GLOBAL_Y,
105805b261ecSmrg                                             newW, newH, weight);
105905b261ecSmrg    }
106005b261ecSmrg
106105b261ecSmrg    RootlessStartDrawing(pWin);
106205b261ecSmrg
106305b261ecSmrg    /* If necessary, create a source pixmap pointing at the current
106405b261ecSmrg       window bits. */
106505b261ecSmrg
106605b261ecSmrg    if (need_window_source) {
106705b261ecSmrg        gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
106805b261ecSmrg        gResizeDeathPix[0]
106905b261ecSmrg            = GetScratchPixmapHeader(pScreen, oldW, oldH,
107005b261ecSmrg                                     winRec->win->drawable.depth,
107105b261ecSmrg                                     winRec->win->drawable.bitsPerPixel,
107205b261ecSmrg                                     winRec->bytesPerRow, winRec->pixelData);
107305b261ecSmrg
107405b261ecSmrg        SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY);
107505b261ecSmrg    }
107605b261ecSmrg
107705b261ecSmrg    /* Use custom CopyWindow when moving gravity bits around
107805b261ecSmrg       ResizeWindow assumes the old window contents are in the same
107905b261ecSmrg       pixmap, but here they're in deathPix instead. */
108005b261ecSmrg
108105b261ecSmrg    if (gravity) {
108205b261ecSmrg        gResizeOldCopyWindowProc = pScreen->CopyWindow;
108305b261ecSmrg        pScreen->CopyWindow = RootlessResizeCopyWindow;
108405b261ecSmrg    }
108505b261ecSmrg
108605b261ecSmrg    /* If we can't rely on the window server preserving the bits we
108705b261ecSmrg       need in the position we need, copy the pixels in the
108805b261ecSmrg       intersection from src to dst. ResizeWindow assumes these pixels
108905b261ecSmrg       are already present when making gravity adjustments. pWin
109005b261ecSmrg       currently has new-sized pixmap but is in old position.
109105b261ecSmrg
109205b261ecSmrg       FIXME: border width change! (?) */
109305b261ecSmrg
109405b261ecSmrg    if (gravity && weight == RL_GRAVITY_NONE) {
109505b261ecSmrg        PixmapPtr src, dst;
109605b261ecSmrg
109705b261ecSmrg        assert(gResizeDeathCount == 1);
109805b261ecSmrg
109905b261ecSmrg        src = gResizeDeathPix[0];
110005b261ecSmrg        dst = pScreen->GetWindowPixmap(pWin);
110105b261ecSmrg
110205b261ecSmrg        RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n",
110305b261ecSmrg                     rect.x1, rect.y1, rect.x2, rect.y2);
110405b261ecSmrg
110505b261ecSmrg        /* rect is the intersection of the old location and new location */
110605b261ecSmrg        if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL) {
110705b261ecSmrg            /* The window drawable still has the old frame position, which
110805b261ecSmrg               means that DST doesn't actually point at the origin of our
110905b261ecSmrg               physical backing store when adjusted by the drawable.x,y
111005b261ecSmrg               position. So sneakily adjust it temporarily while copying.. */
111105b261ecSmrg
111205b261ecSmrg            ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData;
111305b261ecSmrg            SetPixmapBaseToScreen(dst, newX, newY);
111405b261ecSmrg
111505b261ecSmrg            fbCopyWindowProc(&src->drawable, &dst->drawable, NULL,
111605b261ecSmrg                             &rect, 1, 0, 0, FALSE, FALSE, 0, 0);
111705b261ecSmrg
111805b261ecSmrg            ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData;
111905b261ecSmrg            SetPixmapBaseToScreen(dst, oldX, oldY);
112005b261ecSmrg        }
112105b261ecSmrg    }
112205b261ecSmrg
112305b261ecSmrg    return resize_after;
112405b261ecSmrg}
112505b261ecSmrg
112605b261ecSmrg
112705b261ecSmrgstatic void
112805b261ecSmrgFinishFrameResize(WindowPtr pWin, Bool gravity, int oldX, int oldY,
112905b261ecSmrg                  unsigned int oldW, unsigned int oldH, unsigned int oldBW,
113005b261ecSmrg                  int newX, int newY, unsigned int newW, unsigned int newH,
113105b261ecSmrg                  unsigned int newBW, Bool resize_now)
113205b261ecSmrg{
113305b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
113405b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
113505b261ecSmrg    int i;
113605b261ecSmrg
113705b261ecSmrg    RootlessStopDrawing(pWin, FALSE);
113805b261ecSmrg
113905b261ecSmrg    if (resize_now) {
114005b261ecSmrg        unsigned int weight;
114105b261ecSmrg
114205b261ecSmrg        /* We didn't resize anything earlier, so do it now, now that
114305b261ecSmrg           we've finished gravitating the bits. */
114405b261ecSmrg
114505b261ecSmrg        weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW,
114605b261ecSmrg                                 newX, newY, newW, newH, newBW);
114705b261ecSmrg
114805b261ecSmrg        SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
114905b261ecSmrg                                             newX + SCREEN_TO_GLOBAL_X,
115005b261ecSmrg                                             newY + SCREEN_TO_GLOBAL_Y,
115105b261ecSmrg                                             newW, newH, weight);
115205b261ecSmrg    }
115305b261ecSmrg
115405b261ecSmrg    /* Redraw everything. FIXME: there must be times when we don't need
115505b261ecSmrg       to do this. Perhaps when top-left weighting and no gravity? */
115605b261ecSmrg
115705b261ecSmrg    RootlessDamageRect(pWin, -newBW, -newBW, newW, newH);
115805b261ecSmrg
115905b261ecSmrg    for (i = 0; i < 2; i++) {
116005b261ecSmrg        if (gResizeDeathPix[i] != NULL) {
116105b261ecSmrg            FreeScratchPixmapHeader(gResizeDeathPix[i]);
116205b261ecSmrg            gResizeDeathPix[i] = NULL;
116305b261ecSmrg        }
116405b261ecSmrg    }
116505b261ecSmrg
116605b261ecSmrg    if (gResizeDeathBits != NULL) {
11676747b715Smrg        free(gResizeDeathBits);
116805b261ecSmrg        gResizeDeathBits = NULL;
116905b261ecSmrg    }
117005b261ecSmrg
117105b261ecSmrg    if (gravity) {
117205b261ecSmrg        pScreen->CopyWindow = gResizeOldCopyWindowProc;
117305b261ecSmrg    }
117405b261ecSmrg}
117505b261ecSmrg
117605b261ecSmrg
117705b261ecSmrg/*
117805b261ecSmrg * RootlessMoveWindow
117905b261ecSmrg *  If kind==VTOther, window border is resizing (and borderWidth is
118005b261ecSmrg *  already changed!!@#$)  This case works like window resize, not move.
118105b261ecSmrg */
118205b261ecSmrgvoid
118305b261ecSmrgRootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
118405b261ecSmrg{
118505b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
118605b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
118705b261ecSmrg    CopyWindowProcPtr oldCopyWindowProc = NULL;
118805b261ecSmrg    int oldX = 0, oldY = 0, newX = 0, newY = 0;
118905b261ecSmrg    unsigned int oldW = 0, oldH = 0, oldBW = 0;
119005b261ecSmrg    unsigned int newW = 0, newH = 0, newBW = 0;
119105b261ecSmrg    Bool resize_after = FALSE;
119205b261ecSmrg    RegionRec saveRoot;
119305b261ecSmrg
119405b261ecSmrg    RL_DEBUG_MSG("movewindow start \n");
119505b261ecSmrg
119605b261ecSmrg    if (winRec) {
119705b261ecSmrg        if (kind == VTMove) {
119805b261ecSmrg            oldX = winRec->x;
119905b261ecSmrg            oldY = winRec->y;
120005b261ecSmrg            RootlessRedisplay(pWin);
120105b261ecSmrg            RootlessStartDrawing(pWin);
120205b261ecSmrg        } else {
120305b261ecSmrg            RL_DEBUG_MSG("movewindow border resizing ");
120405b261ecSmrg
120505b261ecSmrg            oldBW = winRec->borderWidth;
120605b261ecSmrg            oldX = winRec->x;
120705b261ecSmrg            oldY = winRec->y;
120805b261ecSmrg            oldW = winRec->width;
120905b261ecSmrg            oldH = winRec->height;
121005b261ecSmrg
121105b261ecSmrg            newBW = wBorderWidth(pWin);
121205b261ecSmrg            newX = x;
121305b261ecSmrg            newY = y;
121405b261ecSmrg            newW = pWin->drawable.width  + 2*newBW;
121505b261ecSmrg            newH = pWin->drawable.height + 2*newBW;
121605b261ecSmrg
121705b261ecSmrg            resize_after = StartFrameResize(pWin, FALSE,
121805b261ecSmrg                                            oldX, oldY, oldW, oldH, oldBW,
121905b261ecSmrg                                            newX, newY, newW, newH, newBW);
122005b261ecSmrg        }
122105b261ecSmrg    }
122205b261ecSmrg
122305b261ecSmrg    HUGE_ROOT(pWin);
122405b261ecSmrg    SCREEN_UNWRAP(pScreen, MoveWindow);
122505b261ecSmrg
122605b261ecSmrg    if (winRec) {
122705b261ecSmrg        oldCopyWindowProc = pScreen->CopyWindow;
122805b261ecSmrg        pScreen->CopyWindow = RootlessNoCopyWindow;
122905b261ecSmrg    }
123005b261ecSmrg    pScreen->MoveWindow(pWin, x, y, pSib, kind);
123105b261ecSmrg    if (winRec) {
123205b261ecSmrg        pScreen->CopyWindow = oldCopyWindowProc;
123305b261ecSmrg    }
123405b261ecSmrg
123505b261ecSmrg    NORMAL_ROOT(pWin);
123605b261ecSmrg    SCREEN_WRAP(pScreen, MoveWindow);
123705b261ecSmrg
123805b261ecSmrg    if (winRec) {
123905b261ecSmrg        if (kind == VTMove) {
124005b261ecSmrg            winRec->x = x;
124105b261ecSmrg            winRec->y = y;
124205b261ecSmrg            RootlessStopDrawing(pWin, FALSE);
124305b261ecSmrg            SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen,
124405b261ecSmrg                                               x + SCREEN_TO_GLOBAL_X,
124505b261ecSmrg                                               y + SCREEN_TO_GLOBAL_Y);
124605b261ecSmrg        } else {
124705b261ecSmrg            FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
124805b261ecSmrg                              newX, newY, newW, newH, newBW, resize_after);
124905b261ecSmrg        }
125005b261ecSmrg    }
125105b261ecSmrg
125205b261ecSmrg    RL_DEBUG_MSG("movewindow end\n");
125305b261ecSmrg}
125405b261ecSmrg
125505b261ecSmrg
125605b261ecSmrg/*
125705b261ecSmrg * RootlessResizeWindow
125805b261ecSmrg *  Note: (x, y, w, h) as passed to this procedure don't match the frame
125905b261ecSmrg *  definition. (x,y) is corner of very outer edge, *outside* border.
126005b261ecSmrg *  w,h is width and height *inside* border, *ignoring* border width.
126105b261ecSmrg *  The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw)
126205b261ecSmrg *  is total rect and (x+bw, y+bw, w, h) is inner rect.
126305b261ecSmrg */
126405b261ecSmrgvoid
126505b261ecSmrgRootlessResizeWindow(WindowPtr pWin, int x, int y,
126605b261ecSmrg                     unsigned int w, unsigned int h, WindowPtr pSib)
126705b261ecSmrg{
126805b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
126905b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
127005b261ecSmrg    int oldX = 0, oldY = 0, newX = 0, newY = 0;
127105b261ecSmrg    unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0;
127205b261ecSmrg    Bool resize_after = FALSE;
127305b261ecSmrg    RegionRec saveRoot;
127405b261ecSmrg
127505b261ecSmrg    RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin);
12764642e01fSmrg
12774642e01fSmrg    if(pWin->parent) {
12784642e01fSmrg        if (winRec) {
12794642e01fSmrg            oldBW = winRec->borderWidth;
12804642e01fSmrg            oldX = winRec->x;
12814642e01fSmrg            oldY = winRec->y;
12824642e01fSmrg            oldW = winRec->width;
12834642e01fSmrg            oldH = winRec->height;
128405b261ecSmrg
12854642e01fSmrg            newBW = oldBW;
12864642e01fSmrg            newX = x;
12874642e01fSmrg            newY = y;
12884642e01fSmrg            newW = w + 2*newBW;
12894642e01fSmrg            newH = h + 2*newBW;
129005b261ecSmrg
12914642e01fSmrg            resize_after = StartFrameResize(pWin, TRUE,
12924642e01fSmrg                                            oldX, oldY, oldW, oldH, oldBW,
12934642e01fSmrg                                            newX, newY, newW, newH, newBW);
12944642e01fSmrg        }
129505b261ecSmrg
12964642e01fSmrg        HUGE_ROOT(pWin);
12974642e01fSmrg        SCREEN_UNWRAP(pScreen, ResizeWindow);
12984642e01fSmrg        pScreen->ResizeWindow(pWin, x, y, w, h, pSib);
12994642e01fSmrg        SCREEN_WRAP(pScreen, ResizeWindow);
13004642e01fSmrg        NORMAL_ROOT(pWin);
13014642e01fSmrg
13024642e01fSmrg        if (winRec) {
13034642e01fSmrg            FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
13044642e01fSmrg                              newX, newY, newW, newH, newBW, resize_after);
13054642e01fSmrg        }
13064642e01fSmrg    } else {
13074642e01fSmrg        /* Special case for resizing the root window */
13084642e01fSmrg        BoxRec box;
13094642e01fSmrg
13104642e01fSmrg        pWin->drawable.x = x;
13114642e01fSmrg        pWin->drawable.y = y;
13124642e01fSmrg        pWin->drawable.width = w;
13134642e01fSmrg        pWin->drawable.height = h;
13144642e01fSmrg
13154642e01fSmrg        box.x1 = x; box.y1 = y;
13164642e01fSmrg        box.x2 = x + w; box.y2 = y + h;
13176747b715Smrg        RegionUninit(&pWin->winSize);
13186747b715Smrg        RegionInit(&pWin->winSize, &box, 1);
13196747b715Smrg        RegionCopy(&pWin->borderSize, &pWin->winSize);
13206747b715Smrg        RegionCopy(&pWin->clipList, &pWin->winSize);
13216747b715Smrg        RegionCopy(&pWin->borderClip, &pWin->winSize);
13226747b715Smrg
13236747b715Smrg        if (winRec) {
13246747b715Smrg            SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
13256747b715Smrg                                                 x + SCREEN_TO_GLOBAL_X,
13266747b715Smrg                                                 y + SCREEN_TO_GLOBAL_Y,
13276747b715Smrg                                                 w, h, RL_GRAVITY_NONE);
13286747b715Smrg        }
13294642e01fSmrg
13304642e01fSmrg        miSendExposures(pWin, &pWin->borderClip,
13314642e01fSmrg                        pWin->drawable.x, pWin->drawable.y);
133205b261ecSmrg    }
133305b261ecSmrg
133405b261ecSmrg    RL_DEBUG_MSG("resizewindow end\n");
133505b261ecSmrg}
133605b261ecSmrg
133705b261ecSmrg
133805b261ecSmrg/*
133905b261ecSmrg * RootlessRepositionWindow
134005b261ecSmrg *  Called by the implementation when a window needs to be repositioned to
134105b261ecSmrg *  its correct location on the screen. This routine is typically needed
134205b261ecSmrg *  due to changes in the underlying window system, such as a screen layout
134305b261ecSmrg *  change.
134405b261ecSmrg */
134505b261ecSmrgvoid
134605b261ecSmrgRootlessRepositionWindow(WindowPtr pWin)
134705b261ecSmrg{
134805b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
134905b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
135005b261ecSmrg
135105b261ecSmrg    if (winRec == NULL)
135205b261ecSmrg        return;
135305b261ecSmrg
135405b261ecSmrg    RootlessStopDrawing(pWin, FALSE);
135505b261ecSmrg    SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen,
135605b261ecSmrg                                       winRec->x + SCREEN_TO_GLOBAL_X,
135705b261ecSmrg                                       winRec->y + SCREEN_TO_GLOBAL_Y);
135805b261ecSmrg
135905b261ecSmrg    RootlessReorderWindow(pWin);
136005b261ecSmrg}
136105b261ecSmrg
136205b261ecSmrg
136305b261ecSmrg/*
136405b261ecSmrg * RootlessReparentWindow
136505b261ecSmrg *  Called after a window has been reparented. Generally windows are not
136605b261ecSmrg *  framed until they are mapped. However, a window may be framed early by the
136705b261ecSmrg *  implementation calling RootlessFrameForWindow. (e.g. this could be needed
136805b261ecSmrg *  to attach a VRAM surface to it.) If the window is subsequently reparented
136905b261ecSmrg *  by the window manager before being mapped, we need to give the frame to
137005b261ecSmrg *  the new top-level window.
137105b261ecSmrg */
137205b261ecSmrgvoid
137305b261ecSmrgRootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent)
137405b261ecSmrg{
137505b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
137605b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
137705b261ecSmrg    WindowPtr pTopWin;
137805b261ecSmrg
137905b261ecSmrg    /* Check that window is not top-level now, but used to be. */
138005b261ecSmrg    if (IsRoot(pWin) || IsRoot(pWin->parent)
138105b261ecSmrg        || IsTopLevel(pWin) || winRec == NULL)
138205b261ecSmrg    {
138305b261ecSmrg        goto out;
138405b261ecSmrg    }
138505b261ecSmrg
138605b261ecSmrg    /* If the formerly top-level window has a frame, we want to give the
138705b261ecSmrg       frame to its new top-level parent. If we can't do that, we'll just
138805b261ecSmrg       have to jettison it... */
138905b261ecSmrg
139005b261ecSmrg    pTopWin = TopLevelParent(pWin);
139105b261ecSmrg    assert(pTopWin != pWin);
13924642e01fSmrg
13934642e01fSmrg    pWin->rootlessUnhittable = FALSE;
13944642e01fSmrg
13954642e01fSmrg    DeleteProperty (serverClient, pWin, xa_native_window_id ());
139605b261ecSmrg
139705b261ecSmrg    if (WINREC(pTopWin) != NULL) {
139805b261ecSmrg        /* We're screwed. */
139905b261ecSmrg        RootlessDestroyFrame(pWin, winRec);
140005b261ecSmrg    } else {
140105b261ecSmrg        if (!pTopWin->realized && pWin->realized) {
140205b261ecSmrg            SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid);
140305b261ecSmrg        }
140405b261ecSmrg
140505b261ecSmrg        /* Switch the frame record from one to the other. */
140605b261ecSmrg
14074642e01fSmrg        SETWINREC(pWin, NULL);
14084642e01fSmrg        SETWINREC(pTopWin, winRec);
140905b261ecSmrg
141005b261ecSmrg        RootlessInitializeFrame(pTopWin, winRec);
141105b261ecSmrg        RootlessReshapeFrame(pTopWin);
141205b261ecSmrg
141305b261ecSmrg        SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
141405b261ecSmrg                                             winRec->x + SCREEN_TO_GLOBAL_X,
141505b261ecSmrg                                             winRec->y + SCREEN_TO_GLOBAL_Y,
141605b261ecSmrg                                             winRec->width, winRec->height,
141705b261ecSmrg                                             RL_GRAVITY_NONE);
141805b261ecSmrg
141905b261ecSmrg        if (SCREENREC(pScreen)->imp->SwitchWindow) {
142005b261ecSmrg            SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin);
142105b261ecSmrg        }
142205b261ecSmrg
142305b261ecSmrg        if (pTopWin->realized && !pWin->realized)
142405b261ecSmrg            winRec->is_reorder_pending = TRUE;
142505b261ecSmrg    }
142605b261ecSmrg
142705b261ecSmrgout:
142805b261ecSmrg    if (SCREENREC(pScreen)->ReparentWindow) {
142905b261ecSmrg        SCREEN_UNWRAP(pScreen, ReparentWindow);
143005b261ecSmrg        pScreen->ReparentWindow(pWin, pPriorParent);
143105b261ecSmrg        SCREEN_WRAP(pScreen, ReparentWindow);
143205b261ecSmrg    }
143305b261ecSmrg}
143405b261ecSmrg
143505b261ecSmrg
143605b261ecSmrgvoid
14374642e01fSmrgRootlessFlushWindowColormap (WindowPtr pWin)
143805b261ecSmrg{
14394642e01fSmrg  RootlessWindowRec *winRec = WINREC (pWin);
14406747b715Smrg  ScreenPtr pScreen = pWin->drawable.pScreen;
144105b261ecSmrg
14424642e01fSmrg  if (winRec == NULL)
14434642e01fSmrg    return;
144405b261ecSmrg
14454642e01fSmrg  RootlessStopDrawing (pWin, FALSE);
144605b261ecSmrg
14476747b715Smrg  if (SCREENREC(pScreen)->imp->UpdateColormap)
14486747b715Smrg    SCREENREC(pScreen)->imp->UpdateColormap(winRec->wid, pScreen);
144905b261ecSmrg}
145005b261ecSmrg
145105b261ecSmrg/*
145205b261ecSmrg * RootlessChangeBorderWidth
145305b261ecSmrg *  FIXME: untested!
145405b261ecSmrg *  pWin inside corner stays the same; pWin->drawable.[xy] stays the same
145505b261ecSmrg *  Frame moves and resizes.
145605b261ecSmrg */
145705b261ecSmrgvoid
145805b261ecSmrgRootlessChangeBorderWidth(WindowPtr pWin, unsigned int width)
145905b261ecSmrg{
146005b261ecSmrg    RegionRec saveRoot;
146105b261ecSmrg    Bool resize_after = FALSE;
146205b261ecSmrg
146305b261ecSmrg    RL_DEBUG_MSG("change border width ");
146405b261ecSmrg
146505b261ecSmrg    if (width != wBorderWidth(pWin)) {
146605b261ecSmrg        RootlessWindowRec *winRec = WINREC(pWin);
146705b261ecSmrg        int oldX = 0, oldY = 0, newX = 0, newY = 0;
146805b261ecSmrg        unsigned int oldW = 0, oldH = 0, oldBW = 0;
146905b261ecSmrg        unsigned int newW = 0, newH = 0, newBW = 0;
147005b261ecSmrg
147105b261ecSmrg        if (winRec) {
147205b261ecSmrg            oldBW = winRec->borderWidth;
147305b261ecSmrg            oldX = winRec->x;
147405b261ecSmrg            oldY = winRec->y;
147505b261ecSmrg            oldW = winRec->width;
147605b261ecSmrg            oldH = winRec->height;
147705b261ecSmrg
147805b261ecSmrg            newBW = width;
147905b261ecSmrg            newX = pWin->drawable.x - newBW;
148005b261ecSmrg            newY = pWin->drawable.y - newBW;
148105b261ecSmrg            newW = pWin->drawable.width  + 2*newBW;
148205b261ecSmrg            newH = pWin->drawable.height + 2*newBW;
148305b261ecSmrg
148405b261ecSmrg            resize_after = StartFrameResize(pWin, FALSE,
148505b261ecSmrg                                            oldX, oldY, oldW, oldH, oldBW,
148605b261ecSmrg                                            newX, newY, newW, newH, newBW);
148705b261ecSmrg        }
148805b261ecSmrg
148905b261ecSmrg        HUGE_ROOT(pWin);
149005b261ecSmrg        SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth);
149105b261ecSmrg        pWin->drawable.pScreen->ChangeBorderWidth(pWin, width);
149205b261ecSmrg        SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth);
149305b261ecSmrg        NORMAL_ROOT(pWin);
149405b261ecSmrg
149505b261ecSmrg        if (winRec) {
149605b261ecSmrg            FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
149705b261ecSmrg                              newX, newY, newW, newH, newBW, resize_after);
149805b261ecSmrg        }
149905b261ecSmrg    }
150005b261ecSmrg
150105b261ecSmrg    RL_DEBUG_MSG("change border width end\n");
150205b261ecSmrg}
15034642e01fSmrg
15044642e01fSmrg/*
15054642e01fSmrg * RootlessOrderAllWindows
15064642e01fSmrg * Brings all X11 windows to the top of the window stack
15074642e01fSmrg * (i.e in front of Aqua windows) -- called when X11.app is given focus
15084642e01fSmrg */
15094642e01fSmrgvoid
15106747b715SmrgRootlessOrderAllWindows (Bool include_unhitable)
15114642e01fSmrg{
15124642e01fSmrg    int i;
15134642e01fSmrg    WindowPtr pWin;
15144642e01fSmrg
15154642e01fSmrg    if (windows_hidden)
15164642e01fSmrg        return;
15174642e01fSmrg
15184642e01fSmrg    RL_DEBUG_MSG("RootlessOrderAllWindows() ");
15194642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
15204642e01fSmrg      if (screenInfo.screens[i] == NULL) continue;
15216747b715Smrg      pWin = screenInfo.screens[i]->root;
15224642e01fSmrg      if (pWin == NULL) continue;
15234642e01fSmrg
15244642e01fSmrg      for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) {
15254642e01fSmrg	if (!pWin->realized) continue;
15264642e01fSmrg	if (RootlessEnsureFrame(pWin) == NULL) continue;
15276747b715Smrg        if (!include_unhitable && pWin->rootlessUnhittable) continue;
15284642e01fSmrg	RootlessReorderWindow (pWin);
15294642e01fSmrg      }
15304642e01fSmrg    }
15314642e01fSmrg    RL_DEBUG_MSG("RootlessOrderAllWindows() done");
15324642e01fSmrg}
15334642e01fSmrg
15344642e01fSmrgvoid
15354642e01fSmrgRootlessEnableRoot (ScreenPtr pScreen)
15364642e01fSmrg{
15374642e01fSmrg    WindowPtr pRoot;
15386747b715Smrg    pRoot = pScreen->root;
15394642e01fSmrg
15404642e01fSmrg    RootlessEnsureFrame (pRoot);
15414642e01fSmrg    (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE);
15424642e01fSmrg    RootlessReorderWindow (pRoot);
15434642e01fSmrg}
15444642e01fSmrg
15454642e01fSmrgvoid
15464642e01fSmrgRootlessDisableRoot (ScreenPtr pScreen)
15474642e01fSmrg{
15484642e01fSmrg    WindowPtr pRoot;
15494642e01fSmrg    RootlessWindowRec *winRec;
15504642e01fSmrg
15516747b715Smrg    pRoot = pScreen->root;
15524642e01fSmrg    winRec = WINREC (pRoot);
15534642e01fSmrg
15544642e01fSmrg    if (NULL == winRec)
15554642e01fSmrg	return;
15564642e01fSmrg
15574642e01fSmrg    RootlessDestroyFrame (pRoot, winRec);
15584642e01fSmrg    DeleteProperty (serverClient, pRoot, xa_native_window_id ());
15594642e01fSmrg}
15604642e01fSmrg
15614642e01fSmrgvoid
15624642e01fSmrgRootlessHideAllWindows (void)
15634642e01fSmrg{
15644642e01fSmrg    int i;
15654642e01fSmrg    ScreenPtr pScreen;
15664642e01fSmrg    WindowPtr pWin;
15674642e01fSmrg    RootlessWindowRec *winRec;
15684642e01fSmrg
15694642e01fSmrg    if (windows_hidden)
15704642e01fSmrg        return;
15714642e01fSmrg
15724642e01fSmrg    windows_hidden = TRUE;
15734642e01fSmrg
15744642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++)
15754642e01fSmrg    {
15764642e01fSmrg        pScreen = screenInfo.screens[i];
15776747b715Smrg	if (pScreen == NULL)
15786747b715Smrg	    continue;
15796747b715Smrg	pWin = pScreen->root;
15806747b715Smrg	if (pWin == NULL)
15814642e01fSmrg            continue;
15824642e01fSmrg
15834642e01fSmrg        for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
15844642e01fSmrg        {
15854642e01fSmrg            if (!pWin->realized)
15864642e01fSmrg                continue;
15874642e01fSmrg
15884642e01fSmrg            RootlessStopDrawing (pWin, FALSE);
15894642e01fSmrg
15904642e01fSmrg            winRec = WINREC (pWin);
15914642e01fSmrg            if (winRec != NULL)
15924642e01fSmrg            {
15936747b715Smrg              if (SCREENREC(pScreen)->imp->HideWindow)
15946747b715Smrg                SCREENREC(pScreen)->imp->HideWindow(winRec->wid);
15954642e01fSmrg            }
15964642e01fSmrg        }
15974642e01fSmrg    }
15984642e01fSmrg}
15994642e01fSmrg
16004642e01fSmrgvoid
16014642e01fSmrgRootlessShowAllWindows (void)
16024642e01fSmrg{
16034642e01fSmrg    int i;
16044642e01fSmrg    ScreenPtr pScreen;
16054642e01fSmrg    WindowPtr pWin;
16064642e01fSmrg    RootlessWindowRec *winRec;
16074642e01fSmrg
16084642e01fSmrg    if (!windows_hidden)
16094642e01fSmrg        return;
16104642e01fSmrg
16114642e01fSmrg    windows_hidden = FALSE;
16124642e01fSmrg
16134642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++)
16144642e01fSmrg    {
16154642e01fSmrg        pScreen = screenInfo.screens[i];
16166747b715Smrg	if (pScreen == NULL)
16176747b715Smrg	    continue;
16186747b715Smrg	pWin = pScreen->root;
16196747b715Smrg	if (pWin == NULL)
16204642e01fSmrg            continue;
16214642e01fSmrg
16224642e01fSmrg        for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
16234642e01fSmrg        {
16244642e01fSmrg            if (!pWin->realized)
16254642e01fSmrg                continue;
16264642e01fSmrg
16274642e01fSmrg            winRec = RootlessEnsureFrame (pWin);
16284642e01fSmrg            if (winRec == NULL)
16294642e01fSmrg                continue;
16304642e01fSmrg
16314642e01fSmrg            RootlessReorderWindow (pWin);
16324642e01fSmrg        }
16334642e01fSmrg
16344642e01fSmrg        RootlessScreenExpose (pScreen);
16354642e01fSmrg    }
16364642e01fSmrg}
16376747b715Smrg
16386747b715Smrg/*
16396747b715Smrg * SetPixmapOfAncestors
16406747b715Smrg *  Set the Pixmaps on all ParentRelative windows up the ancestor chain.
16416747b715Smrg */
16426747b715Smrgvoid
16436747b715SmrgRootlessSetPixmapOfAncestors(WindowPtr pWin)
16446747b715Smrg{
16456747b715Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
16466747b715Smrg    WindowPtr topWin = TopLevelParent(pWin);
16476747b715Smrg    RootlessWindowRec *topWinRec = WINREC(topWin);
16486747b715Smrg
16496747b715Smrg    while (pWin->backgroundState == ParentRelative) {
16506747b715Smrg        if (pWin == topWin) {
16516747b715Smrg            // disallow ParentRelative background state on top level
16526747b715Smrg            XID pixel = 0;
16536747b715Smrg            ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
16546747b715Smrg            RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin);
16556747b715Smrg            break;
16566747b715Smrg        }
16576747b715Smrg
16586747b715Smrg        pWin = pWin->parent;
16596747b715Smrg        pScreen->SetWindowPixmap(pWin, topWinRec->pixmap);
16606747b715Smrg    }
16616747b715Smrg}
16626747b715Smrg
1663