rootlessWindow.c revision 4642e01f
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#ifdef __APPLE__
404642e01fSmrg//#include <X11/Xlib.h>
414642e01fSmrg#include <X11/Xatom.h>
424642e01fSmrg#include "mi.h"
434642e01fSmrg#include "pixmapstr.h"
444642e01fSmrg#include "windowstr.h"
454642e01fSmrg#include <Xplugin.h>
464642e01fSmrg//#include <X11/extensions/applewm.h>
474642e01fSmrgextern int darwinMainScreenX, darwinMainScreenY;
484642e01fSmrg#endif
494642e01fSmrg#include "fb.h"
504642e01fSmrg
514642e01fSmrg#define AppleWMNumWindowLevels 5
5205b261ecSmrg
5305b261ecSmrg#include "rootlessCommon.h"
5405b261ecSmrg#include "rootlessWindow.h"
5505b261ecSmrg
5605b261ecSmrg#ifdef ROOTLESS_GLOBAL_COORDS
5705b261ecSmrg#define SCREEN_TO_GLOBAL_X \
5805b261ecSmrg    (dixScreenOrigins[pScreen->myNum].x + rootlessGlobalOffsetX)
5905b261ecSmrg#define SCREEN_TO_GLOBAL_Y \
6005b261ecSmrg    (dixScreenOrigins[pScreen->myNum].y + rootlessGlobalOffsetY)
6105b261ecSmrg#else
6205b261ecSmrg#define SCREEN_TO_GLOBAL_X 0
6305b261ecSmrg#define SCREEN_TO_GLOBAL_Y 0
6405b261ecSmrg#endif
6505b261ecSmrg
664642e01fSmrg#define MAKE_WINDOW_ID(x)		((xp_window_id)((size_t)(x)))
674642e01fSmrg
684642e01fSmrg#define DEFINE_ATOM_HELPER(func,atom_name)                      \
694642e01fSmrg  static Atom func (void) {                                       \
704642e01fSmrg    static unsigned int generation = 0;                             \
714642e01fSmrg    static Atom atom;                                           \
724642e01fSmrg    if (generation != serverGeneration) {                       \
734642e01fSmrg      generation = serverGeneration;                          \
744642e01fSmrg      atom = MakeAtom (atom_name, strlen (atom_name), TRUE);  \
754642e01fSmrg    }                                                           \
764642e01fSmrg    return atom;                                                \
774642e01fSmrg  }
784642e01fSmrg
794642e01fSmrgDEFINE_ATOM_HELPER (xa_native_screen_origin, "_NATIVE_SCREEN_ORIGIN")
804642e01fSmrgDEFINE_ATOM_HELPER (xa_native_window_id, "_NATIVE_WINDOW_ID")
814642e01fSmrgDEFINE_ATOM_HELPER (xa_apple_no_order_in, "_APPLE_NO_ORDER_IN")
824642e01fSmrg
834642e01fSmrgstatic Bool no_configure_window;
844642e01fSmrgstatic Bool windows_hidden;
854642e01fSmrg// TODO - abstract xp functions
864642e01fSmrg
874642e01fSmrgstatic inline int
884642e01fSmrgconfigure_window (xp_window_id id, unsigned int mask,
894642e01fSmrg                  const xp_window_changes *values)
904642e01fSmrg{
914642e01fSmrg  if (!no_configure_window)
924642e01fSmrg    return xp_configure_window (id, mask, values);
934642e01fSmrg  else
944642e01fSmrg    return XP_Success;
954642e01fSmrg}
964642e01fSmrg
974642e01fSmrg/*static inline unsigned long
984642e01fSmrgcurrent_time_in_seconds (void)
994642e01fSmrg{
1004642e01fSmrg  unsigned long t = 0;
1014642e01fSmrg
1024642e01fSmrg  t += currentTime.milliseconds / 1000;
1034642e01fSmrg  t += currentTime.months * 4294967;
1044642e01fSmrg
1054642e01fSmrg  return t;
1064642e01fSmrg  } */
1074642e01fSmrg
1084642e01fSmrgstatic inline Bool
1094642e01fSmrgrootlessHasRoot (ScreenPtr pScreen)
1104642e01fSmrg{
1114642e01fSmrg  return WINREC (WindowTable[pScreen->myNum]) != NULL;
1124642e01fSmrg}
1134642e01fSmrg
1144642e01fSmrgvoid
1154642e01fSmrgRootlessNativeWindowStateChanged (WindowPtr pWin, unsigned int state)
1164642e01fSmrg{
1174642e01fSmrg  RootlessWindowRec *winRec;
1184642e01fSmrg
1194642e01fSmrg  if (pWin == NULL) return;
1204642e01fSmrg
1214642e01fSmrg  winRec = WINREC (pWin);
1224642e01fSmrg  if (winRec == NULL) return;
1234642e01fSmrg
1244642e01fSmrg  winRec->is_offscreen = ((state & XP_WINDOW_STATE_OFFSCREEN) != 0);
1254642e01fSmrg  winRec->is_obscured = ((state & XP_WINDOW_STATE_OBSCURED) != 0);
1264642e01fSmrg  pWin->rootlessUnhittable = winRec->is_offscreen;
1274642e01fSmrg}
1284642e01fSmrg
1294642e01fSmrgvoid RootlessNativeWindowMoved (WindowPtr pWin) {
1304642e01fSmrg    xp_box bounds;
1314642e01fSmrg    int sx, sy, err;
1324642e01fSmrg    XID vlist[2];
1334642e01fSmrg    Mask mask;
1344642e01fSmrg    ClientPtr pClient;
1354642e01fSmrg    RootlessWindowRec *winRec;
1364642e01fSmrg
1374642e01fSmrg    winRec = WINREC(pWin);
1384642e01fSmrg
1394642e01fSmrg    if (xp_get_window_bounds (MAKE_WINDOW_ID(winRec->wid), &bounds) != Success) return;
1404642e01fSmrg
1414642e01fSmrg    sx = dixScreenOrigins[pWin->drawable.pScreen->myNum].x + darwinMainScreenX;
1424642e01fSmrg    sy = dixScreenOrigins[pWin->drawable.pScreen->myNum].y + darwinMainScreenY;
1434642e01fSmrg
1444642e01fSmrg    /* Fake up a ConfigureWindow packet to resize the window to the current bounds. */
1454642e01fSmrg    vlist[0] = (INT16) bounds.x1 - sx;
1464642e01fSmrg    vlist[1] = (INT16) bounds.y1 - sy;
1474642e01fSmrg    mask = CWX | CWY;
1484642e01fSmrg
1494642e01fSmrg    /* pretend we're the owner of the window! */
1504642e01fSmrg    err = dixLookupClient(&pClient, pWin->drawable.id, NullClient, DixUnknownAccess);
1514642e01fSmrg    if(err != Success) {
1524642e01fSmrg        ErrorF("RootlessNativeWindowMoved(): Failed to lookup window: 0x%x\n", (unsigned int)pWin->drawable.id);
1534642e01fSmrg        return;
1544642e01fSmrg    }
1554642e01fSmrg
1564642e01fSmrg    /* Don't want to do anything to the physical window (avoids
1574642e01fSmrg     notification-response feedback loops) */
1584642e01fSmrg
1594642e01fSmrg    no_configure_window = TRUE;
1604642e01fSmrg    ConfigureWindow (pWin, mask, vlist, pClient);
1614642e01fSmrg    no_configure_window = FALSE;
1624642e01fSmrg}
1634642e01fSmrg
1644642e01fSmrg/* Updates the _NATIVE_SCREEN_ORIGIN property on the given root window. */
1654642e01fSmrgstatic void
1664642e01fSmrgset_screen_origin (WindowPtr pWin)
1674642e01fSmrg{
1684642e01fSmrg  long data[2];
1694642e01fSmrg
1704642e01fSmrg  if (!IsRoot (pWin))
1714642e01fSmrg    return;
1724642e01fSmrg
1734642e01fSmrg  /* FIXME: move this to an extension? */
1744642e01fSmrg
1754642e01fSmrg  data[0] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].x
1764642e01fSmrg	     + darwinMainScreenX);
1774642e01fSmrg  data[1] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].y
1784642e01fSmrg	     + darwinMainScreenY);
1794642e01fSmrg
1804642e01fSmrg  dixChangeWindowProperty(serverClient, pWin, xa_native_screen_origin(),
1814642e01fSmrg			  XA_INTEGER, 32, PropModeReplace, 2, data, TRUE);
1824642e01fSmrg}
18305b261ecSmrg
18405b261ecSmrg/*
18505b261ecSmrg * RootlessCreateWindow
18605b261ecSmrg *  For now, don't create a physical window until either the window is
18705b261ecSmrg *  realized, or we really need it (e.g. to attach VRAM surfaces to).
18805b261ecSmrg *  Do reset the window size so it's not clipped by the root window.
18905b261ecSmrg */
19005b261ecSmrgBool
19105b261ecSmrgRootlessCreateWindow(WindowPtr pWin)
19205b261ecSmrg{
19305b261ecSmrg    Bool result;
19405b261ecSmrg    RegionRec saveRoot;
19505b261ecSmrg
1964642e01fSmrg    SETWINREC(pWin, NULL);
1974642e01fSmrg    dixSetPrivate(&pWin->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL);
19805b261ecSmrg
19905b261ecSmrg    SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow);
20005b261ecSmrg
20105b261ecSmrg    if (!IsRoot(pWin)) {
20205b261ecSmrg        /* win/border size set by DIX, not by wrapped CreateWindow, so
20305b261ecSmrg           correct it here. Don't HUGE_ROOT when pWin is the root! */
20405b261ecSmrg
20505b261ecSmrg        HUGE_ROOT(pWin);
20605b261ecSmrg        SetWinSize(pWin);
20705b261ecSmrg        SetBorderSize(pWin);
20805b261ecSmrg    }
20905b261ecSmrg
21005b261ecSmrg    result = pWin->drawable.pScreen->CreateWindow(pWin);
21105b261ecSmrg
21205b261ecSmrg    if (pWin->parent) {
21305b261ecSmrg        NORMAL_ROOT(pWin);
21405b261ecSmrg    }
21505b261ecSmrg
21605b261ecSmrg    SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow);
21705b261ecSmrg
21805b261ecSmrg    return result;
21905b261ecSmrg}
22005b261ecSmrg
22105b261ecSmrg
22205b261ecSmrg/*
22305b261ecSmrg * RootlessDestroyFrame
22405b261ecSmrg *  Destroy the physical window associated with the given window.
22505b261ecSmrg */
22605b261ecSmrgstatic void
22705b261ecSmrgRootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec)
22805b261ecSmrg{
22905b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
23005b261ecSmrg
23105b261ecSmrg    SCREENREC(pScreen)->imp->DestroyFrame(winRec->wid);
23205b261ecSmrg
23305b261ecSmrg#ifdef ROOTLESS_TRACK_DAMAGE
23405b261ecSmrg    REGION_UNINIT(pScreen, &winRec->damage);
23505b261ecSmrg#endif
23605b261ecSmrg
23705b261ecSmrg    xfree(winRec);
2384642e01fSmrg    SETWINREC(pWin, NULL);
23905b261ecSmrg}
24005b261ecSmrg
24105b261ecSmrg
24205b261ecSmrg/*
24305b261ecSmrg * RootlessDestroyWindow
24405b261ecSmrg *  Destroy the physical window associated with the given window.
24505b261ecSmrg */
24605b261ecSmrgBool
24705b261ecSmrgRootlessDestroyWindow(WindowPtr pWin)
24805b261ecSmrg{
24905b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
25005b261ecSmrg    Bool result;
25105b261ecSmrg
25205b261ecSmrg    if (winRec != NULL) {
25305b261ecSmrg        RootlessDestroyFrame(pWin, winRec);
25405b261ecSmrg    }
25505b261ecSmrg
25605b261ecSmrg    SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow);
25705b261ecSmrg    result = pWin->drawable.pScreen->DestroyWindow(pWin);
25805b261ecSmrg    SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow);
25905b261ecSmrg
26005b261ecSmrg    return result;
26105b261ecSmrg}
26205b261ecSmrg
26305b261ecSmrg
26405b261ecSmrg
26505b261ecSmrgstatic Bool
26605b261ecSmrgRootlessGetShape(WindowPtr pWin, RegionPtr pShape)
26705b261ecSmrg{
26805b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
26905b261ecSmrg
2704642e01fSmrg    /*
2714642e01fSmrg     * Avoid a warning.
2724642e01fSmrg     * REGION_NULL and the other macros don't actually seem to use pScreen.
2734642e01fSmrg     */
2744642e01fSmrg    (void)pScreen;
2754642e01fSmrg
27605b261ecSmrg    if (wBoundingShape(pWin) == NULL)
27705b261ecSmrg        return FALSE;
27805b261ecSmrg
27905b261ecSmrg    /* wBoundingShape is relative to *inner* origin of window.
28005b261ecSmrg       Translate by borderWidth to get the outside-relative position. */
28105b261ecSmrg
28205b261ecSmrg    REGION_NULL(pScreen, pShape);
28305b261ecSmrg    REGION_COPY(pScreen, pShape, wBoundingShape(pWin));
28405b261ecSmrg    REGION_TRANSLATE(pScreen, pShape, pWin->borderWidth, pWin->borderWidth);
28505b261ecSmrg
28605b261ecSmrg    return TRUE;
28705b261ecSmrg}
28805b261ecSmrg
28905b261ecSmrg
29005b261ecSmrg/*
29105b261ecSmrg * RootlessReshapeFrame
29205b261ecSmrg *  Set the frame shape.
29305b261ecSmrg */
29405b261ecSmrgstatic void RootlessReshapeFrame(WindowPtr pWin)
29505b261ecSmrg{
29605b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
29705b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
29805b261ecSmrg    RegionRec newShape;
29905b261ecSmrg    RegionPtr pShape;
30005b261ecSmrg
30105b261ecSmrg    // If the window is not yet framed, do nothing
30205b261ecSmrg    if (winRec == NULL)
30305b261ecSmrg        return;
30405b261ecSmrg
30505b261ecSmrg    if (IsRoot(pWin))
30605b261ecSmrg        return;
30705b261ecSmrg
30805b261ecSmrg    RootlessStopDrawing(pWin, FALSE);
30905b261ecSmrg
31005b261ecSmrg    pShape = RootlessGetShape(pWin, &newShape) ? &newShape : NULL;
31105b261ecSmrg
31205b261ecSmrg#ifdef ROOTLESSDEBUG
31305b261ecSmrg    RL_DEBUG_MSG("reshaping...");
31405b261ecSmrg    if (pShape != NULL) {
31505b261ecSmrg        RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ",
31605b261ecSmrg                     REGION_NUM_RECTS(&newShape),
31705b261ecSmrg                     newShape.extents.x1, newShape.extents.y1,
31805b261ecSmrg                     newShape.extents.x2, newShape.extents.y2);
31905b261ecSmrg    } else {
32005b261ecSmrg        RL_DEBUG_MSG("no shape ");
32105b261ecSmrg    }
32205b261ecSmrg#endif
32305b261ecSmrg
32405b261ecSmrg    SCREENREC(pScreen)->imp->ReshapeFrame(winRec->wid, pShape);
32505b261ecSmrg
32605b261ecSmrg    if (pShape != NULL)
32705b261ecSmrg        REGION_UNINIT(pScreen, &newShape);
32805b261ecSmrg}
32905b261ecSmrg
33005b261ecSmrg
33105b261ecSmrg/*
33205b261ecSmrg * RootlessSetShape
33305b261ecSmrg *  Shape is usually set before a window is mapped and the window will
33405b261ecSmrg *  not have a frame associated with it. In this case, the frame will be
33505b261ecSmrg *  shaped when the window is framed.
33605b261ecSmrg */
33705b261ecSmrgvoid
33805b261ecSmrgRootlessSetShape(WindowPtr pWin)
33905b261ecSmrg{
34005b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
34105b261ecSmrg
34205b261ecSmrg    SCREEN_UNWRAP(pScreen, SetShape);
34305b261ecSmrg    pScreen->SetShape(pWin);
34405b261ecSmrg    SCREEN_WRAP(pScreen, SetShape);
34505b261ecSmrg
34605b261ecSmrg    RootlessReshapeFrame(pWin);
34705b261ecSmrg}
34805b261ecSmrg
34905b261ecSmrg
35005b261ecSmrg
35105b261ecSmrg/* Disallow ParentRelative background on top-level windows
3524642e01fSmrg   because the root window doesn't really have the right background.
3534642e01fSmrg */
35405b261ecSmrgBool
35505b261ecSmrgRootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask)
35605b261ecSmrg{
35705b261ecSmrg    Bool result;
35805b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
35905b261ecSmrg
36005b261ecSmrg    RL_DEBUG_MSG("change window attributes start ");
36105b261ecSmrg
36205b261ecSmrg    SCREEN_UNWRAP(pScreen, ChangeWindowAttributes);
36305b261ecSmrg    result = pScreen->ChangeWindowAttributes(pWin, vmask);
36405b261ecSmrg    SCREEN_WRAP(pScreen, ChangeWindowAttributes);
36505b261ecSmrg
36605b261ecSmrg    if (WINREC(pWin)) {
36705b261ecSmrg        // disallow ParentRelative background state
36805b261ecSmrg        if (pWin->backgroundState == ParentRelative) {
36905b261ecSmrg            XID pixel = 0;
37005b261ecSmrg            ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
37105b261ecSmrg        }
37205b261ecSmrg    }
37305b261ecSmrg
37405b261ecSmrg    RL_DEBUG_MSG("change window attributes end\n");
37505b261ecSmrg    return result;
37605b261ecSmrg}
37705b261ecSmrg
37805b261ecSmrg
37905b261ecSmrg/*
38005b261ecSmrg * RootlessPositionWindow
38105b261ecSmrg *  This is a hook for when DIX moves or resizes a window.
38205b261ecSmrg *  Update the frame position now although the physical window is moved
38305b261ecSmrg *  in RootlessMoveWindow. (x, y) are *inside* position. After this,
38405b261ecSmrg *  mi and fb are expecting the pixmap to be at the new location.
38505b261ecSmrg */
38605b261ecSmrgBool
38705b261ecSmrgRootlessPositionWindow(WindowPtr pWin, int x, int y)
38805b261ecSmrg{
38905b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
39005b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
39105b261ecSmrg    Bool result;
39205b261ecSmrg
39305b261ecSmrg    RL_DEBUG_MSG("positionwindow start (win 0x%x @ %i, %i)\n", pWin, x, y);
39405b261ecSmrg
39505b261ecSmrg    if (winRec) {
39605b261ecSmrg        if (winRec->is_drawing) {
39705b261ecSmrg            // Reset frame's pixmap and move it to the new position.
39805b261ecSmrg            int bw = wBorderWidth(pWin);
39905b261ecSmrg
40005b261ecSmrg            winRec->pixmap->devPrivate.ptr = winRec->pixelData;
40105b261ecSmrg            SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw);
40205b261ecSmrg
40305b261ecSmrg#ifdef ROOTLESS_TRACK_DAMAGE
40405b261ecSmrg            // Move damaged region to correspond to new window position
40505b261ecSmrg            if (REGION_NOTEMPTY(pScreen, &winRec->damage)) {
40605b261ecSmrg                REGION_TRANSLATE(pScreen, &winRec->damage,
40705b261ecSmrg                                 x - bw - winRec->x,
40805b261ecSmrg                                 y - bw - winRec->y);
40905b261ecSmrg            }
41005b261ecSmrg#endif
41105b261ecSmrg        }
41205b261ecSmrg    }
41305b261ecSmrg
41405b261ecSmrg    SCREEN_UNWRAP(pScreen, PositionWindow);
41505b261ecSmrg    result = pScreen->PositionWindow(pWin, x, y);
41605b261ecSmrg    SCREEN_WRAP(pScreen, PositionWindow);
41705b261ecSmrg
41805b261ecSmrg    RL_DEBUG_MSG("positionwindow end\n");
41905b261ecSmrg    return result;
42005b261ecSmrg}
42105b261ecSmrg
42205b261ecSmrg
42305b261ecSmrg/*
42405b261ecSmrg * RootlessInitializeFrame
42505b261ecSmrg *  Initialize some basic attributes of the frame. Note that winRec
42605b261ecSmrg *  may already have valid data in it, so don't overwrite anything
42705b261ecSmrg *  valuable.
42805b261ecSmrg */
42905b261ecSmrgstatic void
43005b261ecSmrgRootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec *winRec)
43105b261ecSmrg{
43205b261ecSmrg    DrawablePtr d = &pWin->drawable;
43305b261ecSmrg    int bw = wBorderWidth(pWin);
43405b261ecSmrg
43505b261ecSmrg    winRec->win = pWin;
43605b261ecSmrg
43705b261ecSmrg    winRec->x = d->x - bw;
43805b261ecSmrg    winRec->y = d->y - bw;
43905b261ecSmrg    winRec->width = d->width + 2*bw;
44005b261ecSmrg    winRec->height = d->height + 2*bw;
44105b261ecSmrg    winRec->borderWidth = bw;
44205b261ecSmrg
44305b261ecSmrg#ifdef ROOTLESS_TRACK_DAMAGE
44405b261ecSmrg    REGION_NULL(pScreen, &winRec->damage);
44505b261ecSmrg#endif
44605b261ecSmrg}
44705b261ecSmrg
44805b261ecSmrg
4494642e01fSmrgBool
4504642e01fSmrgRootlessColormapCallback (void *data, int first_color, int n_colors, uint32_t *colors)
4514642e01fSmrg{
4524642e01fSmrg    return (RootlessResolveColormap (data, first_color, n_colors, colors) ? XP_Success : XP_BadMatch);
4534642e01fSmrg}
4544642e01fSmrg
45505b261ecSmrg/*
45605b261ecSmrg * RootlessEnsureFrame
45705b261ecSmrg *  Make sure the given window is framed. If the window doesn't have a
45805b261ecSmrg *  physical window associated with it, attempt to create one. If that
45905b261ecSmrg *  is unsuccessful, return NULL.
46005b261ecSmrg */
46105b261ecSmrgstatic RootlessWindowRec *
46205b261ecSmrgRootlessEnsureFrame(WindowPtr pWin)
46305b261ecSmrg{
46405b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
46505b261ecSmrg    RootlessWindowRec *winRec;
46605b261ecSmrg    RegionRec shape;
46705b261ecSmrg    RegionPtr pShape = NULL;
46805b261ecSmrg
46905b261ecSmrg    if (WINREC(pWin) != NULL)
47005b261ecSmrg        return WINREC(pWin);
47105b261ecSmrg
4724642e01fSmrg    if (!IsTopLevel(pWin) && !IsRoot(pWin))
47305b261ecSmrg        return NULL;
47405b261ecSmrg
47505b261ecSmrg    if (pWin->drawable.class != InputOutput)
47605b261ecSmrg        return NULL;
47705b261ecSmrg
47805b261ecSmrg    winRec = xalloc(sizeof(RootlessWindowRec));
47905b261ecSmrg
48005b261ecSmrg    if (!winRec)
48105b261ecSmrg        return NULL;
48205b261ecSmrg
48305b261ecSmrg    RootlessInitializeFrame(pWin, winRec);
48405b261ecSmrg
48505b261ecSmrg    winRec->is_drawing = FALSE;
48605b261ecSmrg    winRec->is_reorder_pending = FALSE;
48705b261ecSmrg    winRec->pixmap = NULL;
48805b261ecSmrg    winRec->wid = NULL;
48905b261ecSmrg
4904642e01fSmrg    SETWINREC(pWin, winRec);
49105b261ecSmrg
49205b261ecSmrg    // Set the frame's shape if the window is shaped
49305b261ecSmrg    if (RootlessGetShape(pWin, &shape))
49405b261ecSmrg        pShape = &shape;
49505b261ecSmrg
49605b261ecSmrg    RL_DEBUG_MSG("creating frame ");
49705b261ecSmrg
49805b261ecSmrg    if (!SCREENREC(pScreen)->imp->CreateFrame(winRec, pScreen,
49905b261ecSmrg                                              winRec->x + SCREEN_TO_GLOBAL_X,
50005b261ecSmrg                                              winRec->y + SCREEN_TO_GLOBAL_Y,
50105b261ecSmrg                                              pShape))
50205b261ecSmrg    {
50305b261ecSmrg        RL_DEBUG_MSG("implementation failed to create frame!\n");
50405b261ecSmrg        xfree(winRec);
5054642e01fSmrg        SETWINREC(pWin, NULL);
50605b261ecSmrg        return NULL;
50705b261ecSmrg    }
50805b261ecSmrg
5094642e01fSmrg    if (pWin->drawable.depth == 8)
5104642e01fSmrg      RootlessFlushWindowColormap(pWin);
5114642e01fSmrg
51205b261ecSmrg    if (pShape != NULL)
51305b261ecSmrg        REGION_UNINIT(pScreen, &shape);
51405b261ecSmrg
51505b261ecSmrg    return winRec;
51605b261ecSmrg}
51705b261ecSmrg
51805b261ecSmrg
51905b261ecSmrg/*
52005b261ecSmrg * RootlessRealizeWindow
52105b261ecSmrg *  The frame is usually created here and not in CreateWindow so that
52205b261ecSmrg *  windows do not eat memory until they are realized.
52305b261ecSmrg */
52405b261ecSmrgBool
52505b261ecSmrgRootlessRealizeWindow(WindowPtr pWin)
52605b261ecSmrg{
52705b261ecSmrg    Bool result;
52805b261ecSmrg    RegionRec saveRoot;
52905b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
53005b261ecSmrg
53105b261ecSmrg    RL_DEBUG_MSG("realizewindow start (win 0x%x) ", pWin);
53205b261ecSmrg
53305b261ecSmrg    if ((IsTopLevel(pWin) && pWin->drawable.class == InputOutput)) {
53405b261ecSmrg        RootlessWindowRec *winRec;
53505b261ecSmrg
53605b261ecSmrg        winRec = RootlessEnsureFrame(pWin);
53705b261ecSmrg        if (winRec == NULL)
53805b261ecSmrg            return FALSE;
53905b261ecSmrg
54005b261ecSmrg        winRec->is_reorder_pending = TRUE;
54105b261ecSmrg
54205b261ecSmrg        RL_DEBUG_MSG("Top level window ");
54305b261ecSmrg
54405b261ecSmrg        // Disallow ParentRelative background state on top-level windows.
54505b261ecSmrg        // This might have been set before the window was mapped.
54605b261ecSmrg        if (pWin->backgroundState == ParentRelative) {
54705b261ecSmrg            XID pixel = 0;
54805b261ecSmrg            ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
54905b261ecSmrg        }
55005b261ecSmrg    }
55105b261ecSmrg
55205b261ecSmrg    if (!IsRoot(pWin)) HUGE_ROOT(pWin);
55305b261ecSmrg    SCREEN_UNWRAP(pScreen, RealizeWindow);
55405b261ecSmrg    result = pScreen->RealizeWindow(pWin);
55505b261ecSmrg    SCREEN_WRAP(pScreen, RealizeWindow);
55605b261ecSmrg    if (!IsRoot(pWin)) NORMAL_ROOT(pWin);
55705b261ecSmrg
55805b261ecSmrg    RL_DEBUG_MSG("realizewindow end\n");
55905b261ecSmrg    return result;
56005b261ecSmrg}
56105b261ecSmrg
56205b261ecSmrg
56305b261ecSmrg/*
56405b261ecSmrg * RootlessFrameForWindow
56505b261ecSmrg *  Returns the frame ID for the physical window displaying the given window.
56605b261ecSmrg *  If CREATE is true and the window has no frame, attempt to create one.
56705b261ecSmrg */
56805b261ecSmrgRootlessFrameID
56905b261ecSmrgRootlessFrameForWindow(WindowPtr pWin, Bool create)
57005b261ecSmrg{
57105b261ecSmrg    WindowPtr pTopWin;
57205b261ecSmrg    RootlessWindowRec *winRec;
57305b261ecSmrg
57405b261ecSmrg    pTopWin = TopLevelParent(pWin);
57505b261ecSmrg    if (pTopWin == NULL)
57605b261ecSmrg        return NULL;
57705b261ecSmrg
57805b261ecSmrg    winRec = WINREC(pTopWin);
57905b261ecSmrg
58005b261ecSmrg    if (winRec == NULL && create && pWin->drawable.class == InputOutput) {
58105b261ecSmrg        winRec = RootlessEnsureFrame(pTopWin);
58205b261ecSmrg    }
58305b261ecSmrg
58405b261ecSmrg    if (winRec == NULL)
58505b261ecSmrg        return NULL;
58605b261ecSmrg
58705b261ecSmrg    return winRec->wid;
58805b261ecSmrg}
58905b261ecSmrg
59005b261ecSmrg
59105b261ecSmrg/*
59205b261ecSmrg * RootlessUnrealizeWindow
59305b261ecSmrg *  Unmap the physical window.
59405b261ecSmrg */
59505b261ecSmrgBool
59605b261ecSmrgRootlessUnrealizeWindow(WindowPtr pWin)
59705b261ecSmrg{
59805b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
59905b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
60005b261ecSmrg    Bool result;
60105b261ecSmrg
60205b261ecSmrg    RL_DEBUG_MSG("unrealizewindow start ");
60305b261ecSmrg
60405b261ecSmrg    if (winRec) {
60505b261ecSmrg        RootlessStopDrawing(pWin, FALSE);
60605b261ecSmrg
60705b261ecSmrg        SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid);
60805b261ecSmrg
60905b261ecSmrg        winRec->is_reorder_pending = FALSE;
61005b261ecSmrg    }
61105b261ecSmrg
61205b261ecSmrg    SCREEN_UNWRAP(pScreen, UnrealizeWindow);
61305b261ecSmrg    result = pScreen->UnrealizeWindow(pWin);
61405b261ecSmrg    SCREEN_WRAP(pScreen, UnrealizeWindow);
61505b261ecSmrg
61605b261ecSmrg    RL_DEBUG_MSG("unrealizewindow end\n");
61705b261ecSmrg    return result;
61805b261ecSmrg}
61905b261ecSmrg
62005b261ecSmrg
62105b261ecSmrg/*
62205b261ecSmrg * RootlessReorderWindow
62305b261ecSmrg *  Reorder the frame associated with the given window so that it's
62405b261ecSmrg *  physically above the window below it in the X stacking order.
62505b261ecSmrg */
62605b261ecSmrgvoid
62705b261ecSmrgRootlessReorderWindow(WindowPtr pWin)
62805b261ecSmrg{
62905b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
63005b261ecSmrg
6314642e01fSmrg    if (pWin->realized && winRec != NULL && !winRec->is_reorder_pending && !windows_hidden) {
63205b261ecSmrg        WindowPtr newPrevW;
63305b261ecSmrg        RootlessWindowRec *newPrev;
63405b261ecSmrg        RootlessFrameID newPrevID;
63505b261ecSmrg        ScreenPtr pScreen = pWin->drawable.pScreen;
63605b261ecSmrg
63705b261ecSmrg        /* Check if the implementation wants the frame to not be reordered
63805b261ecSmrg           even though the X11 window is restacked. This can be useful if
63905b261ecSmrg           frames are ordered-in with animation so that the reordering is not
64005b261ecSmrg           done until the animation is complete. */
64105b261ecSmrg        if (SCREENREC(pScreen)->imp->DoReorderWindow) {
64205b261ecSmrg            if (!SCREENREC(pScreen)->imp->DoReorderWindow(winRec))
64305b261ecSmrg                return;
64405b261ecSmrg        }
64505b261ecSmrg
64605b261ecSmrg        RootlessStopDrawing(pWin, FALSE);
64705b261ecSmrg
64805b261ecSmrg        /* Find the next window above this one that has a mapped frame. */
64905b261ecSmrg
65005b261ecSmrg        newPrevW = pWin->prevSib;
65105b261ecSmrg        while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized))
65205b261ecSmrg            newPrevW = newPrevW->prevSib;
65305b261ecSmrg
65405b261ecSmrg        newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL;
65505b261ecSmrg        newPrevID = newPrev != NULL ? newPrev->wid : 0;
65605b261ecSmrg
65705b261ecSmrg        /* If it exists, reorder the frame above us first. */
65805b261ecSmrg
65905b261ecSmrg        if (newPrev && newPrev->is_reorder_pending) {
66005b261ecSmrg            newPrev->is_reorder_pending = FALSE;
66105b261ecSmrg            RootlessReorderWindow(newPrevW);
66205b261ecSmrg        }
66305b261ecSmrg
66405b261ecSmrg        SCREENREC(pScreen)->imp->RestackFrame(winRec->wid, newPrevID);
66505b261ecSmrg    }
66605b261ecSmrg}
66705b261ecSmrg
66805b261ecSmrg
66905b261ecSmrg/*
67005b261ecSmrg * RootlessRestackWindow
67105b261ecSmrg *  This is a hook for when DIX changes the window stacking order.
67205b261ecSmrg *  The window has already been inserted into its new position in the
67305b261ecSmrg *  DIX window stack. We need to change the order of the physical
67405b261ecSmrg *  window to match.
67505b261ecSmrg */
67605b261ecSmrgvoid
67705b261ecSmrgRootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib)
67805b261ecSmrg{
67905b261ecSmrg    RegionRec saveRoot;
68005b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
68105b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
68205b261ecSmrg
68305b261ecSmrg    RL_DEBUG_MSG("restackwindow start ");
68405b261ecSmrg    if (winRec)
68505b261ecSmrg        RL_DEBUG_MSG("restack top level \n");
68605b261ecSmrg
68705b261ecSmrg    HUGE_ROOT(pWin);
68805b261ecSmrg    SCREEN_UNWRAP(pScreen, RestackWindow);
68905b261ecSmrg
69005b261ecSmrg    if (pScreen->RestackWindow)
69105b261ecSmrg        pScreen->RestackWindow(pWin, pOldNextSib);
69205b261ecSmrg
69305b261ecSmrg    SCREEN_WRAP(pScreen, RestackWindow);
69405b261ecSmrg    NORMAL_ROOT(pWin);
69505b261ecSmrg
69605b261ecSmrg    if (winRec && pWin->viewable) {
69705b261ecSmrg        RootlessReorderWindow(pWin);
69805b261ecSmrg    }
69905b261ecSmrg
70005b261ecSmrg    RL_DEBUG_MSG("restackwindow end\n");
70105b261ecSmrg}
70205b261ecSmrg
70305b261ecSmrg/*
70405b261ecSmrg * Specialized window copy procedures
70505b261ecSmrg */
70605b261ecSmrg
70705b261ecSmrg// Globals needed during window resize and move.
70805b261ecSmrgstatic pointer gResizeDeathBits = NULL;
70905b261ecSmrgstatic int gResizeDeathCount = 0;
71005b261ecSmrgstatic PixmapPtr gResizeDeathPix[2] = {NULL, NULL};
71105b261ecSmrgstatic BoxRec gResizeDeathBounds[2];
71205b261ecSmrgstatic CopyWindowProcPtr gResizeOldCopyWindowProc = NULL;
71305b261ecSmrg
71405b261ecSmrg/*
71505b261ecSmrg * RootlessNoCopyWindow
71605b261ecSmrg *  CopyWindow() that doesn't do anything. For MoveWindow() of
71705b261ecSmrg *  top-level windows.
71805b261ecSmrg */
71905b261ecSmrgstatic void
72005b261ecSmrgRootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
72105b261ecSmrg                     RegionPtr prgnSrc)
72205b261ecSmrg{
72305b261ecSmrg    // some code expects the region to be translated
72405b261ecSmrg    int dx = ptOldOrg.x - pWin->drawable.x;
72505b261ecSmrg    int dy = ptOldOrg.y - pWin->drawable.y;
72605b261ecSmrg
72705b261ecSmrg    RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW ");
72805b261ecSmrg
72905b261ecSmrg    REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
73005b261ecSmrg}
73105b261ecSmrg
73205b261ecSmrg
73305b261ecSmrg/*
73405b261ecSmrg * RootlessResizeCopyWindow
73505b261ecSmrg *  CopyWindow used during ResizeWindow for gravity moves. Based on
73605b261ecSmrg *  fbCopyWindow. The original always draws on the root pixmap, which
73705b261ecSmrg *  we don't have. Instead, draw on the parent window's pixmap.
73805b261ecSmrg *  Resize version: the old location's pixels are in gResizeCopyWindowSource.
73905b261ecSmrg */
74005b261ecSmrgstatic void
74105b261ecSmrgRootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
74205b261ecSmrg                         RegionPtr prgnSrc)
74305b261ecSmrg{
74405b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
74505b261ecSmrg    RegionRec   rgnDst;
74605b261ecSmrg    int         dx, dy;
74705b261ecSmrg
74805b261ecSmrg    RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin);
74905b261ecSmrg
75005b261ecSmrg    /* Don't unwrap pScreen->CopyWindow.
75105b261ecSmrg       The bogus rewrap with RootlessCopyWindow causes a crash if
75205b261ecSmrg       CopyWindow is called again during the same resize. */
75305b261ecSmrg
75405b261ecSmrg    if (gResizeDeathCount == 0)
75505b261ecSmrg        return;
75605b261ecSmrg
75705b261ecSmrg    RootlessStartDrawing(pWin);
75805b261ecSmrg
75905b261ecSmrg    dx = ptOldOrg.x - pWin->drawable.x;
76005b261ecSmrg    dy = ptOldOrg.y - pWin->drawable.y;
76105b261ecSmrg    REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy);
76205b261ecSmrg    REGION_NULL(pScreen, &rgnDst);
76305b261ecSmrg    REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
76405b261ecSmrg
76505b261ecSmrg    if (gResizeDeathCount == 1) {
76605b261ecSmrg        /* Simple case, we only have a single source pixmap. */
76705b261ecSmrg
76805b261ecSmrg        fbCopyRegion(&gResizeDeathPix[0]->drawable,
76905b261ecSmrg                     &pScreen->GetWindowPixmap(pWin)->drawable, 0,
77005b261ecSmrg                     &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
77105b261ecSmrg    }
77205b261ecSmrg    else {
77305b261ecSmrg        int i;
77405b261ecSmrg        RegionRec clip, clipped;
77505b261ecSmrg
77605b261ecSmrg        /* More complex case, N source pixmaps (usually two). So we
77705b261ecSmrg           intersect the destination with each source and copy those bits. */
77805b261ecSmrg
77905b261ecSmrg        for (i = 0; i < gResizeDeathCount; i++) {
78005b261ecSmrg            REGION_INIT(pScreen, &clip, gResizeDeathBounds + 0, 1);
78105b261ecSmrg            REGION_NULL(pScreen, &clipped);
78205b261ecSmrg            REGION_INTERSECT(pScreen, &rgnDst, &clip, &clipped);
78305b261ecSmrg
78405b261ecSmrg            fbCopyRegion(&gResizeDeathPix[i]->drawable,
78505b261ecSmrg                         &pScreen->GetWindowPixmap(pWin)->drawable, 0,
78605b261ecSmrg                         &clipped, dx, dy, fbCopyWindowProc, 0, 0);
78705b261ecSmrg
78805b261ecSmrg            REGION_UNINIT(pScreen, &clipped);
78905b261ecSmrg            REGION_UNINIT(pScreen, &clip);
79005b261ecSmrg        }
79105b261ecSmrg    }
79205b261ecSmrg
79305b261ecSmrg    /* Don't update - resize will update everything */
79405b261ecSmrg    REGION_UNINIT(pScreen, &rgnDst);
79505b261ecSmrg
79605b261ecSmrg    fbValidateDrawable(&pWin->drawable);
79705b261ecSmrg
79805b261ecSmrg    RL_DEBUG_MSG("resizecopywindowFB end\n");
79905b261ecSmrg}
80005b261ecSmrg
80105b261ecSmrg
80205b261ecSmrg/*
80305b261ecSmrg * RootlessCopyWindow
80405b261ecSmrg *  Update *new* location of window. Old location is redrawn with
8054642e01fSmrg *  miPaintWindow. Cloned from fbCopyWindow.
80605b261ecSmrg *  The original always draws on the root pixmap, which we don't have.
80705b261ecSmrg *  Instead, draw on the parent window's pixmap.
80805b261ecSmrg */
80905b261ecSmrgvoid
81005b261ecSmrgRootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
81105b261ecSmrg{
81205b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
81305b261ecSmrg    RegionRec   rgnDst;
81405b261ecSmrg    int         dx, dy;
81505b261ecSmrg    BoxPtr extents;
81605b261ecSmrg    int area;
81705b261ecSmrg
81805b261ecSmrg    RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin);
81905b261ecSmrg
82005b261ecSmrg    SCREEN_UNWRAP(pScreen, CopyWindow);
82105b261ecSmrg
82205b261ecSmrg    dx = ptOldOrg.x - pWin->drawable.x;
82305b261ecSmrg    dy = ptOldOrg.y - pWin->drawable.y;
82405b261ecSmrg    REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy);
82505b261ecSmrg
82605b261ecSmrg    REGION_NULL(pScreen, &rgnDst);
82705b261ecSmrg    REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
82805b261ecSmrg
82905b261ecSmrg    extents = REGION_EXTENTS(pScreen, &rgnDst);
83005b261ecSmrg    area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1);
83105b261ecSmrg
83205b261ecSmrg    /* If the area exceeds threshold, use the implementation's
83305b261ecSmrg       accelerated version. */
83405b261ecSmrg    if (area > rootless_CopyWindow_threshold &&
83505b261ecSmrg        SCREENREC(pScreen)->imp->CopyWindow)
83605b261ecSmrg    {
83705b261ecSmrg        RootlessWindowRec *winRec;
83805b261ecSmrg        WindowPtr top;
83905b261ecSmrg
84005b261ecSmrg        top = TopLevelParent(pWin);
84105b261ecSmrg        if (top == NULL) {
84205b261ecSmrg            RL_DEBUG_MSG("no parent\n");
8434642e01fSmrg            goto out;
84405b261ecSmrg        }
84505b261ecSmrg
84605b261ecSmrg        winRec = WINREC(top);
84705b261ecSmrg        if (winRec == NULL) {
84805b261ecSmrg            RL_DEBUG_MSG("not framed\n");
8494642e01fSmrg            goto out;
85005b261ecSmrg        }
85105b261ecSmrg
85205b261ecSmrg        /* Move region to window local coords */
85305b261ecSmrg        REGION_TRANSLATE(pScreen, &rgnDst, -winRec->x, -winRec->y);
85405b261ecSmrg
85505b261ecSmrg        RootlessStopDrawing(pWin, FALSE);
85605b261ecSmrg
85705b261ecSmrg        SCREENREC(pScreen)->imp->CopyWindow(winRec->wid,
85805b261ecSmrg                                            REGION_NUM_RECTS(&rgnDst),
85905b261ecSmrg                                            REGION_RECTS(&rgnDst),
86005b261ecSmrg                                            dx, dy);
86105b261ecSmrg    }
86205b261ecSmrg    else {
86305b261ecSmrg        RootlessStartDrawing(pWin);
86405b261ecSmrg
86505b261ecSmrg        fbCopyRegion((DrawablePtr) pWin, (DrawablePtr) pWin,
86605b261ecSmrg                     0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
86705b261ecSmrg
86805b261ecSmrg        /* prgnSrc has been translated to dst position */
86905b261ecSmrg        RootlessDamageRegion(pWin, prgnSrc);
87005b261ecSmrg    }
87105b261ecSmrg
8724642e01fSmrgout:
87305b261ecSmrg    REGION_UNINIT(pScreen, &rgnDst);
87405b261ecSmrg    fbValidateDrawable(&pWin->drawable);
87505b261ecSmrg
87605b261ecSmrg    SCREEN_WRAP(pScreen, CopyWindow);
87705b261ecSmrg
87805b261ecSmrg    RL_DEBUG_MSG("copywindowFB end\n");
87905b261ecSmrg}
88005b261ecSmrg
88105b261ecSmrg
88205b261ecSmrg/*
88305b261ecSmrg * Window resize procedures
88405b261ecSmrg */
88505b261ecSmrg
88605b261ecSmrgenum {
88705b261ecSmrg    WIDTH_SMALLER = 1,
88805b261ecSmrg    HEIGHT_SMALLER = 2,
88905b261ecSmrg};
89005b261ecSmrg
89105b261ecSmrg
89205b261ecSmrg/*
89305b261ecSmrg * ResizeWeighting
89405b261ecSmrg *  Choose gravity to avoid local copies. Do that by looking for
89505b261ecSmrg *  a corner that doesn't move _relative to the screen_.
89605b261ecSmrg */
89705b261ecSmrgstatic inline unsigned int
89805b261ecSmrgResizeWeighting(int oldX1, int oldY1, int oldX2, int oldY2, int oldBW,
89905b261ecSmrg                int newX1, int newY1, int newX2, int newY2, int newBW)
90005b261ecSmrg{
90105b261ecSmrg#ifdef ROOTLESS_RESIZE_GRAVITY
90205b261ecSmrg    if (newBW != oldBW)
90305b261ecSmrg        return RL_GRAVITY_NONE;
90405b261ecSmrg
90505b261ecSmrg    if (newX1 == oldX1 && newY1 == oldY1)
90605b261ecSmrg        return RL_GRAVITY_NORTH_WEST;
90705b261ecSmrg    else if (newX1 == oldX1 && newY2 == oldY2)
90805b261ecSmrg        return RL_GRAVITY_SOUTH_WEST;
90905b261ecSmrg    else if (newX2 == oldX2 && newY2 == oldY2)
91005b261ecSmrg        return RL_GRAVITY_SOUTH_EAST;
91105b261ecSmrg    else if (newX2 == oldX2 && newY1 == oldY1)
91205b261ecSmrg        return RL_GRAVITY_NORTH_EAST;
91305b261ecSmrg    else
91405b261ecSmrg        return RL_GRAVITY_NONE;
91505b261ecSmrg#else
91605b261ecSmrg    return RL_GRAVITY_NONE;
91705b261ecSmrg#endif
91805b261ecSmrg}
91905b261ecSmrg
92005b261ecSmrg
92105b261ecSmrg/*
92205b261ecSmrg * StartFrameResize
92305b261ecSmrg *  Prepare to resize a top-level window. The old window's pixels are
92405b261ecSmrg *  saved and the implementation is told to change the window size.
92505b261ecSmrg *  (x,y,w,h) is outer frame of window (outside border)
92605b261ecSmrg */
92705b261ecSmrgstatic Bool
92805b261ecSmrgStartFrameResize(WindowPtr pWin, Bool gravity,
92905b261ecSmrg                 int oldX, int oldY, int oldW, int oldH, int oldBW,
93005b261ecSmrg                 int newX, int newY, int newW, int newH, int newBW)
93105b261ecSmrg{
93205b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
93305b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
93405b261ecSmrg    Bool need_window_source = FALSE, resize_after = FALSE;
93505b261ecSmrg
93605b261ecSmrg    BoxRec rect;
93705b261ecSmrg    int oldX2, newX2;
93805b261ecSmrg    int oldY2, newY2;
93905b261ecSmrg    unsigned int weight;
94005b261ecSmrg
94105b261ecSmrg    oldX2 = oldX + oldW, newX2 = newX + newW;
94205b261ecSmrg    oldY2 = oldY + oldH, newY2 = newY + newH;
94305b261ecSmrg
94405b261ecSmrg    /* Decide which resize weighting to use */
94505b261ecSmrg    weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW,
94605b261ecSmrg                             newX, newY, newW, newH, newBW);
94705b261ecSmrg
94805b261ecSmrg    /* Compute intersection between old and new rects */
94905b261ecSmrg    rect.x1 = max(oldX, newX);
95005b261ecSmrg    rect.y1 = max(oldY, newY);
95105b261ecSmrg    rect.x2 = min(oldX2, newX2);
95205b261ecSmrg    rect.y2 = min(oldY2, newY2);
95305b261ecSmrg
95405b261ecSmrg    RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity);
95505b261ecSmrg    RL_DEBUG_MSG("%d %d %d %d %d   %d %d %d %d %d\n",
95605b261ecSmrg                 oldX, oldY, oldW, oldH, oldBW,
95705b261ecSmrg                 newX, newY, newW, newH, newBW);
95805b261ecSmrg
95905b261ecSmrg    RootlessRedisplay(pWin);
96005b261ecSmrg
96105b261ecSmrg    /* If gravity is true, then we need to have a way of recovering all
96205b261ecSmrg       the original bits in the window for when X rearranges the contents
96305b261ecSmrg       based on the various gravity settings. The obvious way is to just
96405b261ecSmrg       snapshot the entire backing store before resizing it, but that
96505b261ecSmrg       it slow on large windows.
96605b261ecSmrg
96705b261ecSmrg       So the optimization here is to use the implementation's resize
96805b261ecSmrg       weighting options (if available) to allow us to reason about what
96905b261ecSmrg       is left in the backing store after the resize. We can then only
97005b261ecSmrg       copy what won't be there after the resize, and do a two-stage copy
97105b261ecSmrg       operation.
97205b261ecSmrg
97305b261ecSmrg       Most of these optimizations are only applied when the top-left
97405b261ecSmrg       corner of the window is fixed, since that's the common case. They
97505b261ecSmrg       could probably be extended with some thought. */
97605b261ecSmrg
97705b261ecSmrg    gResizeDeathCount = 0;
97805b261ecSmrg
97905b261ecSmrg    if (gravity && weight == RL_GRAVITY_NORTH_WEST) {
98005b261ecSmrg        unsigned int code = 0;
98105b261ecSmrg
98205b261ecSmrg        /* Top left corner is anchored. We never need to copy the
98305b261ecSmrg           entire window. */
98405b261ecSmrg
98505b261ecSmrg        need_window_source = TRUE;
98605b261ecSmrg
98705b261ecSmrg        /* These comparisons were chosen to avoid setting bits when the sizes
98805b261ecSmrg        are the same. (So the fastest case automatically gets taken when
98905b261ecSmrg        dimensions are unchanging.) */
99005b261ecSmrg
99105b261ecSmrg        if (newW < oldW)
99205b261ecSmrg            code |= WIDTH_SMALLER;
99305b261ecSmrg        if (newH < oldH)
99405b261ecSmrg            code |= HEIGHT_SMALLER;
99505b261ecSmrg
99605b261ecSmrg        if (((code ^ (code >> 1)) & 1) == 0) {
99705b261ecSmrg            /* Both dimensions are either getting larger, or both
99805b261ecSmrg               are getting smaller. No need to copy anything. */
99905b261ecSmrg
100005b261ecSmrg            if (code == (WIDTH_SMALLER | HEIGHT_SMALLER)) {
100105b261ecSmrg                /* Since the window is getting smaller, we can do gravity
100205b261ecSmrg                   repair on it with it's current size, then resize it
100305b261ecSmrg                   afterwards. */
100405b261ecSmrg
100505b261ecSmrg                resize_after = TRUE;
100605b261ecSmrg            }
100705b261ecSmrg
100805b261ecSmrg            gResizeDeathCount = 1;
100905b261ecSmrg        }
101005b261ecSmrg        else {
101105b261ecSmrg            unsigned int copy_rowbytes, Bpp;
101205b261ecSmrg            unsigned int copy_rect_width, copy_rect_height;
101305b261ecSmrg            BoxRec copy_rect;
101405b261ecSmrg
101505b261ecSmrg            /* We can get away with a partial copy. 'rect' is the
101605b261ecSmrg               intersection between old and new bounds, so copy
101705b261ecSmrg               everything to the right of or below the intersection. */
101805b261ecSmrg
101905b261ecSmrg            RootlessStartDrawing(pWin);
102005b261ecSmrg
102105b261ecSmrg            if (code == WIDTH_SMALLER) {
102205b261ecSmrg                copy_rect.x1 = rect.x2;
102305b261ecSmrg                copy_rect.y1 = rect.y1;
102405b261ecSmrg                copy_rect.x2 = oldX2;
102505b261ecSmrg                copy_rect.y2 = oldY2;
102605b261ecSmrg            }
102705b261ecSmrg            else if (code == HEIGHT_SMALLER) {
102805b261ecSmrg                copy_rect.x1 = rect.x1;
102905b261ecSmrg                copy_rect.y1 = rect.y2;
103005b261ecSmrg                copy_rect.x2 = oldX2;
103105b261ecSmrg                copy_rect.y2 = oldY2;
103205b261ecSmrg            }
103305b261ecSmrg            else
103405b261ecSmrg                abort();
103505b261ecSmrg
103605b261ecSmrg            Bpp = winRec->win->drawable.bitsPerPixel / 8;
103705b261ecSmrg            copy_rect_width = copy_rect.x2 - copy_rect.x1;
103805b261ecSmrg            copy_rect_height = copy_rect.y2 - copy_rect.y1;
103905b261ecSmrg            copy_rowbytes = ((copy_rect_width * Bpp) + 31) & ~31;
104005b261ecSmrg            gResizeDeathBits = xalloc(copy_rowbytes
104105b261ecSmrg                                      * copy_rect_height);
104205b261ecSmrg
104305b261ecSmrg            if (copy_rect_width * copy_rect_height >
104405b261ecSmrg                        rootless_CopyBytes_threshold &&
104505b261ecSmrg                SCREENREC(pScreen)->imp->CopyBytes)
104605b261ecSmrg            {
104705b261ecSmrg                SCREENREC(pScreen)->imp->CopyBytes(
104805b261ecSmrg                    copy_rect_width * Bpp, copy_rect_height,
104905b261ecSmrg                    ((char *) winRec->pixelData)
105005b261ecSmrg                    + ((copy_rect.y1 - oldY) * winRec->bytesPerRow)
105105b261ecSmrg                    + (copy_rect.x1 - oldX) * Bpp, winRec->bytesPerRow,
105205b261ecSmrg                    gResizeDeathBits, copy_rowbytes);
105305b261ecSmrg            } else {
105405b261ecSmrg                fbBlt((FbBits *) (winRec->pixelData
105505b261ecSmrg                      + ((copy_rect.y1 - oldY) * winRec->bytesPerRow)
105605b261ecSmrg                      + (copy_rect.x1 - oldX) * Bpp),
105705b261ecSmrg                      winRec->bytesPerRow / sizeof(FbBits), 0,
105805b261ecSmrg                      (FbBits *) gResizeDeathBits,
105905b261ecSmrg                      copy_rowbytes / sizeof(FbBits), 0,
106005b261ecSmrg                      copy_rect_width * Bpp, copy_rect_height,
106105b261ecSmrg                      GXcopy, FB_ALLONES, Bpp, 0, 0);
106205b261ecSmrg            }
106305b261ecSmrg
106405b261ecSmrg            gResizeDeathBounds[1] = copy_rect;
106505b261ecSmrg            gResizeDeathPix[1]
106605b261ecSmrg                = GetScratchPixmapHeader(pScreen, copy_rect_width,
106705b261ecSmrg                                         copy_rect_height,
106805b261ecSmrg                                         winRec->win->drawable.depth,
106905b261ecSmrg                                         winRec->win->drawable.bitsPerPixel,
107005b261ecSmrg                                         winRec->bytesPerRow,
107105b261ecSmrg                                         (void *) gResizeDeathBits);
107205b261ecSmrg
107305b261ecSmrg            SetPixmapBaseToScreen(gResizeDeathPix[1],
107405b261ecSmrg                                  copy_rect.x1, copy_rect.y1);
107505b261ecSmrg
107605b261ecSmrg            gResizeDeathCount = 2;
107705b261ecSmrg        }
107805b261ecSmrg    }
107905b261ecSmrg    else if (gravity) {
108005b261ecSmrg        /* The general case. Just copy everything. */
108105b261ecSmrg
108205b261ecSmrg        RootlessStartDrawing(pWin);
108305b261ecSmrg
108405b261ecSmrg        gResizeDeathBits = xalloc(winRec->bytesPerRow * winRec->height);
108505b261ecSmrg
108605b261ecSmrg        memcpy(gResizeDeathBits, winRec->pixelData,
108705b261ecSmrg               winRec->bytesPerRow * winRec->height);
108805b261ecSmrg
108905b261ecSmrg        gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
109005b261ecSmrg        gResizeDeathPix[0]
109105b261ecSmrg            = GetScratchPixmapHeader(pScreen, winRec->width,
109205b261ecSmrg                                     winRec->height,
109305b261ecSmrg                                     winRec->win->drawable.depth,
109405b261ecSmrg                                     winRec->win->drawable.bitsPerPixel,
109505b261ecSmrg                                     winRec->bytesPerRow,
109605b261ecSmrg                                     (void *) gResizeDeathBits);
109705b261ecSmrg
109805b261ecSmrg        SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY);
109905b261ecSmrg        gResizeDeathCount = 1;
110005b261ecSmrg    }
110105b261ecSmrg
110205b261ecSmrg    RootlessStopDrawing(pWin, FALSE);
110305b261ecSmrg
110405b261ecSmrg    winRec->x = newX;
110505b261ecSmrg    winRec->y = newY;
110605b261ecSmrg    winRec->width = newW;
110705b261ecSmrg    winRec->height = newH;
110805b261ecSmrg    winRec->borderWidth = newBW;
110905b261ecSmrg
111005b261ecSmrg    /* Unless both dimensions are getting smaller, Resize the frame
111105b261ecSmrg       before doing gravity repair */
111205b261ecSmrg
111305b261ecSmrg    if (!resize_after) {
111405b261ecSmrg        SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
111505b261ecSmrg                                             newX + SCREEN_TO_GLOBAL_X,
111605b261ecSmrg                                             newY + SCREEN_TO_GLOBAL_Y,
111705b261ecSmrg                                             newW, newH, weight);
111805b261ecSmrg    }
111905b261ecSmrg
112005b261ecSmrg    RootlessStartDrawing(pWin);
112105b261ecSmrg
112205b261ecSmrg    /* If necessary, create a source pixmap pointing at the current
112305b261ecSmrg       window bits. */
112405b261ecSmrg
112505b261ecSmrg    if (need_window_source) {
112605b261ecSmrg        gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
112705b261ecSmrg        gResizeDeathPix[0]
112805b261ecSmrg            = GetScratchPixmapHeader(pScreen, oldW, oldH,
112905b261ecSmrg                                     winRec->win->drawable.depth,
113005b261ecSmrg                                     winRec->win->drawable.bitsPerPixel,
113105b261ecSmrg                                     winRec->bytesPerRow, winRec->pixelData);
113205b261ecSmrg
113305b261ecSmrg        SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY);
113405b261ecSmrg    }
113505b261ecSmrg
113605b261ecSmrg    /* Use custom CopyWindow when moving gravity bits around
113705b261ecSmrg       ResizeWindow assumes the old window contents are in the same
113805b261ecSmrg       pixmap, but here they're in deathPix instead. */
113905b261ecSmrg
114005b261ecSmrg    if (gravity) {
114105b261ecSmrg        gResizeOldCopyWindowProc = pScreen->CopyWindow;
114205b261ecSmrg        pScreen->CopyWindow = RootlessResizeCopyWindow;
114305b261ecSmrg    }
114405b261ecSmrg
114505b261ecSmrg    /* If we can't rely on the window server preserving the bits we
114605b261ecSmrg       need in the position we need, copy the pixels in the
114705b261ecSmrg       intersection from src to dst. ResizeWindow assumes these pixels
114805b261ecSmrg       are already present when making gravity adjustments. pWin
114905b261ecSmrg       currently has new-sized pixmap but is in old position.
115005b261ecSmrg
115105b261ecSmrg       FIXME: border width change! (?) */
115205b261ecSmrg
115305b261ecSmrg    if (gravity && weight == RL_GRAVITY_NONE) {
115405b261ecSmrg        PixmapPtr src, dst;
115505b261ecSmrg
115605b261ecSmrg        assert(gResizeDeathCount == 1);
115705b261ecSmrg
115805b261ecSmrg        src = gResizeDeathPix[0];
115905b261ecSmrg        dst = pScreen->GetWindowPixmap(pWin);
116005b261ecSmrg
116105b261ecSmrg        RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n",
116205b261ecSmrg                     rect.x1, rect.y1, rect.x2, rect.y2);
116305b261ecSmrg
116405b261ecSmrg        /* rect is the intersection of the old location and new location */
116505b261ecSmrg        if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL) {
116605b261ecSmrg            /* The window drawable still has the old frame position, which
116705b261ecSmrg               means that DST doesn't actually point at the origin of our
116805b261ecSmrg               physical backing store when adjusted by the drawable.x,y
116905b261ecSmrg               position. So sneakily adjust it temporarily while copying.. */
117005b261ecSmrg
117105b261ecSmrg            ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData;
117205b261ecSmrg            SetPixmapBaseToScreen(dst, newX, newY);
117305b261ecSmrg
117405b261ecSmrg            fbCopyWindowProc(&src->drawable, &dst->drawable, NULL,
117505b261ecSmrg                             &rect, 1, 0, 0, FALSE, FALSE, 0, 0);
117605b261ecSmrg
117705b261ecSmrg            ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData;
117805b261ecSmrg            SetPixmapBaseToScreen(dst, oldX, oldY);
117905b261ecSmrg        }
118005b261ecSmrg    }
118105b261ecSmrg
118205b261ecSmrg    return resize_after;
118305b261ecSmrg}
118405b261ecSmrg
118505b261ecSmrg
118605b261ecSmrgstatic void
118705b261ecSmrgFinishFrameResize(WindowPtr pWin, Bool gravity, int oldX, int oldY,
118805b261ecSmrg                  unsigned int oldW, unsigned int oldH, unsigned int oldBW,
118905b261ecSmrg                  int newX, int newY, unsigned int newW, unsigned int newH,
119005b261ecSmrg                  unsigned int newBW, Bool resize_now)
119105b261ecSmrg{
119205b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
119305b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
119405b261ecSmrg    int i;
119505b261ecSmrg
119605b261ecSmrg    RootlessStopDrawing(pWin, FALSE);
119705b261ecSmrg
119805b261ecSmrg    if (resize_now) {
119905b261ecSmrg        unsigned int weight;
120005b261ecSmrg
120105b261ecSmrg        /* We didn't resize anything earlier, so do it now, now that
120205b261ecSmrg           we've finished gravitating the bits. */
120305b261ecSmrg
120405b261ecSmrg        weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW,
120505b261ecSmrg                                 newX, newY, newW, newH, newBW);
120605b261ecSmrg
120705b261ecSmrg        SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
120805b261ecSmrg                                             newX + SCREEN_TO_GLOBAL_X,
120905b261ecSmrg                                             newY + SCREEN_TO_GLOBAL_Y,
121005b261ecSmrg                                             newW, newH, weight);
121105b261ecSmrg    }
121205b261ecSmrg
121305b261ecSmrg    /* Redraw everything. FIXME: there must be times when we don't need
121405b261ecSmrg       to do this. Perhaps when top-left weighting and no gravity? */
121505b261ecSmrg
121605b261ecSmrg    RootlessDamageRect(pWin, -newBW, -newBW, newW, newH);
121705b261ecSmrg
121805b261ecSmrg    for (i = 0; i < 2; i++) {
121905b261ecSmrg        if (gResizeDeathPix[i] != NULL) {
122005b261ecSmrg            FreeScratchPixmapHeader(gResizeDeathPix[i]);
122105b261ecSmrg            gResizeDeathPix[i] = NULL;
122205b261ecSmrg        }
122305b261ecSmrg    }
122405b261ecSmrg
122505b261ecSmrg    if (gResizeDeathBits != NULL) {
122605b261ecSmrg        xfree(gResizeDeathBits);
122705b261ecSmrg        gResizeDeathBits = NULL;
122805b261ecSmrg    }
122905b261ecSmrg
123005b261ecSmrg    if (gravity) {
123105b261ecSmrg        pScreen->CopyWindow = gResizeOldCopyWindowProc;
123205b261ecSmrg    }
123305b261ecSmrg}
123405b261ecSmrg
123505b261ecSmrg
123605b261ecSmrg/*
123705b261ecSmrg * RootlessMoveWindow
123805b261ecSmrg *  If kind==VTOther, window border is resizing (and borderWidth is
123905b261ecSmrg *  already changed!!@#$)  This case works like window resize, not move.
124005b261ecSmrg */
124105b261ecSmrgvoid
124205b261ecSmrgRootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
124305b261ecSmrg{
124405b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
124505b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
124605b261ecSmrg    CopyWindowProcPtr oldCopyWindowProc = NULL;
124705b261ecSmrg    int oldX = 0, oldY = 0, newX = 0, newY = 0;
124805b261ecSmrg    unsigned int oldW = 0, oldH = 0, oldBW = 0;
124905b261ecSmrg    unsigned int newW = 0, newH = 0, newBW = 0;
125005b261ecSmrg    Bool resize_after = FALSE;
125105b261ecSmrg    RegionRec saveRoot;
125205b261ecSmrg
125305b261ecSmrg    RL_DEBUG_MSG("movewindow start \n");
125405b261ecSmrg
125505b261ecSmrg    if (winRec) {
125605b261ecSmrg        if (kind == VTMove) {
125705b261ecSmrg            oldX = winRec->x;
125805b261ecSmrg            oldY = winRec->y;
125905b261ecSmrg            RootlessRedisplay(pWin);
126005b261ecSmrg            RootlessStartDrawing(pWin);
126105b261ecSmrg        } else {
126205b261ecSmrg            RL_DEBUG_MSG("movewindow border resizing ");
126305b261ecSmrg
126405b261ecSmrg            oldBW = winRec->borderWidth;
126505b261ecSmrg            oldX = winRec->x;
126605b261ecSmrg            oldY = winRec->y;
126705b261ecSmrg            oldW = winRec->width;
126805b261ecSmrg            oldH = winRec->height;
126905b261ecSmrg
127005b261ecSmrg            newBW = wBorderWidth(pWin);
127105b261ecSmrg            newX = x;
127205b261ecSmrg            newY = y;
127305b261ecSmrg            newW = pWin->drawable.width  + 2*newBW;
127405b261ecSmrg            newH = pWin->drawable.height + 2*newBW;
127505b261ecSmrg
127605b261ecSmrg            resize_after = StartFrameResize(pWin, FALSE,
127705b261ecSmrg                                            oldX, oldY, oldW, oldH, oldBW,
127805b261ecSmrg                                            newX, newY, newW, newH, newBW);
127905b261ecSmrg        }
128005b261ecSmrg    }
128105b261ecSmrg
128205b261ecSmrg    HUGE_ROOT(pWin);
128305b261ecSmrg    SCREEN_UNWRAP(pScreen, MoveWindow);
128405b261ecSmrg
128505b261ecSmrg    if (winRec) {
128605b261ecSmrg        oldCopyWindowProc = pScreen->CopyWindow;
128705b261ecSmrg        pScreen->CopyWindow = RootlessNoCopyWindow;
128805b261ecSmrg    }
128905b261ecSmrg    pScreen->MoveWindow(pWin, x, y, pSib, kind);
129005b261ecSmrg    if (winRec) {
129105b261ecSmrg        pScreen->CopyWindow = oldCopyWindowProc;
129205b261ecSmrg    }
129305b261ecSmrg
129405b261ecSmrg    NORMAL_ROOT(pWin);
129505b261ecSmrg    SCREEN_WRAP(pScreen, MoveWindow);
129605b261ecSmrg
129705b261ecSmrg    if (winRec) {
129805b261ecSmrg        if (kind == VTMove) {
129905b261ecSmrg            winRec->x = x;
130005b261ecSmrg            winRec->y = y;
130105b261ecSmrg            RootlessStopDrawing(pWin, FALSE);
130205b261ecSmrg            SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen,
130305b261ecSmrg                                               x + SCREEN_TO_GLOBAL_X,
130405b261ecSmrg                                               y + SCREEN_TO_GLOBAL_Y);
130505b261ecSmrg        } else {
130605b261ecSmrg            FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
130705b261ecSmrg                              newX, newY, newW, newH, newBW, resize_after);
130805b261ecSmrg        }
130905b261ecSmrg    }
131005b261ecSmrg
131105b261ecSmrg    RL_DEBUG_MSG("movewindow end\n");
131205b261ecSmrg}
131305b261ecSmrg
131405b261ecSmrg
131505b261ecSmrg/*
131605b261ecSmrg * RootlessResizeWindow
131705b261ecSmrg *  Note: (x, y, w, h) as passed to this procedure don't match the frame
131805b261ecSmrg *  definition. (x,y) is corner of very outer edge, *outside* border.
131905b261ecSmrg *  w,h is width and height *inside* border, *ignoring* border width.
132005b261ecSmrg *  The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw)
132105b261ecSmrg *  is total rect and (x+bw, y+bw, w, h) is inner rect.
132205b261ecSmrg */
132305b261ecSmrgvoid
132405b261ecSmrgRootlessResizeWindow(WindowPtr pWin, int x, int y,
132505b261ecSmrg                     unsigned int w, unsigned int h, WindowPtr pSib)
132605b261ecSmrg{
132705b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
132805b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
132905b261ecSmrg    int oldX = 0, oldY = 0, newX = 0, newY = 0;
133005b261ecSmrg    unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0;
133105b261ecSmrg    Bool resize_after = FALSE;
133205b261ecSmrg    RegionRec saveRoot;
133305b261ecSmrg
133405b261ecSmrg    RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin);
13354642e01fSmrg
13364642e01fSmrg    if(pWin->parent) {
13374642e01fSmrg        if (winRec) {
13384642e01fSmrg            oldBW = winRec->borderWidth;
13394642e01fSmrg            oldX = winRec->x;
13404642e01fSmrg            oldY = winRec->y;
13414642e01fSmrg            oldW = winRec->width;
13424642e01fSmrg            oldH = winRec->height;
134305b261ecSmrg
13444642e01fSmrg            newBW = oldBW;
13454642e01fSmrg            newX = x;
13464642e01fSmrg            newY = y;
13474642e01fSmrg            newW = w + 2*newBW;
13484642e01fSmrg            newH = h + 2*newBW;
134905b261ecSmrg
13504642e01fSmrg            resize_after = StartFrameResize(pWin, TRUE,
13514642e01fSmrg                                            oldX, oldY, oldW, oldH, oldBW,
13524642e01fSmrg                                            newX, newY, newW, newH, newBW);
13534642e01fSmrg        }
135405b261ecSmrg
13554642e01fSmrg        HUGE_ROOT(pWin);
13564642e01fSmrg        SCREEN_UNWRAP(pScreen, ResizeWindow);
13574642e01fSmrg        pScreen->ResizeWindow(pWin, x, y, w, h, pSib);
13584642e01fSmrg        SCREEN_WRAP(pScreen, ResizeWindow);
13594642e01fSmrg        NORMAL_ROOT(pWin);
13604642e01fSmrg
13614642e01fSmrg        if (winRec) {
13624642e01fSmrg            FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
13634642e01fSmrg                              newX, newY, newW, newH, newBW, resize_after);
13644642e01fSmrg        }
13654642e01fSmrg    } else {
13664642e01fSmrg        /* Special case for resizing the root window */
13674642e01fSmrg        BoxRec box;
13684642e01fSmrg
13694642e01fSmrg        pWin->drawable.x = x;
13704642e01fSmrg        pWin->drawable.y = y;
13714642e01fSmrg        pWin->drawable.width = w;
13724642e01fSmrg        pWin->drawable.height = h;
13734642e01fSmrg
13744642e01fSmrg        box.x1 = x; box.y1 = y;
13754642e01fSmrg        box.x2 = x + w; box.y2 = y + h;
13764642e01fSmrg        REGION_UNINIT(pScreen, &pWin->winSize);
13774642e01fSmrg        REGION_INIT(pScreen, &pWin->winSize, &box, 1);
13784642e01fSmrg        REGION_COPY(pScreen, &pWin->borderSize, &pWin->winSize);
13794642e01fSmrg        REGION_COPY(pScreen, &pWin->clipList, &pWin->winSize);
13804642e01fSmrg        REGION_COPY(pScreen, &pWin->borderClip, &pWin->winSize);
13814642e01fSmrg
13824642e01fSmrg        miSendExposures(pWin, &pWin->borderClip,
13834642e01fSmrg                        pWin->drawable.x, pWin->drawable.y);
138405b261ecSmrg    }
138505b261ecSmrg
138605b261ecSmrg    RL_DEBUG_MSG("resizewindow end\n");
138705b261ecSmrg}
138805b261ecSmrg
138905b261ecSmrg
139005b261ecSmrg/*
139105b261ecSmrg * RootlessRepositionWindow
139205b261ecSmrg *  Called by the implementation when a window needs to be repositioned to
139305b261ecSmrg *  its correct location on the screen. This routine is typically needed
139405b261ecSmrg *  due to changes in the underlying window system, such as a screen layout
139505b261ecSmrg *  change.
139605b261ecSmrg */
139705b261ecSmrgvoid
139805b261ecSmrgRootlessRepositionWindow(WindowPtr pWin)
139905b261ecSmrg{
140005b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
140105b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
140205b261ecSmrg
140305b261ecSmrg    if (winRec == NULL)
140405b261ecSmrg        return;
140505b261ecSmrg
140605b261ecSmrg    RootlessStopDrawing(pWin, FALSE);
140705b261ecSmrg    SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen,
140805b261ecSmrg                                       winRec->x + SCREEN_TO_GLOBAL_X,
140905b261ecSmrg                                       winRec->y + SCREEN_TO_GLOBAL_Y);
141005b261ecSmrg
141105b261ecSmrg    RootlessReorderWindow(pWin);
141205b261ecSmrg}
141305b261ecSmrg
141405b261ecSmrg
141505b261ecSmrg/*
141605b261ecSmrg * RootlessReparentWindow
141705b261ecSmrg *  Called after a window has been reparented. Generally windows are not
141805b261ecSmrg *  framed until they are mapped. However, a window may be framed early by the
141905b261ecSmrg *  implementation calling RootlessFrameForWindow. (e.g. this could be needed
142005b261ecSmrg *  to attach a VRAM surface to it.) If the window is subsequently reparented
142105b261ecSmrg *  by the window manager before being mapped, we need to give the frame to
142205b261ecSmrg *  the new top-level window.
142305b261ecSmrg */
142405b261ecSmrgvoid
142505b261ecSmrgRootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent)
142605b261ecSmrg{
142705b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
142805b261ecSmrg    RootlessWindowRec *winRec = WINREC(pWin);
142905b261ecSmrg    WindowPtr pTopWin;
143005b261ecSmrg
143105b261ecSmrg    /* Check that window is not top-level now, but used to be. */
143205b261ecSmrg    if (IsRoot(pWin) || IsRoot(pWin->parent)
143305b261ecSmrg        || IsTopLevel(pWin) || winRec == NULL)
143405b261ecSmrg    {
143505b261ecSmrg        goto out;
143605b261ecSmrg    }
143705b261ecSmrg
143805b261ecSmrg    /* If the formerly top-level window has a frame, we want to give the
143905b261ecSmrg       frame to its new top-level parent. If we can't do that, we'll just
144005b261ecSmrg       have to jettison it... */
144105b261ecSmrg
144205b261ecSmrg    pTopWin = TopLevelParent(pWin);
144305b261ecSmrg    assert(pTopWin != pWin);
14444642e01fSmrg
14454642e01fSmrg    pWin->rootlessUnhittable = FALSE;
14464642e01fSmrg
14474642e01fSmrg    DeleteProperty (serverClient, pWin, xa_native_window_id ());
144805b261ecSmrg
144905b261ecSmrg    if (WINREC(pTopWin) != NULL) {
145005b261ecSmrg        /* We're screwed. */
145105b261ecSmrg        RootlessDestroyFrame(pWin, winRec);
145205b261ecSmrg    } else {
145305b261ecSmrg        if (!pTopWin->realized && pWin->realized) {
145405b261ecSmrg            SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid);
145505b261ecSmrg        }
145605b261ecSmrg
145705b261ecSmrg        /* Switch the frame record from one to the other. */
145805b261ecSmrg
14594642e01fSmrg        SETWINREC(pWin, NULL);
14604642e01fSmrg        SETWINREC(pTopWin, winRec);
146105b261ecSmrg
146205b261ecSmrg        RootlessInitializeFrame(pTopWin, winRec);
146305b261ecSmrg        RootlessReshapeFrame(pTopWin);
146405b261ecSmrg
146505b261ecSmrg        SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
146605b261ecSmrg                                             winRec->x + SCREEN_TO_GLOBAL_X,
146705b261ecSmrg                                             winRec->y + SCREEN_TO_GLOBAL_Y,
146805b261ecSmrg                                             winRec->width, winRec->height,
146905b261ecSmrg                                             RL_GRAVITY_NONE);
147005b261ecSmrg
147105b261ecSmrg        if (SCREENREC(pScreen)->imp->SwitchWindow) {
147205b261ecSmrg            SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin);
147305b261ecSmrg        }
147405b261ecSmrg
147505b261ecSmrg        if (pTopWin->realized && !pWin->realized)
147605b261ecSmrg            winRec->is_reorder_pending = TRUE;
147705b261ecSmrg    }
147805b261ecSmrg
147905b261ecSmrgout:
148005b261ecSmrg    if (SCREENREC(pScreen)->ReparentWindow) {
148105b261ecSmrg        SCREEN_UNWRAP(pScreen, ReparentWindow);
148205b261ecSmrg        pScreen->ReparentWindow(pWin, pPriorParent);
148305b261ecSmrg        SCREEN_WRAP(pScreen, ReparentWindow);
148405b261ecSmrg    }
148505b261ecSmrg}
148605b261ecSmrg
148705b261ecSmrg
148805b261ecSmrgvoid
14894642e01fSmrgRootlessFlushWindowColormap (WindowPtr pWin)
149005b261ecSmrg{
14914642e01fSmrg  RootlessWindowRec *winRec = WINREC (pWin);
14924642e01fSmrg  xp_window_changes wc;
149305b261ecSmrg
14944642e01fSmrg  if (winRec == NULL)
14954642e01fSmrg    return;
149605b261ecSmrg
14974642e01fSmrg  RootlessStopDrawing (pWin, FALSE);
149805b261ecSmrg
14994642e01fSmrg  /* This is how we tell xp that the colormap may have changed. */
150005b261ecSmrg
15014642e01fSmrg  wc.colormap = RootlessColormapCallback;
15024642e01fSmrg  wc.colormap_data = pWin->drawable.pScreen;
150305b261ecSmrg
15044642e01fSmrg  configure_window (MAKE_WINDOW_ID(winRec->wid), XP_COLORMAP, &wc);
150505b261ecSmrg}
150605b261ecSmrg
150705b261ecSmrg/*
150805b261ecSmrg * RootlessChangeBorderWidth
150905b261ecSmrg *  FIXME: untested!
151005b261ecSmrg *  pWin inside corner stays the same; pWin->drawable.[xy] stays the same
151105b261ecSmrg *  Frame moves and resizes.
151205b261ecSmrg */
151305b261ecSmrgvoid
151405b261ecSmrgRootlessChangeBorderWidth(WindowPtr pWin, unsigned int width)
151505b261ecSmrg{
151605b261ecSmrg    RegionRec saveRoot;
151705b261ecSmrg    Bool resize_after = FALSE;
151805b261ecSmrg
151905b261ecSmrg    RL_DEBUG_MSG("change border width ");
152005b261ecSmrg
152105b261ecSmrg    if (width != wBorderWidth(pWin)) {
152205b261ecSmrg        RootlessWindowRec *winRec = WINREC(pWin);
152305b261ecSmrg        int oldX = 0, oldY = 0, newX = 0, newY = 0;
152405b261ecSmrg        unsigned int oldW = 0, oldH = 0, oldBW = 0;
152505b261ecSmrg        unsigned int newW = 0, newH = 0, newBW = 0;
152605b261ecSmrg
152705b261ecSmrg        if (winRec) {
152805b261ecSmrg            oldBW = winRec->borderWidth;
152905b261ecSmrg            oldX = winRec->x;
153005b261ecSmrg            oldY = winRec->y;
153105b261ecSmrg            oldW = winRec->width;
153205b261ecSmrg            oldH = winRec->height;
153305b261ecSmrg
153405b261ecSmrg            newBW = width;
153505b261ecSmrg            newX = pWin->drawable.x - newBW;
153605b261ecSmrg            newY = pWin->drawable.y - newBW;
153705b261ecSmrg            newW = pWin->drawable.width  + 2*newBW;
153805b261ecSmrg            newH = pWin->drawable.height + 2*newBW;
153905b261ecSmrg
154005b261ecSmrg            resize_after = StartFrameResize(pWin, FALSE,
154105b261ecSmrg                                            oldX, oldY, oldW, oldH, oldBW,
154205b261ecSmrg                                            newX, newY, newW, newH, newBW);
154305b261ecSmrg        }
154405b261ecSmrg
154505b261ecSmrg        HUGE_ROOT(pWin);
154605b261ecSmrg        SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth);
154705b261ecSmrg        pWin->drawable.pScreen->ChangeBorderWidth(pWin, width);
154805b261ecSmrg        SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth);
154905b261ecSmrg        NORMAL_ROOT(pWin);
155005b261ecSmrg
155105b261ecSmrg        if (winRec) {
155205b261ecSmrg            FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
155305b261ecSmrg                              newX, newY, newW, newH, newBW, resize_after);
155405b261ecSmrg        }
155505b261ecSmrg    }
155605b261ecSmrg
155705b261ecSmrg    RL_DEBUG_MSG("change border width end\n");
155805b261ecSmrg}
15594642e01fSmrg
15604642e01fSmrg/*
15614642e01fSmrg * RootlessOrderAllWindows
15624642e01fSmrg * Brings all X11 windows to the top of the window stack
15634642e01fSmrg * (i.e in front of Aqua windows) -- called when X11.app is given focus
15644642e01fSmrg */
15654642e01fSmrgvoid
15664642e01fSmrgRootlessOrderAllWindows (void)
15674642e01fSmrg{
15684642e01fSmrg    int i;
15694642e01fSmrg    WindowPtr pWin;
15704642e01fSmrg
15714642e01fSmrg    if (windows_hidden)
15724642e01fSmrg        return;
15734642e01fSmrg
15744642e01fSmrg    RL_DEBUG_MSG("RootlessOrderAllWindows() ");
15754642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
15764642e01fSmrg      if (screenInfo.screens[i] == NULL) continue;
15774642e01fSmrg      pWin = WindowTable[i];
15784642e01fSmrg      if (pWin == NULL) continue;
15794642e01fSmrg
15804642e01fSmrg      for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) {
15814642e01fSmrg	if (!pWin->realized) continue;
15824642e01fSmrg	if (RootlessEnsureFrame(pWin) == NULL) continue;
15834642e01fSmrg	RootlessReorderWindow (pWin);
15844642e01fSmrg      }
15854642e01fSmrg    }
15864642e01fSmrg    RL_DEBUG_MSG("RootlessOrderAllWindows() done");
15874642e01fSmrg}
15884642e01fSmrg
15894642e01fSmrgvoid
15904642e01fSmrgRootlessEnableRoot (ScreenPtr pScreen)
15914642e01fSmrg{
15924642e01fSmrg    WindowPtr pRoot;
15934642e01fSmrg    pRoot = WindowTable[pScreen->myNum];
15944642e01fSmrg
15954642e01fSmrg    RootlessEnsureFrame (pRoot);
15964642e01fSmrg    (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE);
15974642e01fSmrg    RootlessReorderWindow (pRoot);
15984642e01fSmrg}
15994642e01fSmrg
16004642e01fSmrgvoid
16014642e01fSmrgRootlessDisableRoot (ScreenPtr pScreen)
16024642e01fSmrg{
16034642e01fSmrg    WindowPtr pRoot;
16044642e01fSmrg    RootlessWindowRec *winRec;
16054642e01fSmrg
16064642e01fSmrg    pRoot = WindowTable[pScreen->myNum];
16074642e01fSmrg    winRec = WINREC (pRoot);
16084642e01fSmrg
16094642e01fSmrg    if (NULL == winRec)
16104642e01fSmrg	return;
16114642e01fSmrg
16124642e01fSmrg    RootlessDestroyFrame (pRoot, winRec);
16134642e01fSmrg    /*
16144642e01fSmrg     * gstaplin: I fixed the usage of this DeleteProperty so that it would compile.
16154642e01fSmrg     * QUESTION: Where is this xa_native_window_id set?
16164642e01fSmrg     */
16174642e01fSmrg    DeleteProperty (serverClient, pRoot, xa_native_window_id ());
16184642e01fSmrg}
16194642e01fSmrg
16204642e01fSmrgvoid
16214642e01fSmrgRootlessHideAllWindows (void)
16224642e01fSmrg{
16234642e01fSmrg    int i;
16244642e01fSmrg    ScreenPtr pScreen;
16254642e01fSmrg    WindowPtr pWin;
16264642e01fSmrg    RootlessWindowRec *winRec;
16274642e01fSmrg    xp_window_changes wc;
16284642e01fSmrg
16294642e01fSmrg    if (windows_hidden)
16304642e01fSmrg        return;
16314642e01fSmrg
16324642e01fSmrg    windows_hidden = TRUE;
16334642e01fSmrg
16344642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++)
16354642e01fSmrg    {
16364642e01fSmrg        pScreen = screenInfo.screens[i];
16374642e01fSmrg        pWin = WindowTable[i];
16384642e01fSmrg        if (pScreen == NULL || pWin == NULL)
16394642e01fSmrg            continue;
16404642e01fSmrg
16414642e01fSmrg        for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
16424642e01fSmrg        {
16434642e01fSmrg            if (!pWin->realized)
16444642e01fSmrg                continue;
16454642e01fSmrg
16464642e01fSmrg            RootlessStopDrawing (pWin, FALSE);
16474642e01fSmrg
16484642e01fSmrg            winRec = WINREC (pWin);
16494642e01fSmrg            if (winRec != NULL)
16504642e01fSmrg            {
16514642e01fSmrg                wc.stack_mode = XP_UNMAPPED;
16524642e01fSmrg                wc.sibling = 0;
16534642e01fSmrg                configure_window (MAKE_WINDOW_ID(winRec->wid), XP_STACKING, &wc);
16544642e01fSmrg            }
16554642e01fSmrg        }
16564642e01fSmrg    }
16574642e01fSmrg}
16584642e01fSmrg
16594642e01fSmrgvoid
16604642e01fSmrgRootlessShowAllWindows (void)
16614642e01fSmrg{
16624642e01fSmrg    int i;
16634642e01fSmrg    ScreenPtr pScreen;
16644642e01fSmrg    WindowPtr pWin;
16654642e01fSmrg    RootlessWindowRec *winRec;
16664642e01fSmrg
16674642e01fSmrg    if (!windows_hidden)
16684642e01fSmrg        return;
16694642e01fSmrg
16704642e01fSmrg    windows_hidden = FALSE;
16714642e01fSmrg
16724642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++)
16734642e01fSmrg    {
16744642e01fSmrg        pScreen = screenInfo.screens[i];
16754642e01fSmrg        pWin = WindowTable[i];
16764642e01fSmrg        if (pScreen == NULL || pWin == NULL)
16774642e01fSmrg            continue;
16784642e01fSmrg
16794642e01fSmrg        for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
16804642e01fSmrg        {
16814642e01fSmrg            if (!pWin->realized)
16824642e01fSmrg                continue;
16834642e01fSmrg
16844642e01fSmrg            winRec = RootlessEnsureFrame (pWin);
16854642e01fSmrg            if (winRec == NULL)
16864642e01fSmrg                continue;
16874642e01fSmrg
16884642e01fSmrg            RootlessReorderWindow (pWin);
16894642e01fSmrg        }
16904642e01fSmrg
16914642e01fSmrg        RootlessScreenExpose (pScreen);
16924642e01fSmrg    }
16934642e01fSmrg}
1694