rootlessWindow.c revision 9ace9065
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#define SCREEN_TO_GLOBAL_X \
556747b715Smrg    (pScreen->x + rootlessGlobalOffsetX)
5605b261ecSmrg#define SCREEN_TO_GLOBAL_Y \
576747b715Smrg    (pScreen->y + rootlessGlobalOffsetY)
5805b261ecSmrg
594642e01fSmrg#define DEFINE_ATOM_HELPER(func,atom_name)                      \
604642e01fSmrg  static Atom func (void) {                                       \
614642e01fSmrg    static unsigned int generation = 0;                             \
624642e01fSmrg    static Atom atom;                                           \
634642e01fSmrg    if (generation != serverGeneration) {                       \
644642e01fSmrg      generation = serverGeneration;                          \
654642e01fSmrg      atom = MakeAtom (atom_name, strlen (atom_name), TRUE);  \
664642e01fSmrg    }                                                           \
674642e01fSmrg    return atom;                                                \
684642e01fSmrg  }
694642e01fSmrg
704642e01fSmrgDEFINE_ATOM_HELPER (xa_native_window_id, "_NATIVE_WINDOW_ID")
714642e01fSmrg
724642e01fSmrgstatic Bool windows_hidden;
734642e01fSmrg// TODO - abstract xp functions
744642e01fSmrg
756747b715Smrg#ifdef __APPLE__
764642e01fSmrg
776747b715Smrg// XXX: identical to x_cvt_vptr_to_uint ?
786747b715Smrg#define MAKE_WINDOW_ID(x)		((xp_window_id)((size_t)(x)))
794642e01fSmrg
804642e01fSmrgvoid
814642e01fSmrgRootlessNativeWindowStateChanged (WindowPtr pWin, unsigned int state)
824642e01fSmrg{
834642e01fSmrg  RootlessWindowRec *winRec;
844642e01fSmrg
854642e01fSmrg  if (pWin == NULL) return;
864642e01fSmrg
874642e01fSmrg  winRec = WINREC (pWin);
884642e01fSmrg  if (winRec == NULL) return;
894642e01fSmrg
904642e01fSmrg  winRec->is_offscreen = ((state & XP_WINDOW_STATE_OFFSCREEN) != 0);
914642e01fSmrg  winRec->is_obscured = ((state & XP_WINDOW_STATE_OBSCURED) != 0);
924642e01fSmrg  pWin->rootlessUnhittable = winRec->is_offscreen;
934642e01fSmrg}
944642e01fSmrg
954642e01fSmrgvoid RootlessNativeWindowMoved (WindowPtr pWin) {
964642e01fSmrg    xp_box bounds;
974642e01fSmrg    int sx, sy, err;
984642e01fSmrg    XID vlist[2];
994642e01fSmrg    Mask mask;
1004642e01fSmrg    ClientPtr pClient;
1014642e01fSmrg    RootlessWindowRec *winRec;
1024642e01fSmrg
1034642e01fSmrg    winRec = WINREC(pWin);
1044642e01fSmrg
1054642e01fSmrg    if (xp_get_window_bounds (MAKE_WINDOW_ID(winRec->wid), &bounds) != Success) return;
1064642e01fSmrg
1076747b715Smrg    sx = pWin->drawable.pScreen->x + darwinMainScreenX;
1086747b715Smrg    sy = pWin->drawable.pScreen->y + darwinMainScreenY;
1094642e01fSmrg
1104642e01fSmrg    /* Fake up a ConfigureWindow packet to resize the window to the current bounds. */
1114642e01fSmrg    vlist[0] = (INT16) bounds.x1 - sx;
1124642e01fSmrg    vlist[1] = (INT16) bounds.y1 - sy;
1134642e01fSmrg    mask = CWX | CWY;
1144642e01fSmrg
1154642e01fSmrg    /* pretend we're the owner of the window! */
1166747b715Smrg    err = dixLookupClient(&pClient, pWin->drawable.id, serverClient, DixUnknownAccess);
1174642e01fSmrg    if(err != Success) {
1184642e01fSmrg        ErrorF("RootlessNativeWindowMoved(): Failed to lookup window: 0x%x\n", (unsigned int)pWin->drawable.id);
1194642e01fSmrg        return;
1204642e01fSmrg    }
1214642e01fSmrg
1224642e01fSmrg    /* Don't want to do anything to the physical window (avoids
1234642e01fSmrg     notification-response feedback loops) */
1244642e01fSmrg
1254642e01fSmrg    no_configure_window = TRUE;
1264642e01fSmrg    ConfigureWindow (pWin, mask, vlist, pClient);
1274642e01fSmrg    no_configure_window = FALSE;
1284642e01fSmrg}
1294642e01fSmrg
1306747b715Smrg#endif /* __APPLE__ */
13105b261ecSmrg
13205b261ecSmrg/*
13305b261ecSmrg * RootlessCreateWindow
13405b261ecSmrg *  For now, don't create a physical window until either the window is
13505b261ecSmrg *  realized, or we really need it (e.g. to attach VRAM surfaces to).
13605b261ecSmrg *  Do reset the window size so it's not clipped by the root window.
13705b261ecSmrg */
13805b261ecSmrgBool
13905b261ecSmrgRootlessCreateWindow(WindowPtr pWin)
14005b261ecSmrg{
14105b261ecSmrg    Bool result;
14205b261ecSmrg    RegionRec saveRoot;
14305b261ecSmrg
1444642e01fSmrg    SETWINREC(pWin, NULL);
1454642e01fSmrg    dixSetPrivate(&pWin->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL);
14605b261ecSmrg
14705b261ecSmrg    SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow);
14805b261ecSmrg
14905b261ecSmrg    if (!IsRoot(pWin)) {
15005b261ecSmrg        /* win/border size set by DIX, not by wrapped CreateWindow, so
15105b261ecSmrg           correct it here. Don't HUGE_ROOT when pWin is the root! */
15205b261ecSmrg
15305b261ecSmrg        HUGE_ROOT(pWin);
15405b261ecSmrg        SetWinSize(pWin);
15505b261ecSmrg        SetBorderSize(pWin);
15605b261ecSmrg    }
15705b261ecSmrg
15805b261ecSmrg    result = pWin->drawable.pScreen->CreateWindow(pWin);
15905b261ecSmrg
16005b261ecSmrg    if (pWin->parent) {
16105b261ecSmrg        NORMAL_ROOT(pWin);
16205b261ecSmrg    }
16305b261ecSmrg
16405b261ecSmrg    SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow);
16505b261ecSmrg
16605b261ecSmrg    return result;
16705b261ecSmrg}
16805b261ecSmrg
16905b261ecSmrg
17005b261ecSmrg/*
17105b261ecSmrg * RootlessDestroyFrame
17205b261ecSmrg *  Destroy the physical window associated with the given window.
17305b261ecSmrg */
17405b261ecSmrgstatic void
17505b261ecSmrgRootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec)
17605b261ecSmrg{
1776747b715Smrg    SCREENREC(pWin->drawable.pScreen)->imp->DestroyFrame(winRec->wid);
1786747b715Smrg    free(winRec);
1794642e01fSmrg    SETWINREC(pWin, NULL);
18005b261ecSmrg}
18105b261ecSmrg
18205b261ecSmrg
18305b261ecSmrg/*
18405b261ecSmrg * RootlessDestroyWindow
18505b261ecSmrg *  Destroy the physical window associated with the given window.
18605b261ecSmrg */
18705b261ecSmrgBool
18805b261ecSmrgRootlessDestroyWindow(WindowPtr pWin)
18905b261ecSmrg{
19005b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
19105b261ecSmrg    Bool result;
19205b261ecSmrg
19305b261ecSmrg    if (winRec != NULL) {
19405b261ecSmrg        RootlessDestroyFrame(pWin, winRec);
19505b261ecSmrg    }
19605b261ecSmrg
19705b261ecSmrg    SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow);
19805b261ecSmrg    result = pWin->drawable.pScreen->DestroyWindow(pWin);
19905b261ecSmrg    SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow);
20005b261ecSmrg
20105b261ecSmrg    return result;
20205b261ecSmrg}
20305b261ecSmrg
20405b261ecSmrg
20505b261ecSmrg
20605b261ecSmrgstatic Bool
20705b261ecSmrgRootlessGetShape(WindowPtr pWin, RegionPtr pShape)
20805b261ecSmrg{
20905b261ecSmrg    if (wBoundingShape(pWin) == NULL)
21005b261ecSmrg        return FALSE;
21105b261ecSmrg
21205b261ecSmrg    /* wBoundingShape is relative to *inner* origin of window.
21305b261ecSmrg       Translate by borderWidth to get the outside-relative position. */
21405b261ecSmrg
2156747b715Smrg    RegionNull(pShape);
2166747b715Smrg    RegionCopy(pShape, wBoundingShape(pWin));
2176747b715Smrg    RegionTranslate(pShape, pWin->borderWidth, pWin->borderWidth);
21805b261ecSmrg
21905b261ecSmrg    return TRUE;
22005b261ecSmrg}
22105b261ecSmrg
22205b261ecSmrg
22305b261ecSmrg/*
22405b261ecSmrg * RootlessReshapeFrame
22505b261ecSmrg *  Set the frame shape.
22605b261ecSmrg */
22705b261ecSmrgstatic void RootlessReshapeFrame(WindowPtr pWin)
22805b261ecSmrg{
22905b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
23005b261ecSmrg    RegionRec newShape;
23105b261ecSmrg    RegionPtr pShape;
23205b261ecSmrg
23305b261ecSmrg    // If the window is not yet framed, do nothing
23405b261ecSmrg    if (winRec == NULL)
23505b261ecSmrg        return;
23605b261ecSmrg
23705b261ecSmrg    if (IsRoot(pWin))
23805b261ecSmrg        return;
23905b261ecSmrg
24005b261ecSmrg    RootlessStopDrawing(pWin, FALSE);
24105b261ecSmrg
24205b261ecSmrg    pShape = RootlessGetShape(pWin, &newShape) ? &newShape : NULL;
24305b261ecSmrg
24405b261ecSmrg#ifdef ROOTLESSDEBUG
24505b261ecSmrg    RL_DEBUG_MSG("reshaping...");
24605b261ecSmrg    if (pShape != NULL) {
24705b261ecSmrg        RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ",
2486747b715Smrg                     RegionNumRects(&newShape),
24905b261ecSmrg                     newShape.extents.x1, newShape.extents.y1,
25005b261ecSmrg                     newShape.extents.x2, newShape.extents.y2);
25105b261ecSmrg    } else {
25205b261ecSmrg        RL_DEBUG_MSG("no shape ");
25305b261ecSmrg    }
25405b261ecSmrg#endif
25505b261ecSmrg
2566747b715Smrg    SCREENREC(pWin->drawable.pScreen)->imp->ReshapeFrame(winRec->wid, pShape);
25705b261ecSmrg
25805b261ecSmrg    if (pShape != NULL)
2596747b715Smrg        RegionUninit(&newShape);
26005b261ecSmrg}
26105b261ecSmrg
26205b261ecSmrg
26305b261ecSmrg/*
26405b261ecSmrg * RootlessSetShape
26505b261ecSmrg *  Shape is usually set before a window is mapped and the window will
26605b261ecSmrg *  not have a frame associated with it. In this case, the frame will be
26705b261ecSmrg *  shaped when the window is framed.
26805b261ecSmrg */
26905b261ecSmrgvoid
2706747b715SmrgRootlessSetShape(WindowPtr pWin, int kind)
27105b261ecSmrg{
27205b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
27305b261ecSmrg
27405b261ecSmrg    SCREEN_UNWRAP(pScreen, SetShape);
2756747b715Smrg    pScreen->SetShape(pWin, kind);
27605b261ecSmrg    SCREEN_WRAP(pScreen, SetShape);
27705b261ecSmrg
27805b261ecSmrg    RootlessReshapeFrame(pWin);
27905b261ecSmrg}
28005b261ecSmrg
28105b261ecSmrg
28205b261ecSmrg
28305b261ecSmrg/* Disallow ParentRelative background on top-level windows
2844642e01fSmrg   because the root window doesn't really have the right background.
2854642e01fSmrg */
28605b261ecSmrgBool
28705b261ecSmrgRootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask)
28805b261ecSmrg{
28905b261ecSmrg    Bool result;
29005b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
29105b261ecSmrg
29205b261ecSmrg    RL_DEBUG_MSG("change window attributes start ");
29305b261ecSmrg
29405b261ecSmrg    SCREEN_UNWRAP(pScreen, ChangeWindowAttributes);
29505b261ecSmrg    result = pScreen->ChangeWindowAttributes(pWin, vmask);
29605b261ecSmrg    SCREEN_WRAP(pScreen, ChangeWindowAttributes);
29705b261ecSmrg
29805b261ecSmrg    if (WINREC(pWin)) {
29905b261ecSmrg        // disallow ParentRelative background state
30005b261ecSmrg        if (pWin->backgroundState == ParentRelative) {
30105b261ecSmrg            XID pixel = 0;
30205b261ecSmrg            ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
30305b261ecSmrg        }
30405b261ecSmrg    }
30505b261ecSmrg
30605b261ecSmrg    RL_DEBUG_MSG("change window attributes end\n");
30705b261ecSmrg    return result;
30805b261ecSmrg}
30905b261ecSmrg
31005b261ecSmrg
31105b261ecSmrg/*
31205b261ecSmrg * RootlessPositionWindow
31305b261ecSmrg *  This is a hook for when DIX moves or resizes a window.
31405b261ecSmrg *  Update the frame position now although the physical window is moved
31505b261ecSmrg *  in RootlessMoveWindow. (x, y) are *inside* position. After this,
31605b261ecSmrg *  mi and fb are expecting the pixmap to be at the new location.
31705b261ecSmrg */
31805b261ecSmrgBool
31905b261ecSmrgRootlessPositionWindow(WindowPtr pWin, int x, int y)
32005b261ecSmrg{
32105b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
32205b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
32305b261ecSmrg    Bool result;
32405b261ecSmrg
32505b261ecSmrg    RL_DEBUG_MSG("positionwindow start (win 0x%x @ %i, %i)\n", pWin, x, y);
32605b261ecSmrg
32705b261ecSmrg    if (winRec) {
32805b261ecSmrg        if (winRec->is_drawing) {
32905b261ecSmrg            // Reset frame's pixmap and move it to the new position.
33005b261ecSmrg            int bw = wBorderWidth(pWin);
33105b261ecSmrg
33205b261ecSmrg            winRec->pixmap->devPrivate.ptr = winRec->pixelData;
33305b261ecSmrg            SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw);
33405b261ecSmrg        }
33505b261ecSmrg    }
33605b261ecSmrg
33705b261ecSmrg    SCREEN_UNWRAP(pScreen, PositionWindow);
33805b261ecSmrg    result = pScreen->PositionWindow(pWin, x, y);
33905b261ecSmrg    SCREEN_WRAP(pScreen, PositionWindow);
34005b261ecSmrg
34105b261ecSmrg    RL_DEBUG_MSG("positionwindow end\n");
34205b261ecSmrg    return result;
34305b261ecSmrg}
34405b261ecSmrg
34505b261ecSmrg
34605b261ecSmrg/*
34705b261ecSmrg * RootlessInitializeFrame
34805b261ecSmrg *  Initialize some basic attributes of the frame. Note that winRec
34905b261ecSmrg *  may already have valid data in it, so don't overwrite anything
35005b261ecSmrg *  valuable.
35105b261ecSmrg */
35205b261ecSmrgstatic void
35305b261ecSmrgRootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec *winRec)
35405b261ecSmrg{
35505b261ecSmrg    DrawablePtr d = &pWin->drawable;
35605b261ecSmrg    int bw = wBorderWidth(pWin);
35705b261ecSmrg
35805b261ecSmrg    winRec->win = pWin;
35905b261ecSmrg
36005b261ecSmrg    winRec->x = d->x - bw;
36105b261ecSmrg    winRec->y = d->y - bw;
36205b261ecSmrg    winRec->width = d->width + 2*bw;
36305b261ecSmrg    winRec->height = d->height + 2*bw;
36405b261ecSmrg    winRec->borderWidth = bw;
36505b261ecSmrg}
36605b261ecSmrg
36705b261ecSmrg/*
36805b261ecSmrg * RootlessEnsureFrame
36905b261ecSmrg *  Make sure the given window is framed. If the window doesn't have a
37005b261ecSmrg *  physical window associated with it, attempt to create one. If that
37105b261ecSmrg *  is unsuccessful, return NULL.
37205b261ecSmrg */
37305b261ecSmrgstatic RootlessWindowRec *
37405b261ecSmrgRootlessEnsureFrame(WindowPtr pWin)
37505b261ecSmrg{
37605b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
37705b261ecSmrg    RootlessWindowRec *winRec;
37805b261ecSmrg    RegionRec shape;
37905b261ecSmrg    RegionPtr pShape = NULL;
38005b261ecSmrg
38105b261ecSmrg    if (WINREC(pWin) != NULL)
38205b261ecSmrg        return WINREC(pWin);
38305b261ecSmrg
3844642e01fSmrg    if (!IsTopLevel(pWin) && !IsRoot(pWin))
38505b261ecSmrg        return NULL;
38605b261ecSmrg
38705b261ecSmrg    if (pWin->drawable.class != InputOutput)
38805b261ecSmrg        return NULL;
38905b261ecSmrg
3906747b715Smrg    winRec = malloc(sizeof(RootlessWindowRec));
39105b261ecSmrg
39205b261ecSmrg    if (!winRec)
39305b261ecSmrg        return NULL;
39405b261ecSmrg
39505b261ecSmrg    RootlessInitializeFrame(pWin, winRec);
39605b261ecSmrg
39705b261ecSmrg    winRec->is_drawing = FALSE;
39805b261ecSmrg    winRec->is_reorder_pending = FALSE;
39905b261ecSmrg    winRec->pixmap = NULL;
40005b261ecSmrg    winRec->wid = NULL;
4016747b715Smrg    winRec->level = 0;
40205b261ecSmrg
4034642e01fSmrg    SETWINREC(pWin, winRec);
40405b261ecSmrg
40505b261ecSmrg    // Set the frame's shape if the window is shaped
40605b261ecSmrg    if (RootlessGetShape(pWin, &shape))
40705b261ecSmrg        pShape = &shape;
40805b261ecSmrg
40905b261ecSmrg    RL_DEBUG_MSG("creating frame ");
41005b261ecSmrg
41105b261ecSmrg    if (!SCREENREC(pScreen)->imp->CreateFrame(winRec, pScreen,
41205b261ecSmrg                                              winRec->x + SCREEN_TO_GLOBAL_X,
41305b261ecSmrg                                              winRec->y + SCREEN_TO_GLOBAL_Y,
41405b261ecSmrg                                              pShape))
41505b261ecSmrg    {
41605b261ecSmrg        RL_DEBUG_MSG("implementation failed to create frame!\n");
4176747b715Smrg        free(winRec);
4184642e01fSmrg        SETWINREC(pWin, NULL);
41905b261ecSmrg        return NULL;
42005b261ecSmrg    }
42105b261ecSmrg
4224642e01fSmrg    if (pWin->drawable.depth == 8)
4234642e01fSmrg      RootlessFlushWindowColormap(pWin);
4244642e01fSmrg
42505b261ecSmrg    if (pShape != NULL)
4266747b715Smrg        RegionUninit(&shape);
42705b261ecSmrg
42805b261ecSmrg    return winRec;
42905b261ecSmrg}
43005b261ecSmrg
43105b261ecSmrg
43205b261ecSmrg/*
43305b261ecSmrg * RootlessRealizeWindow
43405b261ecSmrg *  The frame is usually created here and not in CreateWindow so that
43505b261ecSmrg *  windows do not eat memory until they are realized.
43605b261ecSmrg */
43705b261ecSmrgBool
43805b261ecSmrgRootlessRealizeWindow(WindowPtr pWin)
43905b261ecSmrg{
44005b261ecSmrg    Bool result;
44105b261ecSmrg    RegionRec saveRoot;
44205b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
44305b261ecSmrg
44405b261ecSmrg    RL_DEBUG_MSG("realizewindow start (win 0x%x) ", pWin);
44505b261ecSmrg
44605b261ecSmrg    if ((IsTopLevel(pWin) && pWin->drawable.class == InputOutput)) {
44705b261ecSmrg        RootlessWindowRec *winRec;
44805b261ecSmrg
44905b261ecSmrg        winRec = RootlessEnsureFrame(pWin);
45005b261ecSmrg        if (winRec == NULL)
45105b261ecSmrg            return FALSE;
45205b261ecSmrg
45305b261ecSmrg        winRec->is_reorder_pending = TRUE;
45405b261ecSmrg
45505b261ecSmrg        RL_DEBUG_MSG("Top level window ");
45605b261ecSmrg
45705b261ecSmrg        // Disallow ParentRelative background state on top-level windows.
45805b261ecSmrg        // This might have been set before the window was mapped.
45905b261ecSmrg        if (pWin->backgroundState == ParentRelative) {
46005b261ecSmrg            XID pixel = 0;
46105b261ecSmrg            ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
46205b261ecSmrg        }
46305b261ecSmrg    }
46405b261ecSmrg
46505b261ecSmrg    if (!IsRoot(pWin)) HUGE_ROOT(pWin);
46605b261ecSmrg    SCREEN_UNWRAP(pScreen, RealizeWindow);
46705b261ecSmrg    result = pScreen->RealizeWindow(pWin);
46805b261ecSmrg    SCREEN_WRAP(pScreen, RealizeWindow);
46905b261ecSmrg    if (!IsRoot(pWin)) NORMAL_ROOT(pWin);
47005b261ecSmrg
47105b261ecSmrg    RL_DEBUG_MSG("realizewindow end\n");
47205b261ecSmrg    return result;
47305b261ecSmrg}
47405b261ecSmrg
47505b261ecSmrg
47605b261ecSmrg/*
47705b261ecSmrg * RootlessFrameForWindow
47805b261ecSmrg *  Returns the frame ID for the physical window displaying the given window.
47905b261ecSmrg *  If CREATE is true and the window has no frame, attempt to create one.
48005b261ecSmrg */
48105b261ecSmrgRootlessFrameID
48205b261ecSmrgRootlessFrameForWindow(WindowPtr pWin, Bool create)
48305b261ecSmrg{
48405b261ecSmrg    WindowPtr pTopWin;
48505b261ecSmrg    RootlessWindowRec *winRec;
48605b261ecSmrg
48705b261ecSmrg    pTopWin = TopLevelParent(pWin);
48805b261ecSmrg    if (pTopWin == NULL)
48905b261ecSmrg        return NULL;
49005b261ecSmrg
49105b261ecSmrg    winRec = WINREC(pTopWin);
49205b261ecSmrg
49305b261ecSmrg    if (winRec == NULL && create && pWin->drawable.class == InputOutput) {
49405b261ecSmrg        winRec = RootlessEnsureFrame(pTopWin);
49505b261ecSmrg    }
49605b261ecSmrg
49705b261ecSmrg    if (winRec == NULL)
49805b261ecSmrg        return NULL;
49905b261ecSmrg
50005b261ecSmrg    return winRec->wid;
50105b261ecSmrg}
50205b261ecSmrg
50305b261ecSmrg
50405b261ecSmrg/*
50505b261ecSmrg * RootlessUnrealizeWindow
50605b261ecSmrg *  Unmap the physical window.
50705b261ecSmrg */
50805b261ecSmrgBool
50905b261ecSmrgRootlessUnrealizeWindow(WindowPtr pWin)
51005b261ecSmrg{
51105b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
51205b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
51305b261ecSmrg    Bool result;
51405b261ecSmrg
51505b261ecSmrg    RL_DEBUG_MSG("unrealizewindow start ");
51605b261ecSmrg
51705b261ecSmrg    if (winRec) {
51805b261ecSmrg        RootlessStopDrawing(pWin, FALSE);
51905b261ecSmrg
52005b261ecSmrg        SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid);
52105b261ecSmrg
52205b261ecSmrg        winRec->is_reorder_pending = FALSE;
52305b261ecSmrg    }
52405b261ecSmrg
52505b261ecSmrg    SCREEN_UNWRAP(pScreen, UnrealizeWindow);
52605b261ecSmrg    result = pScreen->UnrealizeWindow(pWin);
52705b261ecSmrg    SCREEN_WRAP(pScreen, UnrealizeWindow);
52805b261ecSmrg
52905b261ecSmrg    RL_DEBUG_MSG("unrealizewindow end\n");
53005b261ecSmrg    return result;
53105b261ecSmrg}
53205b261ecSmrg
53305b261ecSmrg
53405b261ecSmrg/*
53505b261ecSmrg * RootlessReorderWindow
53605b261ecSmrg *  Reorder the frame associated with the given window so that it's
53705b261ecSmrg *  physically above the window below it in the X stacking order.
53805b261ecSmrg */
53905b261ecSmrgvoid
54005b261ecSmrgRootlessReorderWindow(WindowPtr pWin)
54105b261ecSmrg{
54205b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
54305b261ecSmrg
5444642e01fSmrg    if (pWin->realized && winRec != NULL && !winRec->is_reorder_pending && !windows_hidden) {
54505b261ecSmrg        WindowPtr newPrevW;
54605b261ecSmrg        RootlessWindowRec *newPrev;
54705b261ecSmrg        RootlessFrameID newPrevID;
54805b261ecSmrg        ScreenPtr pScreen = pWin->drawable.pScreen;
54905b261ecSmrg
55005b261ecSmrg        /* Check if the implementation wants the frame to not be reordered
55105b261ecSmrg           even though the X11 window is restacked. This can be useful if
55205b261ecSmrg           frames are ordered-in with animation so that the reordering is not
55305b261ecSmrg           done until the animation is complete. */
55405b261ecSmrg        if (SCREENREC(pScreen)->imp->DoReorderWindow) {
55505b261ecSmrg            if (!SCREENREC(pScreen)->imp->DoReorderWindow(winRec))
55605b261ecSmrg                return;
55705b261ecSmrg        }
55805b261ecSmrg
55905b261ecSmrg        RootlessStopDrawing(pWin, FALSE);
56005b261ecSmrg
5616747b715Smrg        /* Find the next window above this one that has a mapped frame.
5626747b715Smrg         * Only include cases where the windows are in the same category of
5636747b715Smrg         * hittability to ensure offscreen windows dont get restacked
5646747b715Smrg         * relative to onscreen ones (but that the offscreen ones maintain
5656747b715Smrg         * their stacking order if they are explicitly asked to Reorder
5666747b715Smrg         */
56705b261ecSmrg
56805b261ecSmrg        newPrevW = pWin->prevSib;
5696747b715Smrg        while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized || newPrevW->rootlessUnhittable != pWin->rootlessUnhittable))
57005b261ecSmrg            newPrevW = newPrevW->prevSib;
57105b261ecSmrg
57205b261ecSmrg        newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL;
57305b261ecSmrg        newPrevID = newPrev != NULL ? newPrev->wid : 0;
57405b261ecSmrg
57505b261ecSmrg        /* If it exists, reorder the frame above us first. */
57605b261ecSmrg
57705b261ecSmrg        if (newPrev && newPrev->is_reorder_pending) {
57805b261ecSmrg            newPrev->is_reorder_pending = FALSE;
57905b261ecSmrg            RootlessReorderWindow(newPrevW);
58005b261ecSmrg        }
58105b261ecSmrg
58205b261ecSmrg        SCREENREC(pScreen)->imp->RestackFrame(winRec->wid, newPrevID);
58305b261ecSmrg    }
58405b261ecSmrg}
58505b261ecSmrg
58605b261ecSmrg
58705b261ecSmrg/*
58805b261ecSmrg * RootlessRestackWindow
58905b261ecSmrg *  This is a hook for when DIX changes the window stacking order.
59005b261ecSmrg *  The window has already been inserted into its new position in the
59105b261ecSmrg *  DIX window stack. We need to change the order of the physical
59205b261ecSmrg *  window to match.
59305b261ecSmrg */
59405b261ecSmrgvoid
59505b261ecSmrgRootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib)
59605b261ecSmrg{
59705b261ecSmrg    RegionRec saveRoot;
59805b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
59905b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
60005b261ecSmrg
60105b261ecSmrg    RL_DEBUG_MSG("restackwindow start ");
60205b261ecSmrg    if (winRec)
60305b261ecSmrg        RL_DEBUG_MSG("restack top level \n");
60405b261ecSmrg
60505b261ecSmrg    HUGE_ROOT(pWin);
60605b261ecSmrg    SCREEN_UNWRAP(pScreen, RestackWindow);
60705b261ecSmrg
60805b261ecSmrg    if (pScreen->RestackWindow)
60905b261ecSmrg        pScreen->RestackWindow(pWin, pOldNextSib);
61005b261ecSmrg
61105b261ecSmrg    SCREEN_WRAP(pScreen, RestackWindow);
61205b261ecSmrg    NORMAL_ROOT(pWin);
61305b261ecSmrg
61405b261ecSmrg    if (winRec && pWin->viewable) {
61505b261ecSmrg        RootlessReorderWindow(pWin);
61605b261ecSmrg    }
61705b261ecSmrg
61805b261ecSmrg    RL_DEBUG_MSG("restackwindow end\n");
61905b261ecSmrg}
62005b261ecSmrg
62105b261ecSmrg/*
62205b261ecSmrg * Specialized window copy procedures
62305b261ecSmrg */
62405b261ecSmrg
62505b261ecSmrg// Globals needed during window resize and move.
62605b261ecSmrgstatic pointer gResizeDeathBits = NULL;
62705b261ecSmrgstatic int gResizeDeathCount = 0;
62805b261ecSmrgstatic PixmapPtr gResizeDeathPix[2] = {NULL, NULL};
62905b261ecSmrgstatic BoxRec gResizeDeathBounds[2];
63005b261ecSmrgstatic CopyWindowProcPtr gResizeOldCopyWindowProc = NULL;
63105b261ecSmrg
63205b261ecSmrg/*
63305b261ecSmrg * RootlessNoCopyWindow
63405b261ecSmrg *  CopyWindow() that doesn't do anything. For MoveWindow() of
63505b261ecSmrg *  top-level windows.
63605b261ecSmrg */
63705b261ecSmrgstatic void
63805b261ecSmrgRootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
63905b261ecSmrg                     RegionPtr prgnSrc)
64005b261ecSmrg{
64105b261ecSmrg    // some code expects the region to be translated
64205b261ecSmrg    int dx = ptOldOrg.x - pWin->drawable.x;
64305b261ecSmrg    int dy = ptOldOrg.y - pWin->drawable.y;
64405b261ecSmrg
64505b261ecSmrg    RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW ");
64605b261ecSmrg
6476747b715Smrg    RegionTranslate(prgnSrc, -dx, -dy);
64805b261ecSmrg}
64905b261ecSmrg
65005b261ecSmrg
65105b261ecSmrg/*
65205b261ecSmrg * RootlessResizeCopyWindow
65305b261ecSmrg *  CopyWindow used during ResizeWindow for gravity moves. Based on
65405b261ecSmrg *  fbCopyWindow. The original always draws on the root pixmap, which
65505b261ecSmrg *  we don't have. Instead, draw on the parent window's pixmap.
65605b261ecSmrg *  Resize version: the old location's pixels are in gResizeCopyWindowSource.
65705b261ecSmrg */
65805b261ecSmrgstatic void
65905b261ecSmrgRootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
66005b261ecSmrg                         RegionPtr prgnSrc)
66105b261ecSmrg{
66205b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
66305b261ecSmrg    RegionRec   rgnDst;
66405b261ecSmrg    int         dx, dy;
66505b261ecSmrg
66605b261ecSmrg    RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin);
66705b261ecSmrg
66805b261ecSmrg    /* Don't unwrap pScreen->CopyWindow.
66905b261ecSmrg       The bogus rewrap with RootlessCopyWindow causes a crash if
67005b261ecSmrg       CopyWindow is called again during the same resize. */
67105b261ecSmrg
67205b261ecSmrg    if (gResizeDeathCount == 0)
67305b261ecSmrg        return;
67405b261ecSmrg
67505b261ecSmrg    RootlessStartDrawing(pWin);
67605b261ecSmrg
67705b261ecSmrg    dx = ptOldOrg.x - pWin->drawable.x;
67805b261ecSmrg    dy = ptOldOrg.y - pWin->drawable.y;
6796747b715Smrg    RegionTranslate(prgnSrc, -dx, -dy);
6806747b715Smrg    RegionNull(&rgnDst);
6816747b715Smrg    RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
68205b261ecSmrg
68305b261ecSmrg    if (gResizeDeathCount == 1) {
68405b261ecSmrg        /* Simple case, we only have a single source pixmap. */
68505b261ecSmrg
68605b261ecSmrg        fbCopyRegion(&gResizeDeathPix[0]->drawable,
68705b261ecSmrg                     &pScreen->GetWindowPixmap(pWin)->drawable, 0,
68805b261ecSmrg                     &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
68905b261ecSmrg    }
69005b261ecSmrg    else {
69105b261ecSmrg        int i;
69205b261ecSmrg        RegionRec clip, clipped;
69305b261ecSmrg
69405b261ecSmrg        /* More complex case, N source pixmaps (usually two). So we
69505b261ecSmrg           intersect the destination with each source and copy those bits. */
69605b261ecSmrg
69705b261ecSmrg        for (i = 0; i < gResizeDeathCount; i++) {
6986747b715Smrg            RegionInit(&clip, gResizeDeathBounds + 0, 1);
6996747b715Smrg            RegionNull(&clipped);
7006747b715Smrg            RegionIntersect(&rgnDst, &clip, &clipped);
70105b261ecSmrg
70205b261ecSmrg            fbCopyRegion(&gResizeDeathPix[i]->drawable,
70305b261ecSmrg                         &pScreen->GetWindowPixmap(pWin)->drawable, 0,
70405b261ecSmrg                         &clipped, dx, dy, fbCopyWindowProc, 0, 0);
70505b261ecSmrg
7066747b715Smrg            RegionUninit(&clipped);
7076747b715Smrg            RegionUninit(&clip);
70805b261ecSmrg        }
70905b261ecSmrg    }
71005b261ecSmrg
71105b261ecSmrg    /* Don't update - resize will update everything */
7126747b715Smrg    RegionUninit(&rgnDst);
71305b261ecSmrg
71405b261ecSmrg    fbValidateDrawable(&pWin->drawable);
71505b261ecSmrg
71605b261ecSmrg    RL_DEBUG_MSG("resizecopywindowFB end\n");
71705b261ecSmrg}
71805b261ecSmrg
71905b261ecSmrg
72005b261ecSmrg/*
72105b261ecSmrg * RootlessCopyWindow
72205b261ecSmrg *  Update *new* location of window. Old location is redrawn with
7234642e01fSmrg *  miPaintWindow. Cloned from fbCopyWindow.
72405b261ecSmrg *  The original always draws on the root pixmap, which we don't have.
72505b261ecSmrg *  Instead, draw on the parent window's pixmap.
72605b261ecSmrg */
72705b261ecSmrgvoid
72805b261ecSmrgRootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
72905b261ecSmrg{
73005b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
73105b261ecSmrg    RegionRec   rgnDst;
73205b261ecSmrg    int         dx, dy;
73305b261ecSmrg    BoxPtr extents;
73405b261ecSmrg    int area;
73505b261ecSmrg
73605b261ecSmrg    RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin);
73705b261ecSmrg
73805b261ecSmrg    SCREEN_UNWRAP(pScreen, CopyWindow);
73905b261ecSmrg
74005b261ecSmrg    dx = ptOldOrg.x - pWin->drawable.x;
74105b261ecSmrg    dy = ptOldOrg.y - pWin->drawable.y;
7426747b715Smrg    RegionTranslate(prgnSrc, -dx, -dy);
74305b261ecSmrg
7446747b715Smrg    RegionNull(&rgnDst);
7456747b715Smrg    RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
74605b261ecSmrg
7476747b715Smrg    extents = RegionExtents(&rgnDst);
74805b261ecSmrg    area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1);
74905b261ecSmrg
75005b261ecSmrg    /* If the area exceeds threshold, use the implementation's
75105b261ecSmrg       accelerated version. */
75205b261ecSmrg    if (area > rootless_CopyWindow_threshold &&
75305b261ecSmrg        SCREENREC(pScreen)->imp->CopyWindow)
75405b261ecSmrg    {
75505b261ecSmrg        RootlessWindowRec *winRec;
75605b261ecSmrg        WindowPtr top;
75705b261ecSmrg
75805b261ecSmrg        top = TopLevelParent(pWin);
75905b261ecSmrg        if (top == NULL) {
76005b261ecSmrg            RL_DEBUG_MSG("no parent\n");
7614642e01fSmrg            goto out;
76205b261ecSmrg        }
76305b261ecSmrg
76405b261ecSmrg        winRec = WINREC(top);
76505b261ecSmrg        if (winRec == NULL) {
76605b261ecSmrg            RL_DEBUG_MSG("not framed\n");
7674642e01fSmrg            goto out;
76805b261ecSmrg        }
76905b261ecSmrg
77005b261ecSmrg        /* Move region to window local coords */
7716747b715Smrg        RegionTranslate(&rgnDst, -winRec->x, -winRec->y);
77205b261ecSmrg
77305b261ecSmrg        RootlessStopDrawing(pWin, FALSE);
77405b261ecSmrg
77505b261ecSmrg        SCREENREC(pScreen)->imp->CopyWindow(winRec->wid,
7766747b715Smrg                                            RegionNumRects(&rgnDst),
7776747b715Smrg                                            RegionRects(&rgnDst),
77805b261ecSmrg                                            dx, dy);
77905b261ecSmrg    }
78005b261ecSmrg    else {
78105b261ecSmrg        RootlessStartDrawing(pWin);
78205b261ecSmrg
78305b261ecSmrg        fbCopyRegion((DrawablePtr) pWin, (DrawablePtr) pWin,
78405b261ecSmrg                     0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
78505b261ecSmrg
78605b261ecSmrg        /* prgnSrc has been translated to dst position */
78705b261ecSmrg        RootlessDamageRegion(pWin, prgnSrc);
78805b261ecSmrg    }
78905b261ecSmrg
7904642e01fSmrgout:
7916747b715Smrg    RegionUninit(&rgnDst);
79205b261ecSmrg    fbValidateDrawable(&pWin->drawable);
79305b261ecSmrg
79405b261ecSmrg    SCREEN_WRAP(pScreen, CopyWindow);
79505b261ecSmrg
79605b261ecSmrg    RL_DEBUG_MSG("copywindowFB end\n");
79705b261ecSmrg}
79805b261ecSmrg
79905b261ecSmrg
80005b261ecSmrg/*
80105b261ecSmrg * Window resize procedures
80205b261ecSmrg */
80305b261ecSmrg
80405b261ecSmrgenum {
80505b261ecSmrg    WIDTH_SMALLER = 1,
80605b261ecSmrg    HEIGHT_SMALLER = 2,
80705b261ecSmrg};
80805b261ecSmrg
80905b261ecSmrg
81005b261ecSmrg/*
81105b261ecSmrg * ResizeWeighting
81205b261ecSmrg *  Choose gravity to avoid local copies. Do that by looking for
81305b261ecSmrg *  a corner that doesn't move _relative to the screen_.
81405b261ecSmrg */
81505b261ecSmrgstatic inline unsigned int
81605b261ecSmrgResizeWeighting(int oldX1, int oldY1, int oldX2, int oldY2, int oldBW,
81705b261ecSmrg                int newX1, int newY1, int newX2, int newY2, int newBW)
81805b261ecSmrg{
81905b261ecSmrg#ifdef ROOTLESS_RESIZE_GRAVITY
82005b261ecSmrg    if (newBW != oldBW)
82105b261ecSmrg        return RL_GRAVITY_NONE;
82205b261ecSmrg
82305b261ecSmrg    if (newX1 == oldX1 && newY1 == oldY1)
82405b261ecSmrg        return RL_GRAVITY_NORTH_WEST;
82505b261ecSmrg    else if (newX1 == oldX1 && newY2 == oldY2)
82605b261ecSmrg        return RL_GRAVITY_SOUTH_WEST;
82705b261ecSmrg    else if (newX2 == oldX2 && newY2 == oldY2)
82805b261ecSmrg        return RL_GRAVITY_SOUTH_EAST;
82905b261ecSmrg    else if (newX2 == oldX2 && newY1 == oldY1)
83005b261ecSmrg        return RL_GRAVITY_NORTH_EAST;
83105b261ecSmrg    else
83205b261ecSmrg        return RL_GRAVITY_NONE;
83305b261ecSmrg#else
83405b261ecSmrg    return RL_GRAVITY_NONE;
83505b261ecSmrg#endif
83605b261ecSmrg}
83705b261ecSmrg
83805b261ecSmrg
83905b261ecSmrg/*
84005b261ecSmrg * StartFrameResize
84105b261ecSmrg *  Prepare to resize a top-level window. The old window's pixels are
84205b261ecSmrg *  saved and the implementation is told to change the window size.
84305b261ecSmrg *  (x,y,w,h) is outer frame of window (outside border)
84405b261ecSmrg */
84505b261ecSmrgstatic Bool
84605b261ecSmrgStartFrameResize(WindowPtr pWin, Bool gravity,
84705b261ecSmrg                 int oldX, int oldY, int oldW, int oldH, int oldBW,
84805b261ecSmrg                 int newX, int newY, int newW, int newH, int newBW)
84905b261ecSmrg{
85005b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
85105b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
85205b261ecSmrg    Bool need_window_source = FALSE, resize_after = FALSE;
85305b261ecSmrg
85405b261ecSmrg    BoxRec rect;
85505b261ecSmrg    int oldX2, newX2;
85605b261ecSmrg    int oldY2, newY2;
85705b261ecSmrg    unsigned int weight;
85805b261ecSmrg
85905b261ecSmrg    oldX2 = oldX + oldW, newX2 = newX + newW;
86005b261ecSmrg    oldY2 = oldY + oldH, newY2 = newY + newH;
86105b261ecSmrg
86205b261ecSmrg    /* Decide which resize weighting to use */
86305b261ecSmrg    weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW,
86405b261ecSmrg                             newX, newY, newW, newH, newBW);
86505b261ecSmrg
86605b261ecSmrg    /* Compute intersection between old and new rects */
86705b261ecSmrg    rect.x1 = max(oldX, newX);
86805b261ecSmrg    rect.y1 = max(oldY, newY);
86905b261ecSmrg    rect.x2 = min(oldX2, newX2);
87005b261ecSmrg    rect.y2 = min(oldY2, newY2);
87105b261ecSmrg
87205b261ecSmrg    RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity);
87305b261ecSmrg    RL_DEBUG_MSG("%d %d %d %d %d   %d %d %d %d %d\n",
87405b261ecSmrg                 oldX, oldY, oldW, oldH, oldBW,
87505b261ecSmrg                 newX, newY, newW, newH, newBW);
87605b261ecSmrg
87705b261ecSmrg    RootlessRedisplay(pWin);
87805b261ecSmrg
87905b261ecSmrg    /* If gravity is true, then we need to have a way of recovering all
88005b261ecSmrg       the original bits in the window for when X rearranges the contents
88105b261ecSmrg       based on the various gravity settings. The obvious way is to just
88205b261ecSmrg       snapshot the entire backing store before resizing it, but that
88305b261ecSmrg       it slow on large windows.
88405b261ecSmrg
88505b261ecSmrg       So the optimization here is to use the implementation's resize
88605b261ecSmrg       weighting options (if available) to allow us to reason about what
88705b261ecSmrg       is left in the backing store after the resize. We can then only
88805b261ecSmrg       copy what won't be there after the resize, and do a two-stage copy
88905b261ecSmrg       operation.
89005b261ecSmrg
89105b261ecSmrg       Most of these optimizations are only applied when the top-left
89205b261ecSmrg       corner of the window is fixed, since that's the common case. They
89305b261ecSmrg       could probably be extended with some thought. */
89405b261ecSmrg
89505b261ecSmrg    gResizeDeathCount = 0;
89605b261ecSmrg
89705b261ecSmrg    if (gravity && weight == RL_GRAVITY_NORTH_WEST) {
89805b261ecSmrg        unsigned int code = 0;
89905b261ecSmrg
90005b261ecSmrg        /* Top left corner is anchored. We never need to copy the
90105b261ecSmrg           entire window. */
90205b261ecSmrg
90305b261ecSmrg        need_window_source = TRUE;
90405b261ecSmrg
90505b261ecSmrg        /* These comparisons were chosen to avoid setting bits when the sizes
90605b261ecSmrg        are the same. (So the fastest case automatically gets taken when
90705b261ecSmrg        dimensions are unchanging.) */
90805b261ecSmrg
90905b261ecSmrg        if (newW < oldW)
91005b261ecSmrg            code |= WIDTH_SMALLER;
91105b261ecSmrg        if (newH < oldH)
91205b261ecSmrg            code |= HEIGHT_SMALLER;
91305b261ecSmrg
91405b261ecSmrg        if (((code ^ (code >> 1)) & 1) == 0) {
91505b261ecSmrg            /* Both dimensions are either getting larger, or both
91605b261ecSmrg               are getting smaller. No need to copy anything. */
91705b261ecSmrg
91805b261ecSmrg            if (code == (WIDTH_SMALLER | HEIGHT_SMALLER)) {
91905b261ecSmrg                /* Since the window is getting smaller, we can do gravity
92005b261ecSmrg                   repair on it with it's current size, then resize it
92105b261ecSmrg                   afterwards. */
92205b261ecSmrg
92305b261ecSmrg                resize_after = TRUE;
92405b261ecSmrg            }
92505b261ecSmrg
92605b261ecSmrg            gResizeDeathCount = 1;
92705b261ecSmrg        }
92805b261ecSmrg        else {
92905b261ecSmrg            unsigned int copy_rowbytes, Bpp;
93005b261ecSmrg            unsigned int copy_rect_width, copy_rect_height;
93105b261ecSmrg            BoxRec copy_rect;
93205b261ecSmrg
93305b261ecSmrg            /* We can get away with a partial copy. 'rect' is the
93405b261ecSmrg               intersection between old and new bounds, so copy
93505b261ecSmrg               everything to the right of or below the intersection. */
93605b261ecSmrg
93705b261ecSmrg            RootlessStartDrawing(pWin);
93805b261ecSmrg
93905b261ecSmrg            if (code == WIDTH_SMALLER) {
94005b261ecSmrg                copy_rect.x1 = rect.x2;
94105b261ecSmrg                copy_rect.y1 = rect.y1;
94205b261ecSmrg                copy_rect.x2 = oldX2;
94305b261ecSmrg                copy_rect.y2 = oldY2;
94405b261ecSmrg            }
94505b261ecSmrg            else if (code == HEIGHT_SMALLER) {
94605b261ecSmrg                copy_rect.x1 = rect.x1;
94705b261ecSmrg                copy_rect.y1 = rect.y2;
94805b261ecSmrg                copy_rect.x2 = oldX2;
94905b261ecSmrg                copy_rect.y2 = oldY2;
95005b261ecSmrg            }
95105b261ecSmrg            else
9526747b715Smrg                OsAbort();
95305b261ecSmrg
95405b261ecSmrg            Bpp = winRec->win->drawable.bitsPerPixel / 8;
95505b261ecSmrg            copy_rect_width = copy_rect.x2 - copy_rect.x1;
95605b261ecSmrg            copy_rect_height = copy_rect.y2 - copy_rect.y1;
95705b261ecSmrg            copy_rowbytes = ((copy_rect_width * Bpp) + 31) & ~31;
9586747b715Smrg            gResizeDeathBits = malloc(copy_rowbytes
95905b261ecSmrg                                      * copy_rect_height);
96005b261ecSmrg
96105b261ecSmrg            if (copy_rect_width * copy_rect_height >
96205b261ecSmrg                        rootless_CopyBytes_threshold &&
96305b261ecSmrg                SCREENREC(pScreen)->imp->CopyBytes)
96405b261ecSmrg            {
96505b261ecSmrg                SCREENREC(pScreen)->imp->CopyBytes(
96605b261ecSmrg                    copy_rect_width * Bpp, copy_rect_height,
96705b261ecSmrg                    ((char *) winRec->pixelData)
96805b261ecSmrg                    + ((copy_rect.y1 - oldY) * winRec->bytesPerRow)
96905b261ecSmrg                    + (copy_rect.x1 - oldX) * Bpp, winRec->bytesPerRow,
97005b261ecSmrg                    gResizeDeathBits, copy_rowbytes);
97105b261ecSmrg            } else {
97205b261ecSmrg                fbBlt((FbBits *) (winRec->pixelData
97305b261ecSmrg                      + ((copy_rect.y1 - oldY) * winRec->bytesPerRow)
97405b261ecSmrg                      + (copy_rect.x1 - oldX) * Bpp),
97505b261ecSmrg                      winRec->bytesPerRow / sizeof(FbBits), 0,
97605b261ecSmrg                      (FbBits *) gResizeDeathBits,
97705b261ecSmrg                      copy_rowbytes / sizeof(FbBits), 0,
97805b261ecSmrg                      copy_rect_width * Bpp, copy_rect_height,
97905b261ecSmrg                      GXcopy, FB_ALLONES, Bpp, 0, 0);
98005b261ecSmrg            }
98105b261ecSmrg
98205b261ecSmrg            gResizeDeathBounds[1] = copy_rect;
98305b261ecSmrg            gResizeDeathPix[1]
98405b261ecSmrg                = GetScratchPixmapHeader(pScreen, copy_rect_width,
98505b261ecSmrg                                         copy_rect_height,
98605b261ecSmrg                                         winRec->win->drawable.depth,
98705b261ecSmrg                                         winRec->win->drawable.bitsPerPixel,
98805b261ecSmrg                                         winRec->bytesPerRow,
98905b261ecSmrg                                         (void *) gResizeDeathBits);
99005b261ecSmrg
99105b261ecSmrg            SetPixmapBaseToScreen(gResizeDeathPix[1],
99205b261ecSmrg                                  copy_rect.x1, copy_rect.y1);
99305b261ecSmrg
99405b261ecSmrg            gResizeDeathCount = 2;
99505b261ecSmrg        }
99605b261ecSmrg    }
99705b261ecSmrg    else if (gravity) {
99805b261ecSmrg        /* The general case. Just copy everything. */
99905b261ecSmrg
100005b261ecSmrg        RootlessStartDrawing(pWin);
100105b261ecSmrg
10026747b715Smrg        gResizeDeathBits = malloc(winRec->bytesPerRow * winRec->height);
100305b261ecSmrg
100405b261ecSmrg        memcpy(gResizeDeathBits, winRec->pixelData,
100505b261ecSmrg               winRec->bytesPerRow * winRec->height);
100605b261ecSmrg
100705b261ecSmrg        gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
100805b261ecSmrg        gResizeDeathPix[0]
100905b261ecSmrg            = GetScratchPixmapHeader(pScreen, winRec->width,
101005b261ecSmrg                                     winRec->height,
101105b261ecSmrg                                     winRec->win->drawable.depth,
101205b261ecSmrg                                     winRec->win->drawable.bitsPerPixel,
101305b261ecSmrg                                     winRec->bytesPerRow,
101405b261ecSmrg                                     (void *) gResizeDeathBits);
101505b261ecSmrg
101605b261ecSmrg        SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY);
101705b261ecSmrg        gResizeDeathCount = 1;
101805b261ecSmrg    }
101905b261ecSmrg
102005b261ecSmrg    RootlessStopDrawing(pWin, FALSE);
102105b261ecSmrg
102205b261ecSmrg    winRec->x = newX;
102305b261ecSmrg    winRec->y = newY;
102405b261ecSmrg    winRec->width = newW;
102505b261ecSmrg    winRec->height = newH;
102605b261ecSmrg    winRec->borderWidth = newBW;
102705b261ecSmrg
102805b261ecSmrg    /* Unless both dimensions are getting smaller, Resize the frame
102905b261ecSmrg       before doing gravity repair */
103005b261ecSmrg
103105b261ecSmrg    if (!resize_after) {
103205b261ecSmrg        SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
103305b261ecSmrg                                             newX + SCREEN_TO_GLOBAL_X,
103405b261ecSmrg                                             newY + SCREEN_TO_GLOBAL_Y,
103505b261ecSmrg                                             newW, newH, weight);
103605b261ecSmrg    }
103705b261ecSmrg
103805b261ecSmrg    RootlessStartDrawing(pWin);
103905b261ecSmrg
104005b261ecSmrg    /* If necessary, create a source pixmap pointing at the current
104105b261ecSmrg       window bits. */
104205b261ecSmrg
104305b261ecSmrg    if (need_window_source) {
104405b261ecSmrg        gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
104505b261ecSmrg        gResizeDeathPix[0]
104605b261ecSmrg            = GetScratchPixmapHeader(pScreen, oldW, oldH,
104705b261ecSmrg                                     winRec->win->drawable.depth,
104805b261ecSmrg                                     winRec->win->drawable.bitsPerPixel,
104905b261ecSmrg                                     winRec->bytesPerRow, winRec->pixelData);
105005b261ecSmrg
105105b261ecSmrg        SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY);
105205b261ecSmrg    }
105305b261ecSmrg
105405b261ecSmrg    /* Use custom CopyWindow when moving gravity bits around
105505b261ecSmrg       ResizeWindow assumes the old window contents are in the same
105605b261ecSmrg       pixmap, but here they're in deathPix instead. */
105705b261ecSmrg
105805b261ecSmrg    if (gravity) {
105905b261ecSmrg        gResizeOldCopyWindowProc = pScreen->CopyWindow;
106005b261ecSmrg        pScreen->CopyWindow = RootlessResizeCopyWindow;
106105b261ecSmrg    }
106205b261ecSmrg
106305b261ecSmrg    /* If we can't rely on the window server preserving the bits we
106405b261ecSmrg       need in the position we need, copy the pixels in the
106505b261ecSmrg       intersection from src to dst. ResizeWindow assumes these pixels
106605b261ecSmrg       are already present when making gravity adjustments. pWin
106705b261ecSmrg       currently has new-sized pixmap but is in old position.
106805b261ecSmrg
106905b261ecSmrg       FIXME: border width change! (?) */
107005b261ecSmrg
107105b261ecSmrg    if (gravity && weight == RL_GRAVITY_NONE) {
107205b261ecSmrg        PixmapPtr src, dst;
107305b261ecSmrg
107405b261ecSmrg        assert(gResizeDeathCount == 1);
107505b261ecSmrg
107605b261ecSmrg        src = gResizeDeathPix[0];
107705b261ecSmrg        dst = pScreen->GetWindowPixmap(pWin);
107805b261ecSmrg
107905b261ecSmrg        RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n",
108005b261ecSmrg                     rect.x1, rect.y1, rect.x2, rect.y2);
108105b261ecSmrg
108205b261ecSmrg        /* rect is the intersection of the old location and new location */
108305b261ecSmrg        if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL) {
108405b261ecSmrg            /* The window drawable still has the old frame position, which
108505b261ecSmrg               means that DST doesn't actually point at the origin of our
108605b261ecSmrg               physical backing store when adjusted by the drawable.x,y
108705b261ecSmrg               position. So sneakily adjust it temporarily while copying.. */
108805b261ecSmrg
108905b261ecSmrg            ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData;
109005b261ecSmrg            SetPixmapBaseToScreen(dst, newX, newY);
109105b261ecSmrg
109205b261ecSmrg            fbCopyWindowProc(&src->drawable, &dst->drawable, NULL,
109305b261ecSmrg                             &rect, 1, 0, 0, FALSE, FALSE, 0, 0);
109405b261ecSmrg
109505b261ecSmrg            ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData;
109605b261ecSmrg            SetPixmapBaseToScreen(dst, oldX, oldY);
109705b261ecSmrg        }
109805b261ecSmrg    }
109905b261ecSmrg
110005b261ecSmrg    return resize_after;
110105b261ecSmrg}
110205b261ecSmrg
110305b261ecSmrg
110405b261ecSmrgstatic void
110505b261ecSmrgFinishFrameResize(WindowPtr pWin, Bool gravity, int oldX, int oldY,
110605b261ecSmrg                  unsigned int oldW, unsigned int oldH, unsigned int oldBW,
110705b261ecSmrg                  int newX, int newY, unsigned int newW, unsigned int newH,
110805b261ecSmrg                  unsigned int newBW, Bool resize_now)
110905b261ecSmrg{
111005b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
111105b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
111205b261ecSmrg    int i;
111305b261ecSmrg
111405b261ecSmrg    RootlessStopDrawing(pWin, FALSE);
111505b261ecSmrg
111605b261ecSmrg    if (resize_now) {
111705b261ecSmrg        unsigned int weight;
111805b261ecSmrg
111905b261ecSmrg        /* We didn't resize anything earlier, so do it now, now that
112005b261ecSmrg           we've finished gravitating the bits. */
112105b261ecSmrg
112205b261ecSmrg        weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW,
112305b261ecSmrg                                 newX, newY, newW, newH, newBW);
112405b261ecSmrg
112505b261ecSmrg        SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
112605b261ecSmrg                                             newX + SCREEN_TO_GLOBAL_X,
112705b261ecSmrg                                             newY + SCREEN_TO_GLOBAL_Y,
112805b261ecSmrg                                             newW, newH, weight);
112905b261ecSmrg    }
113005b261ecSmrg
113105b261ecSmrg    /* Redraw everything. FIXME: there must be times when we don't need
113205b261ecSmrg       to do this. Perhaps when top-left weighting and no gravity? */
113305b261ecSmrg
113405b261ecSmrg    RootlessDamageRect(pWin, -newBW, -newBW, newW, newH);
113505b261ecSmrg
113605b261ecSmrg    for (i = 0; i < 2; i++) {
113705b261ecSmrg        if (gResizeDeathPix[i] != NULL) {
113805b261ecSmrg            FreeScratchPixmapHeader(gResizeDeathPix[i]);
113905b261ecSmrg            gResizeDeathPix[i] = NULL;
114005b261ecSmrg        }
114105b261ecSmrg    }
114205b261ecSmrg
11439ace9065Smrg    free(gResizeDeathBits);
11449ace9065Smrg    gResizeDeathBits = NULL;
114505b261ecSmrg
114605b261ecSmrg    if (gravity) {
114705b261ecSmrg        pScreen->CopyWindow = gResizeOldCopyWindowProc;
114805b261ecSmrg    }
114905b261ecSmrg}
115005b261ecSmrg
115105b261ecSmrg
115205b261ecSmrg/*
115305b261ecSmrg * RootlessMoveWindow
115405b261ecSmrg *  If kind==VTOther, window border is resizing (and borderWidth is
115505b261ecSmrg *  already changed!!@#$)  This case works like window resize, not move.
115605b261ecSmrg */
115705b261ecSmrgvoid
115805b261ecSmrgRootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
115905b261ecSmrg{
116005b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
116105b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
116205b261ecSmrg    CopyWindowProcPtr oldCopyWindowProc = NULL;
116305b261ecSmrg    int oldX = 0, oldY = 0, newX = 0, newY = 0;
116405b261ecSmrg    unsigned int oldW = 0, oldH = 0, oldBW = 0;
116505b261ecSmrg    unsigned int newW = 0, newH = 0, newBW = 0;
116605b261ecSmrg    Bool resize_after = FALSE;
116705b261ecSmrg    RegionRec saveRoot;
116805b261ecSmrg
116905b261ecSmrg    RL_DEBUG_MSG("movewindow start \n");
117005b261ecSmrg
117105b261ecSmrg    if (winRec) {
117205b261ecSmrg        if (kind == VTMove) {
117305b261ecSmrg            oldX = winRec->x;
117405b261ecSmrg            oldY = winRec->y;
117505b261ecSmrg            RootlessRedisplay(pWin);
117605b261ecSmrg            RootlessStartDrawing(pWin);
117705b261ecSmrg        } else {
117805b261ecSmrg            RL_DEBUG_MSG("movewindow border resizing ");
117905b261ecSmrg
118005b261ecSmrg            oldBW = winRec->borderWidth;
118105b261ecSmrg            oldX = winRec->x;
118205b261ecSmrg            oldY = winRec->y;
118305b261ecSmrg            oldW = winRec->width;
118405b261ecSmrg            oldH = winRec->height;
118505b261ecSmrg
118605b261ecSmrg            newBW = wBorderWidth(pWin);
118705b261ecSmrg            newX = x;
118805b261ecSmrg            newY = y;
118905b261ecSmrg            newW = pWin->drawable.width  + 2*newBW;
119005b261ecSmrg            newH = pWin->drawable.height + 2*newBW;
119105b261ecSmrg
119205b261ecSmrg            resize_after = StartFrameResize(pWin, FALSE,
119305b261ecSmrg                                            oldX, oldY, oldW, oldH, oldBW,
119405b261ecSmrg                                            newX, newY, newW, newH, newBW);
119505b261ecSmrg        }
119605b261ecSmrg    }
119705b261ecSmrg
119805b261ecSmrg    HUGE_ROOT(pWin);
119905b261ecSmrg    SCREEN_UNWRAP(pScreen, MoveWindow);
120005b261ecSmrg
120105b261ecSmrg    if (winRec) {
120205b261ecSmrg        oldCopyWindowProc = pScreen->CopyWindow;
120305b261ecSmrg        pScreen->CopyWindow = RootlessNoCopyWindow;
120405b261ecSmrg    }
120505b261ecSmrg    pScreen->MoveWindow(pWin, x, y, pSib, kind);
120605b261ecSmrg    if (winRec) {
120705b261ecSmrg        pScreen->CopyWindow = oldCopyWindowProc;
120805b261ecSmrg    }
120905b261ecSmrg
121005b261ecSmrg    NORMAL_ROOT(pWin);
121105b261ecSmrg    SCREEN_WRAP(pScreen, MoveWindow);
121205b261ecSmrg
121305b261ecSmrg    if (winRec) {
121405b261ecSmrg        if (kind == VTMove) {
121505b261ecSmrg            winRec->x = x;
121605b261ecSmrg            winRec->y = y;
121705b261ecSmrg            RootlessStopDrawing(pWin, FALSE);
121805b261ecSmrg            SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen,
121905b261ecSmrg                                               x + SCREEN_TO_GLOBAL_X,
122005b261ecSmrg                                               y + SCREEN_TO_GLOBAL_Y);
122105b261ecSmrg        } else {
122205b261ecSmrg            FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
122305b261ecSmrg                              newX, newY, newW, newH, newBW, resize_after);
122405b261ecSmrg        }
122505b261ecSmrg    }
122605b261ecSmrg
122705b261ecSmrg    RL_DEBUG_MSG("movewindow end\n");
122805b261ecSmrg}
122905b261ecSmrg
123005b261ecSmrg
123105b261ecSmrg/*
123205b261ecSmrg * RootlessResizeWindow
123305b261ecSmrg *  Note: (x, y, w, h) as passed to this procedure don't match the frame
123405b261ecSmrg *  definition. (x,y) is corner of very outer edge, *outside* border.
123505b261ecSmrg *  w,h is width and height *inside* border, *ignoring* border width.
123605b261ecSmrg *  The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw)
123705b261ecSmrg *  is total rect and (x+bw, y+bw, w, h) is inner rect.
123805b261ecSmrg */
123905b261ecSmrgvoid
124005b261ecSmrgRootlessResizeWindow(WindowPtr pWin, int x, int y,
124105b261ecSmrg                     unsigned int w, unsigned int h, WindowPtr pSib)
124205b261ecSmrg{
124305b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
124405b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
124505b261ecSmrg    int oldX = 0, oldY = 0, newX = 0, newY = 0;
124605b261ecSmrg    unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0;
124705b261ecSmrg    Bool resize_after = FALSE;
124805b261ecSmrg    RegionRec saveRoot;
124905b261ecSmrg
125005b261ecSmrg    RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin);
12514642e01fSmrg
12524642e01fSmrg    if(pWin->parent) {
12534642e01fSmrg        if (winRec) {
12544642e01fSmrg            oldBW = winRec->borderWidth;
12554642e01fSmrg            oldX = winRec->x;
12564642e01fSmrg            oldY = winRec->y;
12574642e01fSmrg            oldW = winRec->width;
12584642e01fSmrg            oldH = winRec->height;
125905b261ecSmrg
12604642e01fSmrg            newBW = oldBW;
12614642e01fSmrg            newX = x;
12624642e01fSmrg            newY = y;
12634642e01fSmrg            newW = w + 2*newBW;
12644642e01fSmrg            newH = h + 2*newBW;
126505b261ecSmrg
12664642e01fSmrg            resize_after = StartFrameResize(pWin, TRUE,
12674642e01fSmrg                                            oldX, oldY, oldW, oldH, oldBW,
12684642e01fSmrg                                            newX, newY, newW, newH, newBW);
12694642e01fSmrg        }
127005b261ecSmrg
12714642e01fSmrg        HUGE_ROOT(pWin);
12724642e01fSmrg        SCREEN_UNWRAP(pScreen, ResizeWindow);
12734642e01fSmrg        pScreen->ResizeWindow(pWin, x, y, w, h, pSib);
12744642e01fSmrg        SCREEN_WRAP(pScreen, ResizeWindow);
12754642e01fSmrg        NORMAL_ROOT(pWin);
12764642e01fSmrg
12774642e01fSmrg        if (winRec) {
12784642e01fSmrg            FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
12794642e01fSmrg                              newX, newY, newW, newH, newBW, resize_after);
12804642e01fSmrg        }
12814642e01fSmrg    } else {
12824642e01fSmrg        /* Special case for resizing the root window */
12834642e01fSmrg        BoxRec box;
12844642e01fSmrg
12854642e01fSmrg        pWin->drawable.x = x;
12864642e01fSmrg        pWin->drawable.y = y;
12874642e01fSmrg        pWin->drawable.width = w;
12884642e01fSmrg        pWin->drawable.height = h;
12894642e01fSmrg
12904642e01fSmrg        box.x1 = x; box.y1 = y;
12914642e01fSmrg        box.x2 = x + w; box.y2 = y + h;
12926747b715Smrg        RegionUninit(&pWin->winSize);
12936747b715Smrg        RegionInit(&pWin->winSize, &box, 1);
12946747b715Smrg        RegionCopy(&pWin->borderSize, &pWin->winSize);
12956747b715Smrg        RegionCopy(&pWin->clipList, &pWin->winSize);
12966747b715Smrg        RegionCopy(&pWin->borderClip, &pWin->winSize);
12976747b715Smrg
12986747b715Smrg        if (winRec) {
12996747b715Smrg            SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
13006747b715Smrg                                                 x + SCREEN_TO_GLOBAL_X,
13016747b715Smrg                                                 y + SCREEN_TO_GLOBAL_Y,
13026747b715Smrg                                                 w, h, RL_GRAVITY_NONE);
13036747b715Smrg        }
13044642e01fSmrg
13054642e01fSmrg        miSendExposures(pWin, &pWin->borderClip,
13064642e01fSmrg                        pWin->drawable.x, pWin->drawable.y);
130705b261ecSmrg    }
130805b261ecSmrg
130905b261ecSmrg    RL_DEBUG_MSG("resizewindow end\n");
131005b261ecSmrg}
131105b261ecSmrg
131205b261ecSmrg
131305b261ecSmrg/*
131405b261ecSmrg * RootlessRepositionWindow
131505b261ecSmrg *  Called by the implementation when a window needs to be repositioned to
131605b261ecSmrg *  its correct location on the screen. This routine is typically needed
131705b261ecSmrg *  due to changes in the underlying window system, such as a screen layout
131805b261ecSmrg *  change.
131905b261ecSmrg */
132005b261ecSmrgvoid
132105b261ecSmrgRootlessRepositionWindow(WindowPtr pWin)
132205b261ecSmrg{
132305b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
132405b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
132505b261ecSmrg
132605b261ecSmrg    if (winRec == NULL)
132705b261ecSmrg        return;
132805b261ecSmrg
132905b261ecSmrg    RootlessStopDrawing(pWin, FALSE);
133005b261ecSmrg    SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen,
133105b261ecSmrg                                       winRec->x + SCREEN_TO_GLOBAL_X,
133205b261ecSmrg                                       winRec->y + SCREEN_TO_GLOBAL_Y);
133305b261ecSmrg
133405b261ecSmrg    RootlessReorderWindow(pWin);
133505b261ecSmrg}
133605b261ecSmrg
133705b261ecSmrg
133805b261ecSmrg/*
133905b261ecSmrg * RootlessReparentWindow
134005b261ecSmrg *  Called after a window has been reparented. Generally windows are not
134105b261ecSmrg *  framed until they are mapped. However, a window may be framed early by the
134205b261ecSmrg *  implementation calling RootlessFrameForWindow. (e.g. this could be needed
134305b261ecSmrg *  to attach a VRAM surface to it.) If the window is subsequently reparented
134405b261ecSmrg *  by the window manager before being mapped, we need to give the frame to
134505b261ecSmrg *  the new top-level window.
134605b261ecSmrg */
134705b261ecSmrgvoid
134805b261ecSmrgRootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent)
134905b261ecSmrg{
135005b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
135105b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
135205b261ecSmrg    WindowPtr pTopWin;
135305b261ecSmrg
135405b261ecSmrg    /* Check that window is not top-level now, but used to be. */
135505b261ecSmrg    if (IsRoot(pWin) || IsRoot(pWin->parent)
135605b261ecSmrg        || IsTopLevel(pWin) || winRec == NULL)
135705b261ecSmrg    {
135805b261ecSmrg        goto out;
135905b261ecSmrg    }
136005b261ecSmrg
136105b261ecSmrg    /* If the formerly top-level window has a frame, we want to give the
136205b261ecSmrg       frame to its new top-level parent. If we can't do that, we'll just
136305b261ecSmrg       have to jettison it... */
136405b261ecSmrg
136505b261ecSmrg    pTopWin = TopLevelParent(pWin);
136605b261ecSmrg    assert(pTopWin != pWin);
13674642e01fSmrg
13684642e01fSmrg    pWin->rootlessUnhittable = FALSE;
13694642e01fSmrg
13704642e01fSmrg    DeleteProperty (serverClient, pWin, xa_native_window_id ());
137105b261ecSmrg
137205b261ecSmrg    if (WINREC(pTopWin) != NULL) {
137305b261ecSmrg        /* We're screwed. */
137405b261ecSmrg        RootlessDestroyFrame(pWin, winRec);
137505b261ecSmrg    } else {
137605b261ecSmrg        if (!pTopWin->realized && pWin->realized) {
137705b261ecSmrg            SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid);
137805b261ecSmrg        }
137905b261ecSmrg
138005b261ecSmrg        /* Switch the frame record from one to the other. */
138105b261ecSmrg
13824642e01fSmrg        SETWINREC(pWin, NULL);
13834642e01fSmrg        SETWINREC(pTopWin, winRec);
138405b261ecSmrg
138505b261ecSmrg        RootlessInitializeFrame(pTopWin, winRec);
138605b261ecSmrg        RootlessReshapeFrame(pTopWin);
138705b261ecSmrg
138805b261ecSmrg        SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
138905b261ecSmrg                                             winRec->x + SCREEN_TO_GLOBAL_X,
139005b261ecSmrg                                             winRec->y + SCREEN_TO_GLOBAL_Y,
139105b261ecSmrg                                             winRec->width, winRec->height,
139205b261ecSmrg                                             RL_GRAVITY_NONE);
139305b261ecSmrg
139405b261ecSmrg        if (SCREENREC(pScreen)->imp->SwitchWindow) {
139505b261ecSmrg            SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin);
139605b261ecSmrg        }
139705b261ecSmrg
139805b261ecSmrg        if (pTopWin->realized && !pWin->realized)
139905b261ecSmrg            winRec->is_reorder_pending = TRUE;
140005b261ecSmrg    }
140105b261ecSmrg
140205b261ecSmrgout:
140305b261ecSmrg    if (SCREENREC(pScreen)->ReparentWindow) {
140405b261ecSmrg        SCREEN_UNWRAP(pScreen, ReparentWindow);
140505b261ecSmrg        pScreen->ReparentWindow(pWin, pPriorParent);
140605b261ecSmrg        SCREEN_WRAP(pScreen, ReparentWindow);
140705b261ecSmrg    }
140805b261ecSmrg}
140905b261ecSmrg
141005b261ecSmrg
141105b261ecSmrgvoid
14124642e01fSmrgRootlessFlushWindowColormap (WindowPtr pWin)
141305b261ecSmrg{
14144642e01fSmrg  RootlessWindowRec *winRec = WINREC (pWin);
14156747b715Smrg  ScreenPtr pScreen = pWin->drawable.pScreen;
141605b261ecSmrg
14174642e01fSmrg  if (winRec == NULL)
14184642e01fSmrg    return;
141905b261ecSmrg
14204642e01fSmrg  RootlessStopDrawing (pWin, FALSE);
142105b261ecSmrg
14226747b715Smrg  if (SCREENREC(pScreen)->imp->UpdateColormap)
14236747b715Smrg    SCREENREC(pScreen)->imp->UpdateColormap(winRec->wid, pScreen);
142405b261ecSmrg}
142505b261ecSmrg
142605b261ecSmrg/*
142705b261ecSmrg * RootlessChangeBorderWidth
142805b261ecSmrg *  FIXME: untested!
142905b261ecSmrg *  pWin inside corner stays the same; pWin->drawable.[xy] stays the same
143005b261ecSmrg *  Frame moves and resizes.
143105b261ecSmrg */
143205b261ecSmrgvoid
143305b261ecSmrgRootlessChangeBorderWidth(WindowPtr pWin, unsigned int width)
143405b261ecSmrg{
143505b261ecSmrg    RegionRec saveRoot;
143605b261ecSmrg    Bool resize_after = FALSE;
143705b261ecSmrg
143805b261ecSmrg    RL_DEBUG_MSG("change border width ");
143905b261ecSmrg
144005b261ecSmrg    if (width != wBorderWidth(pWin)) {
144105b261ecSmrg        RootlessWindowRec *winRec = WINREC(pWin);
144205b261ecSmrg        int oldX = 0, oldY = 0, newX = 0, newY = 0;
144305b261ecSmrg        unsigned int oldW = 0, oldH = 0, oldBW = 0;
144405b261ecSmrg        unsigned int newW = 0, newH = 0, newBW = 0;
144505b261ecSmrg
144605b261ecSmrg        if (winRec) {
144705b261ecSmrg            oldBW = winRec->borderWidth;
144805b261ecSmrg            oldX = winRec->x;
144905b261ecSmrg            oldY = winRec->y;
145005b261ecSmrg            oldW = winRec->width;
145105b261ecSmrg            oldH = winRec->height;
145205b261ecSmrg
145305b261ecSmrg            newBW = width;
145405b261ecSmrg            newX = pWin->drawable.x - newBW;
145505b261ecSmrg            newY = pWin->drawable.y - newBW;
145605b261ecSmrg            newW = pWin->drawable.width  + 2*newBW;
145705b261ecSmrg            newH = pWin->drawable.height + 2*newBW;
145805b261ecSmrg
145905b261ecSmrg            resize_after = StartFrameResize(pWin, FALSE,
146005b261ecSmrg                                            oldX, oldY, oldW, oldH, oldBW,
146105b261ecSmrg                                            newX, newY, newW, newH, newBW);
146205b261ecSmrg        }
146305b261ecSmrg
146405b261ecSmrg        HUGE_ROOT(pWin);
146505b261ecSmrg        SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth);
146605b261ecSmrg        pWin->drawable.pScreen->ChangeBorderWidth(pWin, width);
146705b261ecSmrg        SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth);
146805b261ecSmrg        NORMAL_ROOT(pWin);
146905b261ecSmrg
147005b261ecSmrg        if (winRec) {
147105b261ecSmrg            FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
147205b261ecSmrg                              newX, newY, newW, newH, newBW, resize_after);
147305b261ecSmrg        }
147405b261ecSmrg    }
147505b261ecSmrg
147605b261ecSmrg    RL_DEBUG_MSG("change border width end\n");
147705b261ecSmrg}
14784642e01fSmrg
14794642e01fSmrg/*
14804642e01fSmrg * RootlessOrderAllWindows
14814642e01fSmrg * Brings all X11 windows to the top of the window stack
14824642e01fSmrg * (i.e in front of Aqua windows) -- called when X11.app is given focus
14834642e01fSmrg */
14844642e01fSmrgvoid
14856747b715SmrgRootlessOrderAllWindows (Bool include_unhitable)
14864642e01fSmrg{
14874642e01fSmrg    int i;
14884642e01fSmrg    WindowPtr pWin;
14894642e01fSmrg
14904642e01fSmrg    if (windows_hidden)
14914642e01fSmrg        return;
14924642e01fSmrg
14934642e01fSmrg    RL_DEBUG_MSG("RootlessOrderAllWindows() ");
14944642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
14954642e01fSmrg      if (screenInfo.screens[i] == NULL) continue;
14966747b715Smrg      pWin = screenInfo.screens[i]->root;
14974642e01fSmrg      if (pWin == NULL) continue;
14984642e01fSmrg
14994642e01fSmrg      for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) {
15004642e01fSmrg	if (!pWin->realized) continue;
15014642e01fSmrg	if (RootlessEnsureFrame(pWin) == NULL) continue;
15026747b715Smrg        if (!include_unhitable && pWin->rootlessUnhittable) continue;
15034642e01fSmrg	RootlessReorderWindow (pWin);
15044642e01fSmrg      }
15054642e01fSmrg    }
15064642e01fSmrg    RL_DEBUG_MSG("RootlessOrderAllWindows() done");
15074642e01fSmrg}
15084642e01fSmrg
15094642e01fSmrgvoid
15104642e01fSmrgRootlessEnableRoot (ScreenPtr pScreen)
15114642e01fSmrg{
15124642e01fSmrg    WindowPtr pRoot;
15136747b715Smrg    pRoot = pScreen->root;
15144642e01fSmrg
15154642e01fSmrg    RootlessEnsureFrame (pRoot);
15164642e01fSmrg    (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE);
15174642e01fSmrg    RootlessReorderWindow (pRoot);
15184642e01fSmrg}
15194642e01fSmrg
15204642e01fSmrgvoid
15214642e01fSmrgRootlessDisableRoot (ScreenPtr pScreen)
15224642e01fSmrg{
15234642e01fSmrg    WindowPtr pRoot;
15244642e01fSmrg    RootlessWindowRec *winRec;
15254642e01fSmrg
15266747b715Smrg    pRoot = pScreen->root;
15274642e01fSmrg    winRec = WINREC (pRoot);
15284642e01fSmrg
15294642e01fSmrg    if (NULL == winRec)
15304642e01fSmrg	return;
15314642e01fSmrg
15324642e01fSmrg    RootlessDestroyFrame (pRoot, winRec);
15334642e01fSmrg    DeleteProperty (serverClient, pRoot, xa_native_window_id ());
15344642e01fSmrg}
15354642e01fSmrg
15364642e01fSmrgvoid
15374642e01fSmrgRootlessHideAllWindows (void)
15384642e01fSmrg{
15394642e01fSmrg    int i;
15404642e01fSmrg    ScreenPtr pScreen;
15414642e01fSmrg    WindowPtr pWin;
15424642e01fSmrg    RootlessWindowRec *winRec;
15434642e01fSmrg
15444642e01fSmrg    if (windows_hidden)
15454642e01fSmrg        return;
15464642e01fSmrg
15474642e01fSmrg    windows_hidden = TRUE;
15484642e01fSmrg
15494642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++)
15504642e01fSmrg    {
15514642e01fSmrg        pScreen = screenInfo.screens[i];
15526747b715Smrg	if (pScreen == NULL)
15536747b715Smrg	    continue;
15546747b715Smrg	pWin = pScreen->root;
15556747b715Smrg	if (pWin == NULL)
15564642e01fSmrg            continue;
15574642e01fSmrg
15584642e01fSmrg        for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
15594642e01fSmrg        {
15604642e01fSmrg            if (!pWin->realized)
15614642e01fSmrg                continue;
15624642e01fSmrg
15634642e01fSmrg            RootlessStopDrawing (pWin, FALSE);
15644642e01fSmrg
15654642e01fSmrg            winRec = WINREC (pWin);
15664642e01fSmrg            if (winRec != NULL)
15674642e01fSmrg            {
15686747b715Smrg              if (SCREENREC(pScreen)->imp->HideWindow)
15696747b715Smrg                SCREENREC(pScreen)->imp->HideWindow(winRec->wid);
15704642e01fSmrg            }
15714642e01fSmrg        }
15724642e01fSmrg    }
15734642e01fSmrg}
15744642e01fSmrg
15754642e01fSmrgvoid
15764642e01fSmrgRootlessShowAllWindows (void)
15774642e01fSmrg{
15784642e01fSmrg    int i;
15794642e01fSmrg    ScreenPtr pScreen;
15804642e01fSmrg    WindowPtr pWin;
15814642e01fSmrg    RootlessWindowRec *winRec;
15824642e01fSmrg
15834642e01fSmrg    if (!windows_hidden)
15844642e01fSmrg        return;
15854642e01fSmrg
15864642e01fSmrg    windows_hidden = FALSE;
15874642e01fSmrg
15884642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++)
15894642e01fSmrg    {
15904642e01fSmrg        pScreen = screenInfo.screens[i];
15916747b715Smrg	if (pScreen == NULL)
15926747b715Smrg	    continue;
15936747b715Smrg	pWin = pScreen->root;
15946747b715Smrg	if (pWin == NULL)
15954642e01fSmrg            continue;
15964642e01fSmrg
15974642e01fSmrg        for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
15984642e01fSmrg        {
15994642e01fSmrg            if (!pWin->realized)
16004642e01fSmrg                continue;
16014642e01fSmrg
16024642e01fSmrg            winRec = RootlessEnsureFrame (pWin);
16034642e01fSmrg            if (winRec == NULL)
16044642e01fSmrg                continue;
16054642e01fSmrg
16064642e01fSmrg            RootlessReorderWindow (pWin);
16074642e01fSmrg        }
16084642e01fSmrg
16094642e01fSmrg        RootlessScreenExpose (pScreen);
16104642e01fSmrg    }
16114642e01fSmrg}
16126747b715Smrg
16136747b715Smrg/*
16146747b715Smrg * SetPixmapOfAncestors
16156747b715Smrg *  Set the Pixmaps on all ParentRelative windows up the ancestor chain.
16166747b715Smrg */
16176747b715Smrgvoid
16186747b715SmrgRootlessSetPixmapOfAncestors(WindowPtr pWin)
16196747b715Smrg{
16206747b715Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
16216747b715Smrg    WindowPtr topWin = TopLevelParent(pWin);
16226747b715Smrg    RootlessWindowRec *topWinRec = WINREC(topWin);
16236747b715Smrg
16246747b715Smrg    while (pWin->backgroundState == ParentRelative) {
16256747b715Smrg        if (pWin == topWin) {
16266747b715Smrg            // disallow ParentRelative background state on top level
16276747b715Smrg            XID pixel = 0;
16286747b715Smrg            ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
16296747b715Smrg            RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin);
16306747b715Smrg            break;
16316747b715Smrg        }
16326747b715Smrg
16336747b715Smrg        pWin = pWin->parent;
16346747b715Smrg        pScreen->SetWindowPixmap(pWin, topWinRec->pixmap);
16356747b715Smrg    }
16366747b715Smrg}
16376747b715Smrg
1638