1706f2543Smrg/*
2706f2543Smrg * Rootless window management
3706f2543Smrg */
4706f2543Smrg/*
5706f2543Smrg * Copyright (c) 2001 Greg Parker. All Rights Reserved.
6706f2543Smrg * Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved.
7706f2543Smrg * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
8706f2543Smrg *
9706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a
10706f2543Smrg * copy of this software and associated documentation files (the "Software"),
11706f2543Smrg * to deal in the Software without restriction, including without limitation
12706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the
14706f2543Smrg * Software is furnished to do so, subject to the following conditions:
15706f2543Smrg *
16706f2543Smrg * The above copyright notice and this permission notice shall be included in
17706f2543Smrg * all copies or substantial portions of the Software.
18706f2543Smrg *
19706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22706f2543Smrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
23706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25706f2543Smrg * DEALINGS IN THE SOFTWARE.
26706f2543Smrg *
27706f2543Smrg * Except as contained in this notice, the name(s) of the above copyright
28706f2543Smrg * holders shall not be used in advertising or otherwise to promote the sale,
29706f2543Smrg * use or other dealings in this Software without prior written authorization.
30706f2543Smrg */
31706f2543Smrg
32706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
33706f2543Smrg#include <dix-config.h>
34706f2543Smrg#endif
35706f2543Smrg
36706f2543Smrg#include <stddef.h> /* For NULL */
37706f2543Smrg#include <limits.h> /* For CHAR_BIT */
38706f2543Smrg#include <assert.h>
39706f2543Smrg#include <X11/Xatom.h>
40706f2543Smrg#ifdef __APPLE__
41706f2543Smrg#include <Xplugin.h>
42706f2543Smrg#include "mi.h"
43706f2543Smrg#include "pixmapstr.h"
44706f2543Smrg#include "windowstr.h"
45706f2543Smrg//#include <X11/extensions/applewm.h>
46706f2543Smrgextern int darwinMainScreenX, darwinMainScreenY;
47706f2543Smrgextern Bool no_configure_window;
48706f2543Smrg#endif
49706f2543Smrg#include "fb.h"
50706f2543Smrg
51706f2543Smrg#include "rootlessCommon.h"
52706f2543Smrg#include "rootlessWindow.h"
53706f2543Smrg
54706f2543Smrg#define SCREEN_TO_GLOBAL_X \
55706f2543Smrg    (pScreen->x + rootlessGlobalOffsetX)
56706f2543Smrg#define SCREEN_TO_GLOBAL_Y \
57706f2543Smrg    (pScreen->y + rootlessGlobalOffsetY)
58706f2543Smrg
59706f2543Smrg#define DEFINE_ATOM_HELPER(func,atom_name)                      \
60706f2543Smrg  static Atom func (void) {                                       \
61706f2543Smrg    static unsigned int generation = 0;                             \
62706f2543Smrg    static Atom atom;                                           \
63706f2543Smrg    if (generation != serverGeneration) {                       \
64706f2543Smrg      generation = serverGeneration;                          \
65706f2543Smrg      atom = MakeAtom (atom_name, strlen (atom_name), TRUE);  \
66706f2543Smrg    }                                                           \
67706f2543Smrg    return atom;                                                \
68706f2543Smrg  }
69706f2543Smrg
70706f2543SmrgDEFINE_ATOM_HELPER (xa_native_window_id, "_NATIVE_WINDOW_ID")
71706f2543Smrg
72706f2543Smrgstatic Bool windows_hidden;
73706f2543Smrg// TODO - abstract xp functions
74706f2543Smrg
75706f2543Smrg#ifdef __APPLE__
76706f2543Smrg
77706f2543Smrg// XXX: identical to x_cvt_vptr_to_uint ?
78706f2543Smrg#define MAKE_WINDOW_ID(x)		((xp_window_id)((size_t)(x)))
79706f2543Smrg
80706f2543Smrgvoid
81706f2543SmrgRootlessNativeWindowStateChanged (WindowPtr pWin, unsigned int state)
82706f2543Smrg{
83706f2543Smrg  RootlessWindowRec *winRec;
84706f2543Smrg
85706f2543Smrg  if (pWin == NULL) return;
86706f2543Smrg
87706f2543Smrg  winRec = WINREC (pWin);
88706f2543Smrg  if (winRec == NULL) return;
89706f2543Smrg
90706f2543Smrg  winRec->is_offscreen = ((state & XP_WINDOW_STATE_OFFSCREEN) != 0);
91706f2543Smrg  winRec->is_obscured = ((state & XP_WINDOW_STATE_OBSCURED) != 0);
92706f2543Smrg  pWin->rootlessUnhittable = winRec->is_offscreen;
93706f2543Smrg}
94706f2543Smrg
95706f2543Smrgvoid RootlessNativeWindowMoved (WindowPtr pWin) {
96706f2543Smrg    xp_box bounds;
97706f2543Smrg    int sx, sy, err;
98706f2543Smrg    XID vlist[2];
99706f2543Smrg    Mask mask;
100706f2543Smrg    ClientPtr pClient;
101706f2543Smrg    RootlessWindowRec *winRec;
102706f2543Smrg
103706f2543Smrg    winRec = WINREC(pWin);
104706f2543Smrg
105706f2543Smrg    if (xp_get_window_bounds (MAKE_WINDOW_ID(winRec->wid), &bounds) != Success) return;
106706f2543Smrg
107706f2543Smrg    sx = pWin->drawable.pScreen->x + darwinMainScreenX;
108706f2543Smrg    sy = pWin->drawable.pScreen->y + darwinMainScreenY;
109706f2543Smrg
110706f2543Smrg    /* Fake up a ConfigureWindow packet to resize the window to the current bounds. */
111706f2543Smrg    vlist[0] = (INT16) bounds.x1 - sx;
112706f2543Smrg    vlist[1] = (INT16) bounds.y1 - sy;
113706f2543Smrg    mask = CWX | CWY;
114706f2543Smrg
115706f2543Smrg    /* pretend we're the owner of the window! */
116706f2543Smrg    err = dixLookupClient(&pClient, pWin->drawable.id, serverClient, DixUnknownAccess);
117706f2543Smrg    if(err != Success) {
118706f2543Smrg        ErrorF("RootlessNativeWindowMoved(): Failed to lookup window: 0x%x\n", (unsigned int)pWin->drawable.id);
119706f2543Smrg        return;
120706f2543Smrg    }
121706f2543Smrg
122706f2543Smrg    /* Don't want to do anything to the physical window (avoids
123706f2543Smrg     notification-response feedback loops) */
124706f2543Smrg
125706f2543Smrg    no_configure_window = TRUE;
126706f2543Smrg    ConfigureWindow (pWin, mask, vlist, pClient);
127706f2543Smrg    no_configure_window = FALSE;
128706f2543Smrg}
129706f2543Smrg
130706f2543Smrg#endif /* __APPLE__ */
131706f2543Smrg
132706f2543Smrg/*
133706f2543Smrg * RootlessCreateWindow
134706f2543Smrg *  For now, don't create a physical window until either the window is
135706f2543Smrg *  realized, or we really need it (e.g. to attach VRAM surfaces to).
136706f2543Smrg *  Do reset the window size so it's not clipped by the root window.
137706f2543Smrg */
138706f2543SmrgBool
139706f2543SmrgRootlessCreateWindow(WindowPtr pWin)
140706f2543Smrg{
141706f2543Smrg    Bool result;
142706f2543Smrg    RegionRec saveRoot;
143706f2543Smrg
144706f2543Smrg    SETWINREC(pWin, NULL);
145706f2543Smrg    dixSetPrivate(&pWin->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL);
146706f2543Smrg
147706f2543Smrg    SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow);
148706f2543Smrg
149706f2543Smrg    if (!IsRoot(pWin)) {
150706f2543Smrg        /* win/border size set by DIX, not by wrapped CreateWindow, so
151706f2543Smrg           correct it here. Don't HUGE_ROOT when pWin is the root! */
152706f2543Smrg
153706f2543Smrg        HUGE_ROOT(pWin);
154706f2543Smrg        SetWinSize(pWin);
155706f2543Smrg        SetBorderSize(pWin);
156706f2543Smrg    }
157706f2543Smrg
158706f2543Smrg    result = pWin->drawable.pScreen->CreateWindow(pWin);
159706f2543Smrg
160706f2543Smrg    if (pWin->parent) {
161706f2543Smrg        NORMAL_ROOT(pWin);
162706f2543Smrg    }
163706f2543Smrg
164706f2543Smrg    SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow);
165706f2543Smrg
166706f2543Smrg    return result;
167706f2543Smrg}
168706f2543Smrg
169706f2543Smrg
170706f2543Smrg/*
171706f2543Smrg * RootlessDestroyFrame
172706f2543Smrg *  Destroy the physical window associated with the given window.
173706f2543Smrg */
174706f2543Smrgstatic void
175706f2543SmrgRootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec)
176706f2543Smrg{
177706f2543Smrg    SCREENREC(pWin->drawable.pScreen)->imp->DestroyFrame(winRec->wid);
178706f2543Smrg    free(winRec);
179706f2543Smrg    SETWINREC(pWin, NULL);
180706f2543Smrg}
181706f2543Smrg
182706f2543Smrg
183706f2543Smrg/*
184706f2543Smrg * RootlessDestroyWindow
185706f2543Smrg *  Destroy the physical window associated with the given window.
186706f2543Smrg */
187706f2543SmrgBool
188706f2543SmrgRootlessDestroyWindow(WindowPtr pWin)
189706f2543Smrg{
190706f2543Smrg    RootlessWindowRec *winRec = WINREC(pWin);
191706f2543Smrg    Bool result;
192706f2543Smrg
193706f2543Smrg    if (winRec != NULL) {
194706f2543Smrg        RootlessDestroyFrame(pWin, winRec);
195706f2543Smrg    }
196706f2543Smrg
197706f2543Smrg    SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow);
198706f2543Smrg    result = pWin->drawable.pScreen->DestroyWindow(pWin);
199706f2543Smrg    SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow);
200706f2543Smrg
201706f2543Smrg    return result;
202706f2543Smrg}
203706f2543Smrg
204706f2543Smrg
205706f2543Smrg
206706f2543Smrgstatic Bool
207706f2543SmrgRootlessGetShape(WindowPtr pWin, RegionPtr pShape)
208706f2543Smrg{
209706f2543Smrg    if (wBoundingShape(pWin) == NULL)
210706f2543Smrg        return FALSE;
211706f2543Smrg
212706f2543Smrg    /* wBoundingShape is relative to *inner* origin of window.
213706f2543Smrg       Translate by borderWidth to get the outside-relative position. */
214706f2543Smrg
215706f2543Smrg    RegionNull(pShape);
216706f2543Smrg    RegionCopy(pShape, wBoundingShape(pWin));
217706f2543Smrg    RegionTranslate(pShape, pWin->borderWidth, pWin->borderWidth);
218706f2543Smrg
219706f2543Smrg    return TRUE;
220706f2543Smrg}
221706f2543Smrg
222706f2543Smrg
223706f2543Smrg/*
224706f2543Smrg * RootlessReshapeFrame
225706f2543Smrg *  Set the frame shape.
226706f2543Smrg */
227706f2543Smrgstatic void RootlessReshapeFrame(WindowPtr pWin)
228706f2543Smrg{
229706f2543Smrg    RootlessWindowRec *winRec = WINREC(pWin);
230706f2543Smrg    RegionRec newShape;
231706f2543Smrg    RegionPtr pShape;
232706f2543Smrg
233706f2543Smrg    // If the window is not yet framed, do nothing
234706f2543Smrg    if (winRec == NULL)
235706f2543Smrg        return;
236706f2543Smrg
237706f2543Smrg    if (IsRoot(pWin))
238706f2543Smrg        return;
239706f2543Smrg
240706f2543Smrg    RootlessStopDrawing(pWin, FALSE);
241706f2543Smrg
242706f2543Smrg    pShape = RootlessGetShape(pWin, &newShape) ? &newShape : NULL;
243706f2543Smrg
244706f2543Smrg#ifdef ROOTLESSDEBUG
245706f2543Smrg    RL_DEBUG_MSG("reshaping...");
246706f2543Smrg    if (pShape != NULL) {
247706f2543Smrg        RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ",
248706f2543Smrg                     RegionNumRects(&newShape),
249706f2543Smrg                     newShape.extents.x1, newShape.extents.y1,
250706f2543Smrg                     newShape.extents.x2, newShape.extents.y2);
251706f2543Smrg    } else {
252706f2543Smrg        RL_DEBUG_MSG("no shape ");
253706f2543Smrg    }
254706f2543Smrg#endif
255706f2543Smrg
256706f2543Smrg    SCREENREC(pWin->drawable.pScreen)->imp->ReshapeFrame(winRec->wid, pShape);
257706f2543Smrg
258706f2543Smrg    if (pShape != NULL)
259706f2543Smrg        RegionUninit(&newShape);
260706f2543Smrg}
261706f2543Smrg
262706f2543Smrg
263706f2543Smrg/*
264706f2543Smrg * RootlessSetShape
265706f2543Smrg *  Shape is usually set before a window is mapped and the window will
266706f2543Smrg *  not have a frame associated with it. In this case, the frame will be
267706f2543Smrg *  shaped when the window is framed.
268706f2543Smrg */
269706f2543Smrgvoid
270706f2543SmrgRootlessSetShape(WindowPtr pWin, int kind)
271706f2543Smrg{
272706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
273706f2543Smrg
274706f2543Smrg    SCREEN_UNWRAP(pScreen, SetShape);
275706f2543Smrg    pScreen->SetShape(pWin, kind);
276706f2543Smrg    SCREEN_WRAP(pScreen, SetShape);
277706f2543Smrg
278706f2543Smrg    RootlessReshapeFrame(pWin);
279706f2543Smrg}
280706f2543Smrg
281706f2543Smrg
282706f2543Smrg
283706f2543Smrg/* Disallow ParentRelative background on top-level windows
284706f2543Smrg   because the root window doesn't really have the right background.
285706f2543Smrg */
286706f2543SmrgBool
287706f2543SmrgRootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask)
288706f2543Smrg{
289706f2543Smrg    Bool result;
290706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
291706f2543Smrg
292706f2543Smrg    RL_DEBUG_MSG("change window attributes start ");
293706f2543Smrg
294706f2543Smrg    SCREEN_UNWRAP(pScreen, ChangeWindowAttributes);
295706f2543Smrg    result = pScreen->ChangeWindowAttributes(pWin, vmask);
296706f2543Smrg    SCREEN_WRAP(pScreen, ChangeWindowAttributes);
297706f2543Smrg
298706f2543Smrg    if (WINREC(pWin)) {
299706f2543Smrg        // disallow ParentRelative background state
300706f2543Smrg        if (pWin->backgroundState == ParentRelative) {
301706f2543Smrg            XID pixel = 0;
302706f2543Smrg            ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
303706f2543Smrg        }
304706f2543Smrg    }
305706f2543Smrg
306706f2543Smrg    RL_DEBUG_MSG("change window attributes end\n");
307706f2543Smrg    return result;
308706f2543Smrg}
309706f2543Smrg
310706f2543Smrg
311706f2543Smrg/*
312706f2543Smrg * RootlessPositionWindow
313706f2543Smrg *  This is a hook for when DIX moves or resizes a window.
314706f2543Smrg *  Update the frame position now although the physical window is moved
315706f2543Smrg *  in RootlessMoveWindow. (x, y) are *inside* position. After this,
316706f2543Smrg *  mi and fb are expecting the pixmap to be at the new location.
317706f2543Smrg */
318706f2543SmrgBool
319706f2543SmrgRootlessPositionWindow(WindowPtr pWin, int x, int y)
320706f2543Smrg{
321706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
322706f2543Smrg    RootlessWindowRec *winRec = WINREC(pWin);
323706f2543Smrg    Bool result;
324706f2543Smrg
325706f2543Smrg    RL_DEBUG_MSG("positionwindow start (win 0x%x @ %i, %i)\n", pWin, x, y);
326706f2543Smrg
327706f2543Smrg    if (winRec) {
328706f2543Smrg        if (winRec->is_drawing) {
329706f2543Smrg            // Reset frame's pixmap and move it to the new position.
330706f2543Smrg            int bw = wBorderWidth(pWin);
331706f2543Smrg
332706f2543Smrg            winRec->pixmap->devPrivate.ptr = winRec->pixelData;
333706f2543Smrg            SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw);
334706f2543Smrg        }
335706f2543Smrg    }
336706f2543Smrg
337706f2543Smrg    SCREEN_UNWRAP(pScreen, PositionWindow);
338706f2543Smrg    result = pScreen->PositionWindow(pWin, x, y);
339706f2543Smrg    SCREEN_WRAP(pScreen, PositionWindow);
340706f2543Smrg
341706f2543Smrg    RL_DEBUG_MSG("positionwindow end\n");
342706f2543Smrg    return result;
343706f2543Smrg}
344706f2543Smrg
345706f2543Smrg
346706f2543Smrg/*
347706f2543Smrg * RootlessInitializeFrame
348706f2543Smrg *  Initialize some basic attributes of the frame. Note that winRec
349706f2543Smrg *  may already have valid data in it, so don't overwrite anything
350706f2543Smrg *  valuable.
351706f2543Smrg */
352706f2543Smrgstatic void
353706f2543SmrgRootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec *winRec)
354706f2543Smrg{
355706f2543Smrg    DrawablePtr d = &pWin->drawable;
356706f2543Smrg    int bw = wBorderWidth(pWin);
357706f2543Smrg
358706f2543Smrg    winRec->win = pWin;
359706f2543Smrg
360706f2543Smrg    winRec->x = d->x - bw;
361706f2543Smrg    winRec->y = d->y - bw;
362706f2543Smrg    winRec->width = d->width + 2*bw;
363706f2543Smrg    winRec->height = d->height + 2*bw;
364706f2543Smrg    winRec->borderWidth = bw;
365706f2543Smrg}
366706f2543Smrg
367706f2543Smrg/*
368706f2543Smrg * RootlessEnsureFrame
369706f2543Smrg *  Make sure the given window is framed. If the window doesn't have a
370706f2543Smrg *  physical window associated with it, attempt to create one. If that
371706f2543Smrg *  is unsuccessful, return NULL.
372706f2543Smrg */
373706f2543Smrgstatic RootlessWindowRec *
374706f2543SmrgRootlessEnsureFrame(WindowPtr pWin)
375706f2543Smrg{
376706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
377706f2543Smrg    RootlessWindowRec *winRec;
378706f2543Smrg    RegionRec shape;
379706f2543Smrg    RegionPtr pShape = NULL;
380706f2543Smrg
381706f2543Smrg    if (WINREC(pWin) != NULL)
382706f2543Smrg        return WINREC(pWin);
383706f2543Smrg
384706f2543Smrg    if (!IsTopLevel(pWin) && !IsRoot(pWin))
385706f2543Smrg        return NULL;
386706f2543Smrg
387706f2543Smrg    if (pWin->drawable.class != InputOutput)
388706f2543Smrg        return NULL;
389706f2543Smrg
390706f2543Smrg    winRec = malloc(sizeof(RootlessWindowRec));
391706f2543Smrg
392706f2543Smrg    if (!winRec)
393706f2543Smrg        return NULL;
394706f2543Smrg
395706f2543Smrg    RootlessInitializeFrame(pWin, winRec);
396706f2543Smrg
397706f2543Smrg    winRec->is_drawing = FALSE;
398706f2543Smrg    winRec->is_reorder_pending = FALSE;
399706f2543Smrg    winRec->pixmap = NULL;
400706f2543Smrg    winRec->wid = NULL;
401706f2543Smrg    winRec->level = 0;
402706f2543Smrg
403706f2543Smrg    SETWINREC(pWin, winRec);
404706f2543Smrg
405706f2543Smrg    // Set the frame's shape if the window is shaped
406706f2543Smrg    if (RootlessGetShape(pWin, &shape))
407706f2543Smrg        pShape = &shape;
408706f2543Smrg
409706f2543Smrg    RL_DEBUG_MSG("creating frame ");
410706f2543Smrg
411706f2543Smrg    if (!SCREENREC(pScreen)->imp->CreateFrame(winRec, pScreen,
412706f2543Smrg                                              winRec->x + SCREEN_TO_GLOBAL_X,
413706f2543Smrg                                              winRec->y + SCREEN_TO_GLOBAL_Y,
414706f2543Smrg                                              pShape))
415706f2543Smrg    {
416706f2543Smrg        RL_DEBUG_MSG("implementation failed to create frame!\n");
417706f2543Smrg        free(winRec);
418706f2543Smrg        SETWINREC(pWin, NULL);
419706f2543Smrg        return NULL;
420706f2543Smrg    }
421706f2543Smrg
422706f2543Smrg    if (pWin->drawable.depth == 8)
423706f2543Smrg      RootlessFlushWindowColormap(pWin);
424706f2543Smrg
425706f2543Smrg    if (pShape != NULL)
426706f2543Smrg        RegionUninit(&shape);
427706f2543Smrg
428706f2543Smrg    return winRec;
429706f2543Smrg}
430706f2543Smrg
431706f2543Smrg
432706f2543Smrg/*
433706f2543Smrg * RootlessRealizeWindow
434706f2543Smrg *  The frame is usually created here and not in CreateWindow so that
435706f2543Smrg *  windows do not eat memory until they are realized.
436706f2543Smrg */
437706f2543SmrgBool
438706f2543SmrgRootlessRealizeWindow(WindowPtr pWin)
439706f2543Smrg{
440706f2543Smrg    Bool result;
441706f2543Smrg    RegionRec saveRoot;
442706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
443706f2543Smrg
444706f2543Smrg    RL_DEBUG_MSG("realizewindow start (win 0x%x) ", pWin);
445706f2543Smrg
446706f2543Smrg    if ((IsTopLevel(pWin) && pWin->drawable.class == InputOutput)) {
447706f2543Smrg        RootlessWindowRec *winRec;
448706f2543Smrg
449706f2543Smrg        winRec = RootlessEnsureFrame(pWin);
450706f2543Smrg        if (winRec == NULL)
451706f2543Smrg            return FALSE;
452706f2543Smrg
453706f2543Smrg        winRec->is_reorder_pending = TRUE;
454706f2543Smrg
455706f2543Smrg        RL_DEBUG_MSG("Top level window ");
456706f2543Smrg
457706f2543Smrg        // Disallow ParentRelative background state on top-level windows.
458706f2543Smrg        // This might have been set before the window was mapped.
459706f2543Smrg        if (pWin->backgroundState == ParentRelative) {
460706f2543Smrg            XID pixel = 0;
461706f2543Smrg            ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
462706f2543Smrg        }
463706f2543Smrg    }
464706f2543Smrg
465706f2543Smrg    if (!IsRoot(pWin)) HUGE_ROOT(pWin);
466706f2543Smrg    SCREEN_UNWRAP(pScreen, RealizeWindow);
467706f2543Smrg    result = pScreen->RealizeWindow(pWin);
468706f2543Smrg    SCREEN_WRAP(pScreen, RealizeWindow);
469706f2543Smrg    if (!IsRoot(pWin)) NORMAL_ROOT(pWin);
470706f2543Smrg
471706f2543Smrg    RL_DEBUG_MSG("realizewindow end\n");
472706f2543Smrg    return result;
473706f2543Smrg}
474706f2543Smrg
475706f2543Smrg
476706f2543Smrg/*
477706f2543Smrg * RootlessFrameForWindow
478706f2543Smrg *  Returns the frame ID for the physical window displaying the given window.
479706f2543Smrg *  If CREATE is true and the window has no frame, attempt to create one.
480706f2543Smrg */
481706f2543SmrgRootlessFrameID
482706f2543SmrgRootlessFrameForWindow(WindowPtr pWin, Bool create)
483706f2543Smrg{
484706f2543Smrg    WindowPtr pTopWin;
485706f2543Smrg    RootlessWindowRec *winRec;
486706f2543Smrg
487706f2543Smrg    pTopWin = TopLevelParent(pWin);
488706f2543Smrg    if (pTopWin == NULL)
489706f2543Smrg        return NULL;
490706f2543Smrg
491706f2543Smrg    winRec = WINREC(pTopWin);
492706f2543Smrg
493706f2543Smrg    if (winRec == NULL && create && pWin->drawable.class == InputOutput) {
494706f2543Smrg        winRec = RootlessEnsureFrame(pTopWin);
495706f2543Smrg    }
496706f2543Smrg
497706f2543Smrg    if (winRec == NULL)
498706f2543Smrg        return NULL;
499706f2543Smrg
500706f2543Smrg    return winRec->wid;
501706f2543Smrg}
502706f2543Smrg
503706f2543Smrg
504706f2543Smrg/*
505706f2543Smrg * RootlessUnrealizeWindow
506706f2543Smrg *  Unmap the physical window.
507706f2543Smrg */
508706f2543SmrgBool
509706f2543SmrgRootlessUnrealizeWindow(WindowPtr pWin)
510706f2543Smrg{
511706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
512706f2543Smrg    RootlessWindowRec *winRec = WINREC(pWin);
513706f2543Smrg    Bool result;
514706f2543Smrg
515706f2543Smrg    RL_DEBUG_MSG("unrealizewindow start ");
516706f2543Smrg
517706f2543Smrg    if (winRec) {
518706f2543Smrg        RootlessStopDrawing(pWin, FALSE);
519706f2543Smrg
520706f2543Smrg        SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid);
521706f2543Smrg
522706f2543Smrg        winRec->is_reorder_pending = FALSE;
523706f2543Smrg    }
524706f2543Smrg
525706f2543Smrg    SCREEN_UNWRAP(pScreen, UnrealizeWindow);
526706f2543Smrg    result = pScreen->UnrealizeWindow(pWin);
527706f2543Smrg    SCREEN_WRAP(pScreen, UnrealizeWindow);
528706f2543Smrg
529706f2543Smrg    RL_DEBUG_MSG("unrealizewindow end\n");
530706f2543Smrg    return result;
531706f2543Smrg}
532706f2543Smrg
533706f2543Smrg
534706f2543Smrg/*
535706f2543Smrg * RootlessReorderWindow
536706f2543Smrg *  Reorder the frame associated with the given window so that it's
537706f2543Smrg *  physically above the window below it in the X stacking order.
538706f2543Smrg */
539706f2543Smrgvoid
540706f2543SmrgRootlessReorderWindow(WindowPtr pWin)
541706f2543Smrg{
542706f2543Smrg    RootlessWindowRec *winRec = WINREC(pWin);
543706f2543Smrg
544706f2543Smrg    if (pWin->realized && winRec != NULL && !winRec->is_reorder_pending && !windows_hidden) {
545706f2543Smrg        WindowPtr newPrevW;
546706f2543Smrg        RootlessWindowRec *newPrev;
547706f2543Smrg        RootlessFrameID newPrevID;
548706f2543Smrg        ScreenPtr pScreen = pWin->drawable.pScreen;
549706f2543Smrg
550706f2543Smrg        /* Check if the implementation wants the frame to not be reordered
551706f2543Smrg           even though the X11 window is restacked. This can be useful if
552706f2543Smrg           frames are ordered-in with animation so that the reordering is not
553706f2543Smrg           done until the animation is complete. */
554706f2543Smrg        if (SCREENREC(pScreen)->imp->DoReorderWindow) {
555706f2543Smrg            if (!SCREENREC(pScreen)->imp->DoReorderWindow(winRec))
556706f2543Smrg                return;
557706f2543Smrg        }
558706f2543Smrg
559706f2543Smrg        RootlessStopDrawing(pWin, FALSE);
560706f2543Smrg
561706f2543Smrg        /* Find the next window above this one that has a mapped frame.
562706f2543Smrg         * Only include cases where the windows are in the same category of
563706f2543Smrg         * hittability to ensure offscreen windows dont get restacked
564706f2543Smrg         * relative to onscreen ones (but that the offscreen ones maintain
565706f2543Smrg         * their stacking order if they are explicitly asked to Reorder
566706f2543Smrg         */
567706f2543Smrg
568706f2543Smrg        newPrevW = pWin->prevSib;
569706f2543Smrg        while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized || newPrevW->rootlessUnhittable != pWin->rootlessUnhittable))
570706f2543Smrg            newPrevW = newPrevW->prevSib;
571706f2543Smrg
572706f2543Smrg        newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL;
573706f2543Smrg        newPrevID = newPrev != NULL ? newPrev->wid : 0;
574706f2543Smrg
575706f2543Smrg        /* If it exists, reorder the frame above us first. */
576706f2543Smrg
577706f2543Smrg        if (newPrev && newPrev->is_reorder_pending) {
578706f2543Smrg            newPrev->is_reorder_pending = FALSE;
579706f2543Smrg            RootlessReorderWindow(newPrevW);
580706f2543Smrg        }
581706f2543Smrg
582706f2543Smrg        SCREENREC(pScreen)->imp->RestackFrame(winRec->wid, newPrevID);
583706f2543Smrg    }
584706f2543Smrg}
585706f2543Smrg
586706f2543Smrg
587706f2543Smrg/*
588706f2543Smrg * RootlessRestackWindow
589706f2543Smrg *  This is a hook for when DIX changes the window stacking order.
590706f2543Smrg *  The window has already been inserted into its new position in the
591706f2543Smrg *  DIX window stack. We need to change the order of the physical
592706f2543Smrg *  window to match.
593706f2543Smrg */
594706f2543Smrgvoid
595706f2543SmrgRootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib)
596706f2543Smrg{
597706f2543Smrg    RegionRec saveRoot;
598706f2543Smrg    RootlessWindowRec *winRec = WINREC(pWin);
599706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
600706f2543Smrg
601706f2543Smrg    RL_DEBUG_MSG("restackwindow start ");
602706f2543Smrg    if (winRec)
603706f2543Smrg        RL_DEBUG_MSG("restack top level \n");
604706f2543Smrg
605706f2543Smrg    HUGE_ROOT(pWin);
606706f2543Smrg    SCREEN_UNWRAP(pScreen, RestackWindow);
607706f2543Smrg
608706f2543Smrg    if (pScreen->RestackWindow)
609706f2543Smrg        pScreen->RestackWindow(pWin, pOldNextSib);
610706f2543Smrg
611706f2543Smrg    SCREEN_WRAP(pScreen, RestackWindow);
612706f2543Smrg    NORMAL_ROOT(pWin);
613706f2543Smrg
614706f2543Smrg    if (winRec && pWin->viewable) {
615706f2543Smrg        RootlessReorderWindow(pWin);
616706f2543Smrg    }
617706f2543Smrg
618706f2543Smrg    RL_DEBUG_MSG("restackwindow end\n");
619706f2543Smrg}
620706f2543Smrg
621706f2543Smrg/*
622706f2543Smrg * Specialized window copy procedures
623706f2543Smrg */
624706f2543Smrg
625706f2543Smrg// Globals needed during window resize and move.
626706f2543Smrgstatic pointer gResizeDeathBits = NULL;
627706f2543Smrgstatic int gResizeDeathCount = 0;
628706f2543Smrgstatic PixmapPtr gResizeDeathPix[2] = {NULL, NULL};
629706f2543Smrgstatic BoxRec gResizeDeathBounds[2];
630706f2543Smrgstatic CopyWindowProcPtr gResizeOldCopyWindowProc = NULL;
631706f2543Smrg
632706f2543Smrg/*
633706f2543Smrg * RootlessNoCopyWindow
634706f2543Smrg *  CopyWindow() that doesn't do anything. For MoveWindow() of
635706f2543Smrg *  top-level windows.
636706f2543Smrg */
637706f2543Smrgstatic void
638706f2543SmrgRootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
639706f2543Smrg                     RegionPtr prgnSrc)
640706f2543Smrg{
641706f2543Smrg    // some code expects the region to be translated
642706f2543Smrg    int dx = ptOldOrg.x - pWin->drawable.x;
643706f2543Smrg    int dy = ptOldOrg.y - pWin->drawable.y;
644706f2543Smrg
645706f2543Smrg    RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW ");
646706f2543Smrg
647706f2543Smrg    RegionTranslate(prgnSrc, -dx, -dy);
648706f2543Smrg}
649706f2543Smrg
650706f2543Smrg
651706f2543Smrg/*
652706f2543Smrg * RootlessResizeCopyWindow
653706f2543Smrg *  CopyWindow used during ResizeWindow for gravity moves. Based on
654706f2543Smrg *  fbCopyWindow. The original always draws on the root pixmap, which
655706f2543Smrg *  we don't have. Instead, draw on the parent window's pixmap.
656706f2543Smrg *  Resize version: the old location's pixels are in gResizeCopyWindowSource.
657706f2543Smrg */
658706f2543Smrgstatic void
659706f2543SmrgRootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
660706f2543Smrg                         RegionPtr prgnSrc)
661706f2543Smrg{
662706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
663706f2543Smrg    RegionRec   rgnDst;
664706f2543Smrg    int         dx, dy;
665706f2543Smrg
666706f2543Smrg    RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin);
667706f2543Smrg
668706f2543Smrg    /* Don't unwrap pScreen->CopyWindow.
669706f2543Smrg       The bogus rewrap with RootlessCopyWindow causes a crash if
670706f2543Smrg       CopyWindow is called again during the same resize. */
671706f2543Smrg
672706f2543Smrg    if (gResizeDeathCount == 0)
673706f2543Smrg        return;
674706f2543Smrg
675706f2543Smrg    RootlessStartDrawing(pWin);
676706f2543Smrg
677706f2543Smrg    dx = ptOldOrg.x - pWin->drawable.x;
678706f2543Smrg    dy = ptOldOrg.y - pWin->drawable.y;
679706f2543Smrg    RegionTranslate(prgnSrc, -dx, -dy);
680706f2543Smrg    RegionNull(&rgnDst);
681706f2543Smrg    RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
682706f2543Smrg
683706f2543Smrg    if (gResizeDeathCount == 1) {
684706f2543Smrg        /* Simple case, we only have a single source pixmap. */
685706f2543Smrg
686706f2543Smrg        fbCopyRegion(&gResizeDeathPix[0]->drawable,
687706f2543Smrg                     &pScreen->GetWindowPixmap(pWin)->drawable, 0,
688706f2543Smrg                     &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
689706f2543Smrg    }
690706f2543Smrg    else {
691706f2543Smrg        int i;
692706f2543Smrg        RegionRec clip, clipped;
693706f2543Smrg
694706f2543Smrg        /* More complex case, N source pixmaps (usually two). So we
695706f2543Smrg           intersect the destination with each source and copy those bits. */
696706f2543Smrg
697706f2543Smrg        for (i = 0; i < gResizeDeathCount; i++) {
698706f2543Smrg            RegionInit(&clip, gResizeDeathBounds + 0, 1);
699706f2543Smrg            RegionNull(&clipped);
700706f2543Smrg            RegionIntersect(&rgnDst, &clip, &clipped);
701706f2543Smrg
702706f2543Smrg            fbCopyRegion(&gResizeDeathPix[i]->drawable,
703706f2543Smrg                         &pScreen->GetWindowPixmap(pWin)->drawable, 0,
704706f2543Smrg                         &clipped, dx, dy, fbCopyWindowProc, 0, 0);
705706f2543Smrg
706706f2543Smrg            RegionUninit(&clipped);
707706f2543Smrg            RegionUninit(&clip);
708706f2543Smrg        }
709706f2543Smrg    }
710706f2543Smrg
711706f2543Smrg    /* Don't update - resize will update everything */
712706f2543Smrg    RegionUninit(&rgnDst);
713706f2543Smrg
714706f2543Smrg    fbValidateDrawable(&pWin->drawable);
715706f2543Smrg
716706f2543Smrg    RL_DEBUG_MSG("resizecopywindowFB end\n");
717706f2543Smrg}
718706f2543Smrg
719706f2543Smrg
720706f2543Smrg/*
721706f2543Smrg * RootlessCopyWindow
722706f2543Smrg *  Update *new* location of window. Old location is redrawn with
723706f2543Smrg *  miPaintWindow. Cloned from fbCopyWindow.
724706f2543Smrg *  The original always draws on the root pixmap, which we don't have.
725706f2543Smrg *  Instead, draw on the parent window's pixmap.
726706f2543Smrg */
727706f2543Smrgvoid
728706f2543SmrgRootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
729706f2543Smrg{
730706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
731706f2543Smrg    RegionRec   rgnDst;
732706f2543Smrg    int         dx, dy;
733706f2543Smrg    BoxPtr extents;
734706f2543Smrg    int area;
735706f2543Smrg
736706f2543Smrg    RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin);
737706f2543Smrg
738706f2543Smrg    SCREEN_UNWRAP(pScreen, CopyWindow);
739706f2543Smrg
740706f2543Smrg    dx = ptOldOrg.x - pWin->drawable.x;
741706f2543Smrg    dy = ptOldOrg.y - pWin->drawable.y;
742706f2543Smrg    RegionTranslate(prgnSrc, -dx, -dy);
743706f2543Smrg
744706f2543Smrg    RegionNull(&rgnDst);
745706f2543Smrg    RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
746706f2543Smrg
747706f2543Smrg    extents = RegionExtents(&rgnDst);
748706f2543Smrg    area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1);
749706f2543Smrg
750706f2543Smrg    /* If the area exceeds threshold, use the implementation's
751706f2543Smrg       accelerated version. */
752706f2543Smrg    if (area > rootless_CopyWindow_threshold &&
753706f2543Smrg        SCREENREC(pScreen)->imp->CopyWindow)
754706f2543Smrg    {
755706f2543Smrg        RootlessWindowRec *winRec;
756706f2543Smrg        WindowPtr top;
757706f2543Smrg
758706f2543Smrg        top = TopLevelParent(pWin);
759706f2543Smrg        if (top == NULL) {
760706f2543Smrg            RL_DEBUG_MSG("no parent\n");
761706f2543Smrg            goto out;
762706f2543Smrg        }
763706f2543Smrg
764706f2543Smrg        winRec = WINREC(top);
765706f2543Smrg        if (winRec == NULL) {
766706f2543Smrg            RL_DEBUG_MSG("not framed\n");
767706f2543Smrg            goto out;
768706f2543Smrg        }
769706f2543Smrg
770706f2543Smrg        /* Move region to window local coords */
771706f2543Smrg        RegionTranslate(&rgnDst, -winRec->x, -winRec->y);
772706f2543Smrg
773706f2543Smrg        RootlessStopDrawing(pWin, FALSE);
774706f2543Smrg
775706f2543Smrg        SCREENREC(pScreen)->imp->CopyWindow(winRec->wid,
776706f2543Smrg                                            RegionNumRects(&rgnDst),
777706f2543Smrg                                            RegionRects(&rgnDst),
778706f2543Smrg                                            dx, dy);
779706f2543Smrg    }
780706f2543Smrg    else {
781706f2543Smrg        RootlessStartDrawing(pWin);
782706f2543Smrg
783706f2543Smrg        fbCopyRegion((DrawablePtr) pWin, (DrawablePtr) pWin,
784706f2543Smrg                     0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
785706f2543Smrg
786706f2543Smrg        /* prgnSrc has been translated to dst position */
787706f2543Smrg        RootlessDamageRegion(pWin, prgnSrc);
788706f2543Smrg    }
789706f2543Smrg
790706f2543Smrgout:
791706f2543Smrg    RegionUninit(&rgnDst);
792706f2543Smrg    fbValidateDrawable(&pWin->drawable);
793706f2543Smrg
794706f2543Smrg    SCREEN_WRAP(pScreen, CopyWindow);
795706f2543Smrg
796706f2543Smrg    RL_DEBUG_MSG("copywindowFB end\n");
797706f2543Smrg}
798706f2543Smrg
799706f2543Smrg
800706f2543Smrg/*
801706f2543Smrg * Window resize procedures
802706f2543Smrg */
803706f2543Smrg
804706f2543Smrgenum {
805706f2543Smrg    WIDTH_SMALLER = 1,
806706f2543Smrg    HEIGHT_SMALLER = 2,
807706f2543Smrg};
808706f2543Smrg
809706f2543Smrg
810706f2543Smrg/*
811706f2543Smrg * ResizeWeighting
812706f2543Smrg *  Choose gravity to avoid local copies. Do that by looking for
813706f2543Smrg *  a corner that doesn't move _relative to the screen_.
814706f2543Smrg */
815706f2543Smrgstatic inline unsigned int
816706f2543SmrgResizeWeighting(int oldX1, int oldY1, int oldX2, int oldY2, int oldBW,
817706f2543Smrg                int newX1, int newY1, int newX2, int newY2, int newBW)
818706f2543Smrg{
819706f2543Smrg#ifdef ROOTLESS_RESIZE_GRAVITY
820706f2543Smrg    if (newBW != oldBW)
821706f2543Smrg        return RL_GRAVITY_NONE;
822706f2543Smrg
823706f2543Smrg    if (newX1 == oldX1 && newY1 == oldY1)
824706f2543Smrg        return RL_GRAVITY_NORTH_WEST;
825706f2543Smrg    else if (newX1 == oldX1 && newY2 == oldY2)
826706f2543Smrg        return RL_GRAVITY_SOUTH_WEST;
827706f2543Smrg    else if (newX2 == oldX2 && newY2 == oldY2)
828706f2543Smrg        return RL_GRAVITY_SOUTH_EAST;
829706f2543Smrg    else if (newX2 == oldX2 && newY1 == oldY1)
830706f2543Smrg        return RL_GRAVITY_NORTH_EAST;
831706f2543Smrg    else
832706f2543Smrg        return RL_GRAVITY_NONE;
833706f2543Smrg#else
834706f2543Smrg    return RL_GRAVITY_NONE;
835706f2543Smrg#endif
836706f2543Smrg}
837706f2543Smrg
838706f2543Smrg
839706f2543Smrg/*
840706f2543Smrg * StartFrameResize
841706f2543Smrg *  Prepare to resize a top-level window. The old window's pixels are
842706f2543Smrg *  saved and the implementation is told to change the window size.
843706f2543Smrg *  (x,y,w,h) is outer frame of window (outside border)
844706f2543Smrg */
845706f2543Smrgstatic Bool
846706f2543SmrgStartFrameResize(WindowPtr pWin, Bool gravity,
847706f2543Smrg                 int oldX, int oldY, int oldW, int oldH, int oldBW,
848706f2543Smrg                 int newX, int newY, int newW, int newH, int newBW)
849706f2543Smrg{
850706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
851706f2543Smrg    RootlessWindowRec *winRec = WINREC(pWin);
852706f2543Smrg    Bool need_window_source = FALSE, resize_after = FALSE;
853706f2543Smrg
854706f2543Smrg    BoxRec rect;
855706f2543Smrg    int oldX2, newX2;
856706f2543Smrg    int oldY2, newY2;
857706f2543Smrg    unsigned int weight;
858706f2543Smrg
859706f2543Smrg    oldX2 = oldX + oldW, newX2 = newX + newW;
860706f2543Smrg    oldY2 = oldY + oldH, newY2 = newY + newH;
861706f2543Smrg
862706f2543Smrg    /* Decide which resize weighting to use */
863706f2543Smrg    weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW,
864706f2543Smrg                             newX, newY, newW, newH, newBW);
865706f2543Smrg
866706f2543Smrg    /* Compute intersection between old and new rects */
867706f2543Smrg    rect.x1 = max(oldX, newX);
868706f2543Smrg    rect.y1 = max(oldY, newY);
869706f2543Smrg    rect.x2 = min(oldX2, newX2);
870706f2543Smrg    rect.y2 = min(oldY2, newY2);
871706f2543Smrg
872706f2543Smrg    RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity);
873706f2543Smrg    RL_DEBUG_MSG("%d %d %d %d %d   %d %d %d %d %d\n",
874706f2543Smrg                 oldX, oldY, oldW, oldH, oldBW,
875706f2543Smrg                 newX, newY, newW, newH, newBW);
876706f2543Smrg
877706f2543Smrg    RootlessRedisplay(pWin);
878706f2543Smrg
879706f2543Smrg    /* If gravity is true, then we need to have a way of recovering all
880706f2543Smrg       the original bits in the window for when X rearranges the contents
881706f2543Smrg       based on the various gravity settings. The obvious way is to just
882706f2543Smrg       snapshot the entire backing store before resizing it, but that
883706f2543Smrg       it slow on large windows.
884706f2543Smrg
885706f2543Smrg       So the optimization here is to use the implementation's resize
886706f2543Smrg       weighting options (if available) to allow us to reason about what
887706f2543Smrg       is left in the backing store after the resize. We can then only
888706f2543Smrg       copy what won't be there after the resize, and do a two-stage copy
889706f2543Smrg       operation.
890706f2543Smrg
891706f2543Smrg       Most of these optimizations are only applied when the top-left
892706f2543Smrg       corner of the window is fixed, since that's the common case. They
893706f2543Smrg       could probably be extended with some thought. */
894706f2543Smrg
895706f2543Smrg    gResizeDeathCount = 0;
896706f2543Smrg
897706f2543Smrg    if (gravity && weight == RL_GRAVITY_NORTH_WEST) {
898706f2543Smrg        unsigned int code = 0;
899706f2543Smrg
900706f2543Smrg        /* Top left corner is anchored. We never need to copy the
901706f2543Smrg           entire window. */
902706f2543Smrg
903706f2543Smrg        need_window_source = TRUE;
904706f2543Smrg
905706f2543Smrg        /* These comparisons were chosen to avoid setting bits when the sizes
906706f2543Smrg        are the same. (So the fastest case automatically gets taken when
907706f2543Smrg        dimensions are unchanging.) */
908706f2543Smrg
909706f2543Smrg        if (newW < oldW)
910706f2543Smrg            code |= WIDTH_SMALLER;
911706f2543Smrg        if (newH < oldH)
912706f2543Smrg            code |= HEIGHT_SMALLER;
913706f2543Smrg
914706f2543Smrg        if (((code ^ (code >> 1)) & 1) == 0) {
915706f2543Smrg            /* Both dimensions are either getting larger, or both
916706f2543Smrg               are getting smaller. No need to copy anything. */
917706f2543Smrg
918706f2543Smrg            if (code == (WIDTH_SMALLER | HEIGHT_SMALLER)) {
919706f2543Smrg                /* Since the window is getting smaller, we can do gravity
920706f2543Smrg                   repair on it with it's current size, then resize it
921706f2543Smrg                   afterwards. */
922706f2543Smrg
923706f2543Smrg                resize_after = TRUE;
924706f2543Smrg            }
925706f2543Smrg
926706f2543Smrg            gResizeDeathCount = 1;
927706f2543Smrg        }
928706f2543Smrg        else {
929706f2543Smrg            unsigned int copy_rowbytes, Bpp;
930706f2543Smrg            unsigned int copy_rect_width, copy_rect_height;
931706f2543Smrg            BoxRec copy_rect;
932706f2543Smrg
933706f2543Smrg            /* We can get away with a partial copy. 'rect' is the
934706f2543Smrg               intersection between old and new bounds, so copy
935706f2543Smrg               everything to the right of or below the intersection. */
936706f2543Smrg
937706f2543Smrg            RootlessStartDrawing(pWin);
938706f2543Smrg
939706f2543Smrg            if (code == WIDTH_SMALLER) {
940706f2543Smrg                copy_rect.x1 = rect.x2;
941706f2543Smrg                copy_rect.y1 = rect.y1;
942706f2543Smrg                copy_rect.x2 = oldX2;
943706f2543Smrg                copy_rect.y2 = oldY2;
944706f2543Smrg            }
945706f2543Smrg            else if (code == HEIGHT_SMALLER) {
946706f2543Smrg                copy_rect.x1 = rect.x1;
947706f2543Smrg                copy_rect.y1 = rect.y2;
948706f2543Smrg                copy_rect.x2 = oldX2;
949706f2543Smrg                copy_rect.y2 = oldY2;
950706f2543Smrg            }
951706f2543Smrg            else
952706f2543Smrg                OsAbort();
953706f2543Smrg
954706f2543Smrg            Bpp = winRec->win->drawable.bitsPerPixel / 8;
955706f2543Smrg            copy_rect_width = copy_rect.x2 - copy_rect.x1;
956706f2543Smrg            copy_rect_height = copy_rect.y2 - copy_rect.y1;
957706f2543Smrg            copy_rowbytes = ((copy_rect_width * Bpp) + 31) & ~31;
958706f2543Smrg            gResizeDeathBits = malloc(copy_rowbytes
959706f2543Smrg                                      * copy_rect_height);
960706f2543Smrg
961706f2543Smrg            if (copy_rect_width * copy_rect_height >
962706f2543Smrg                        rootless_CopyBytes_threshold &&
963706f2543Smrg                SCREENREC(pScreen)->imp->CopyBytes)
964706f2543Smrg            {
965706f2543Smrg                SCREENREC(pScreen)->imp->CopyBytes(
966706f2543Smrg                    copy_rect_width * Bpp, copy_rect_height,
967706f2543Smrg                    ((char *) winRec->pixelData)
968706f2543Smrg                    + ((copy_rect.y1 - oldY) * winRec->bytesPerRow)
969706f2543Smrg                    + (copy_rect.x1 - oldX) * Bpp, winRec->bytesPerRow,
970706f2543Smrg                    gResizeDeathBits, copy_rowbytes);
971706f2543Smrg            } else {
972706f2543Smrg                fbBlt((FbBits *) (winRec->pixelData
973706f2543Smrg                      + ((copy_rect.y1 - oldY) * winRec->bytesPerRow)
974706f2543Smrg                      + (copy_rect.x1 - oldX) * Bpp),
975706f2543Smrg                      winRec->bytesPerRow / sizeof(FbBits), 0,
976706f2543Smrg                      (FbBits *) gResizeDeathBits,
977706f2543Smrg                      copy_rowbytes / sizeof(FbBits), 0,
978706f2543Smrg                      copy_rect_width * Bpp, copy_rect_height,
979706f2543Smrg                      GXcopy, FB_ALLONES, Bpp, 0, 0);
980706f2543Smrg            }
981706f2543Smrg
982706f2543Smrg            gResizeDeathBounds[1] = copy_rect;
983706f2543Smrg            gResizeDeathPix[1]
984706f2543Smrg                = GetScratchPixmapHeader(pScreen, copy_rect_width,
985706f2543Smrg                                         copy_rect_height,
986706f2543Smrg                                         winRec->win->drawable.depth,
987706f2543Smrg                                         winRec->win->drawable.bitsPerPixel,
988706f2543Smrg                                         winRec->bytesPerRow,
989706f2543Smrg                                         (void *) gResizeDeathBits);
990706f2543Smrg
991706f2543Smrg            SetPixmapBaseToScreen(gResizeDeathPix[1],
992706f2543Smrg                                  copy_rect.x1, copy_rect.y1);
993706f2543Smrg
994706f2543Smrg            gResizeDeathCount = 2;
995706f2543Smrg        }
996706f2543Smrg    }
997706f2543Smrg    else if (gravity) {
998706f2543Smrg        /* The general case. Just copy everything. */
999706f2543Smrg
1000706f2543Smrg        RootlessStartDrawing(pWin);
1001706f2543Smrg
1002706f2543Smrg        gResizeDeathBits = malloc(winRec->bytesPerRow * winRec->height);
1003706f2543Smrg
1004706f2543Smrg        memcpy(gResizeDeathBits, winRec->pixelData,
1005706f2543Smrg               winRec->bytesPerRow * winRec->height);
1006706f2543Smrg
1007706f2543Smrg        gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
1008706f2543Smrg        gResizeDeathPix[0]
1009706f2543Smrg            = GetScratchPixmapHeader(pScreen, winRec->width,
1010706f2543Smrg                                     winRec->height,
1011706f2543Smrg                                     winRec->win->drawable.depth,
1012706f2543Smrg                                     winRec->win->drawable.bitsPerPixel,
1013706f2543Smrg                                     winRec->bytesPerRow,
1014706f2543Smrg                                     (void *) gResizeDeathBits);
1015706f2543Smrg
1016706f2543Smrg        SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY);
1017706f2543Smrg        gResizeDeathCount = 1;
1018706f2543Smrg    }
1019706f2543Smrg
1020706f2543Smrg    RootlessStopDrawing(pWin, FALSE);
1021706f2543Smrg
1022706f2543Smrg    winRec->x = newX;
1023706f2543Smrg    winRec->y = newY;
1024706f2543Smrg    winRec->width = newW;
1025706f2543Smrg    winRec->height = newH;
1026706f2543Smrg    winRec->borderWidth = newBW;
1027706f2543Smrg
1028706f2543Smrg    /* Unless both dimensions are getting smaller, Resize the frame
1029706f2543Smrg       before doing gravity repair */
1030706f2543Smrg
1031706f2543Smrg    if (!resize_after) {
1032706f2543Smrg        SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
1033706f2543Smrg                                             newX + SCREEN_TO_GLOBAL_X,
1034706f2543Smrg                                             newY + SCREEN_TO_GLOBAL_Y,
1035706f2543Smrg                                             newW, newH, weight);
1036706f2543Smrg    }
1037706f2543Smrg
1038706f2543Smrg    RootlessStartDrawing(pWin);
1039706f2543Smrg
1040706f2543Smrg    /* If necessary, create a source pixmap pointing at the current
1041706f2543Smrg       window bits. */
1042706f2543Smrg
1043706f2543Smrg    if (need_window_source) {
1044706f2543Smrg        gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
1045706f2543Smrg        gResizeDeathPix[0]
1046706f2543Smrg            = GetScratchPixmapHeader(pScreen, oldW, oldH,
1047706f2543Smrg                                     winRec->win->drawable.depth,
1048706f2543Smrg                                     winRec->win->drawable.bitsPerPixel,
1049706f2543Smrg                                     winRec->bytesPerRow, winRec->pixelData);
1050706f2543Smrg
1051706f2543Smrg        SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY);
1052706f2543Smrg    }
1053706f2543Smrg
1054706f2543Smrg    /* Use custom CopyWindow when moving gravity bits around
1055706f2543Smrg       ResizeWindow assumes the old window contents are in the same
1056706f2543Smrg       pixmap, but here they're in deathPix instead. */
1057706f2543Smrg
1058706f2543Smrg    if (gravity) {
1059706f2543Smrg        gResizeOldCopyWindowProc = pScreen->CopyWindow;
1060706f2543Smrg        pScreen->CopyWindow = RootlessResizeCopyWindow;
1061706f2543Smrg    }
1062706f2543Smrg
1063706f2543Smrg    /* If we can't rely on the window server preserving the bits we
1064706f2543Smrg       need in the position we need, copy the pixels in the
1065706f2543Smrg       intersection from src to dst. ResizeWindow assumes these pixels
1066706f2543Smrg       are already present when making gravity adjustments. pWin
1067706f2543Smrg       currently has new-sized pixmap but is in old position.
1068706f2543Smrg
1069706f2543Smrg       FIXME: border width change! (?) */
1070706f2543Smrg
1071706f2543Smrg    if (gravity && weight == RL_GRAVITY_NONE) {
1072706f2543Smrg        PixmapPtr src, dst;
1073706f2543Smrg
1074706f2543Smrg        assert(gResizeDeathCount == 1);
1075706f2543Smrg
1076706f2543Smrg        src = gResizeDeathPix[0];
1077706f2543Smrg        dst = pScreen->GetWindowPixmap(pWin);
1078706f2543Smrg
1079706f2543Smrg        RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n",
1080706f2543Smrg                     rect.x1, rect.y1, rect.x2, rect.y2);
1081706f2543Smrg
1082706f2543Smrg        /* rect is the intersection of the old location and new location */
1083706f2543Smrg        if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL) {
1084706f2543Smrg            /* The window drawable still has the old frame position, which
1085706f2543Smrg               means that DST doesn't actually point at the origin of our
1086706f2543Smrg               physical backing store when adjusted by the drawable.x,y
1087706f2543Smrg               position. So sneakily adjust it temporarily while copying.. */
1088706f2543Smrg
1089706f2543Smrg            ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData;
1090706f2543Smrg            SetPixmapBaseToScreen(dst, newX, newY);
1091706f2543Smrg
1092706f2543Smrg            fbCopyWindowProc(&src->drawable, &dst->drawable, NULL,
1093706f2543Smrg                             &rect, 1, 0, 0, FALSE, FALSE, 0, 0);
1094706f2543Smrg
1095706f2543Smrg            ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData;
1096706f2543Smrg            SetPixmapBaseToScreen(dst, oldX, oldY);
1097706f2543Smrg        }
1098706f2543Smrg    }
1099706f2543Smrg
1100706f2543Smrg    return resize_after;
1101706f2543Smrg}
1102706f2543Smrg
1103706f2543Smrg
1104706f2543Smrgstatic void
1105706f2543SmrgFinishFrameResize(WindowPtr pWin, Bool gravity, int oldX, int oldY,
1106706f2543Smrg                  unsigned int oldW, unsigned int oldH, unsigned int oldBW,
1107706f2543Smrg                  int newX, int newY, unsigned int newW, unsigned int newH,
1108706f2543Smrg                  unsigned int newBW, Bool resize_now)
1109706f2543Smrg{
1110706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
1111706f2543Smrg    RootlessWindowRec *winRec = WINREC(pWin);
1112706f2543Smrg    int i;
1113706f2543Smrg
1114706f2543Smrg    RootlessStopDrawing(pWin, FALSE);
1115706f2543Smrg
1116706f2543Smrg    if (resize_now) {
1117706f2543Smrg        unsigned int weight;
1118706f2543Smrg
1119706f2543Smrg        /* We didn't resize anything earlier, so do it now, now that
1120706f2543Smrg           we've finished gravitating the bits. */
1121706f2543Smrg
1122706f2543Smrg        weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW,
1123706f2543Smrg                                 newX, newY, newW, newH, newBW);
1124706f2543Smrg
1125706f2543Smrg        SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
1126706f2543Smrg                                             newX + SCREEN_TO_GLOBAL_X,
1127706f2543Smrg                                             newY + SCREEN_TO_GLOBAL_Y,
1128706f2543Smrg                                             newW, newH, weight);
1129706f2543Smrg    }
1130706f2543Smrg
1131706f2543Smrg    /* Redraw everything. FIXME: there must be times when we don't need
1132706f2543Smrg       to do this. Perhaps when top-left weighting and no gravity? */
1133706f2543Smrg
1134706f2543Smrg    RootlessDamageRect(pWin, -newBW, -newBW, newW, newH);
1135706f2543Smrg
1136706f2543Smrg    for (i = 0; i < 2; i++) {
1137706f2543Smrg        if (gResizeDeathPix[i] != NULL) {
1138706f2543Smrg            FreeScratchPixmapHeader(gResizeDeathPix[i]);
1139706f2543Smrg            gResizeDeathPix[i] = NULL;
1140706f2543Smrg        }
1141706f2543Smrg    }
1142706f2543Smrg
1143706f2543Smrg    free(gResizeDeathBits);
1144706f2543Smrg    gResizeDeathBits = NULL;
1145706f2543Smrg
1146706f2543Smrg    if (gravity) {
1147706f2543Smrg        pScreen->CopyWindow = gResizeOldCopyWindowProc;
1148706f2543Smrg    }
1149706f2543Smrg}
1150706f2543Smrg
1151706f2543Smrg
1152706f2543Smrg/*
1153706f2543Smrg * RootlessMoveWindow
1154706f2543Smrg *  If kind==VTOther, window border is resizing (and borderWidth is
1155706f2543Smrg *  already changed!!@#$)  This case works like window resize, not move.
1156706f2543Smrg */
1157706f2543Smrgvoid
1158706f2543SmrgRootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
1159706f2543Smrg{
1160706f2543Smrg    RootlessWindowRec *winRec = WINREC(pWin);
1161706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
1162706f2543Smrg    CopyWindowProcPtr oldCopyWindowProc = NULL;
1163706f2543Smrg    int oldX = 0, oldY = 0, newX = 0, newY = 0;
1164706f2543Smrg    unsigned int oldW = 0, oldH = 0, oldBW = 0;
1165706f2543Smrg    unsigned int newW = 0, newH = 0, newBW = 0;
1166706f2543Smrg    Bool resize_after = FALSE;
1167706f2543Smrg    RegionRec saveRoot;
1168706f2543Smrg
1169706f2543Smrg    RL_DEBUG_MSG("movewindow start \n");
1170706f2543Smrg
1171706f2543Smrg    if (winRec) {
1172706f2543Smrg        if (kind == VTMove) {
1173706f2543Smrg            oldX = winRec->x;
1174706f2543Smrg            oldY = winRec->y;
1175706f2543Smrg            RootlessRedisplay(pWin);
1176706f2543Smrg            RootlessStartDrawing(pWin);
1177706f2543Smrg        } else {
1178706f2543Smrg            RL_DEBUG_MSG("movewindow border resizing ");
1179706f2543Smrg
1180706f2543Smrg            oldBW = winRec->borderWidth;
1181706f2543Smrg            oldX = winRec->x;
1182706f2543Smrg            oldY = winRec->y;
1183706f2543Smrg            oldW = winRec->width;
1184706f2543Smrg            oldH = winRec->height;
1185706f2543Smrg
1186706f2543Smrg            newBW = wBorderWidth(pWin);
1187706f2543Smrg            newX = x;
1188706f2543Smrg            newY = y;
1189706f2543Smrg            newW = pWin->drawable.width  + 2*newBW;
1190706f2543Smrg            newH = pWin->drawable.height + 2*newBW;
1191706f2543Smrg
1192706f2543Smrg            resize_after = StartFrameResize(pWin, FALSE,
1193706f2543Smrg                                            oldX, oldY, oldW, oldH, oldBW,
1194706f2543Smrg                                            newX, newY, newW, newH, newBW);
1195706f2543Smrg        }
1196706f2543Smrg    }
1197706f2543Smrg
1198706f2543Smrg    HUGE_ROOT(pWin);
1199706f2543Smrg    SCREEN_UNWRAP(pScreen, MoveWindow);
1200706f2543Smrg
1201706f2543Smrg    if (winRec) {
1202706f2543Smrg        oldCopyWindowProc = pScreen->CopyWindow;
1203706f2543Smrg        pScreen->CopyWindow = RootlessNoCopyWindow;
1204706f2543Smrg    }
1205706f2543Smrg    pScreen->MoveWindow(pWin, x, y, pSib, kind);
1206706f2543Smrg    if (winRec) {
1207706f2543Smrg        pScreen->CopyWindow = oldCopyWindowProc;
1208706f2543Smrg    }
1209706f2543Smrg
1210706f2543Smrg    NORMAL_ROOT(pWin);
1211706f2543Smrg    SCREEN_WRAP(pScreen, MoveWindow);
1212706f2543Smrg
1213706f2543Smrg    if (winRec) {
1214706f2543Smrg        if (kind == VTMove) {
1215706f2543Smrg            winRec->x = x;
1216706f2543Smrg            winRec->y = y;
1217706f2543Smrg            RootlessStopDrawing(pWin, FALSE);
1218706f2543Smrg            SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen,
1219706f2543Smrg                                               x + SCREEN_TO_GLOBAL_X,
1220706f2543Smrg                                               y + SCREEN_TO_GLOBAL_Y);
1221706f2543Smrg        } else {
1222706f2543Smrg            FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
1223706f2543Smrg                              newX, newY, newW, newH, newBW, resize_after);
1224706f2543Smrg        }
1225706f2543Smrg    }
1226706f2543Smrg
1227706f2543Smrg    RL_DEBUG_MSG("movewindow end\n");
1228706f2543Smrg}
1229706f2543Smrg
1230706f2543Smrg
1231706f2543Smrg/*
1232706f2543Smrg * RootlessResizeWindow
1233706f2543Smrg *  Note: (x, y, w, h) as passed to this procedure don't match the frame
1234706f2543Smrg *  definition. (x,y) is corner of very outer edge, *outside* border.
1235706f2543Smrg *  w,h is width and height *inside* border, *ignoring* border width.
1236706f2543Smrg *  The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw)
1237706f2543Smrg *  is total rect and (x+bw, y+bw, w, h) is inner rect.
1238706f2543Smrg */
1239706f2543Smrgvoid
1240706f2543SmrgRootlessResizeWindow(WindowPtr pWin, int x, int y,
1241706f2543Smrg                     unsigned int w, unsigned int h, WindowPtr pSib)
1242706f2543Smrg{
1243706f2543Smrg    RootlessWindowRec *winRec = WINREC(pWin);
1244706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
1245706f2543Smrg    int oldX = 0, oldY = 0, newX = 0, newY = 0;
1246706f2543Smrg    unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0;
1247706f2543Smrg    Bool resize_after = FALSE;
1248706f2543Smrg    RegionRec saveRoot;
1249706f2543Smrg
1250706f2543Smrg    RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin);
1251706f2543Smrg
1252706f2543Smrg    if(pWin->parent) {
1253706f2543Smrg        if (winRec) {
1254706f2543Smrg            oldBW = winRec->borderWidth;
1255706f2543Smrg            oldX = winRec->x;
1256706f2543Smrg            oldY = winRec->y;
1257706f2543Smrg            oldW = winRec->width;
1258706f2543Smrg            oldH = winRec->height;
1259706f2543Smrg
1260706f2543Smrg            newBW = oldBW;
1261706f2543Smrg            newX = x;
1262706f2543Smrg            newY = y;
1263706f2543Smrg            newW = w + 2*newBW;
1264706f2543Smrg            newH = h + 2*newBW;
1265706f2543Smrg
1266706f2543Smrg            resize_after = StartFrameResize(pWin, TRUE,
1267706f2543Smrg                                            oldX, oldY, oldW, oldH, oldBW,
1268706f2543Smrg                                            newX, newY, newW, newH, newBW);
1269706f2543Smrg        }
1270706f2543Smrg
1271706f2543Smrg        HUGE_ROOT(pWin);
1272706f2543Smrg        SCREEN_UNWRAP(pScreen, ResizeWindow);
1273706f2543Smrg        pScreen->ResizeWindow(pWin, x, y, w, h, pSib);
1274706f2543Smrg        SCREEN_WRAP(pScreen, ResizeWindow);
1275706f2543Smrg        NORMAL_ROOT(pWin);
1276706f2543Smrg
1277706f2543Smrg        if (winRec) {
1278706f2543Smrg            FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
1279706f2543Smrg                              newX, newY, newW, newH, newBW, resize_after);
1280706f2543Smrg        }
1281706f2543Smrg    } else {
1282706f2543Smrg        /* Special case for resizing the root window */
1283706f2543Smrg        BoxRec box;
1284706f2543Smrg
1285706f2543Smrg        pWin->drawable.x = x;
1286706f2543Smrg        pWin->drawable.y = y;
1287706f2543Smrg        pWin->drawable.width = w;
1288706f2543Smrg        pWin->drawable.height = h;
1289706f2543Smrg
1290706f2543Smrg        box.x1 = x; box.y1 = y;
1291706f2543Smrg        box.x2 = x + w; box.y2 = y + h;
1292706f2543Smrg        RegionUninit(&pWin->winSize);
1293706f2543Smrg        RegionInit(&pWin->winSize, &box, 1);
1294706f2543Smrg        RegionCopy(&pWin->borderSize, &pWin->winSize);
1295706f2543Smrg        RegionCopy(&pWin->clipList, &pWin->winSize);
1296706f2543Smrg        RegionCopy(&pWin->borderClip, &pWin->winSize);
1297706f2543Smrg
1298706f2543Smrg        if (winRec) {
1299706f2543Smrg            SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
1300706f2543Smrg                                                 x + SCREEN_TO_GLOBAL_X,
1301706f2543Smrg                                                 y + SCREEN_TO_GLOBAL_Y,
1302706f2543Smrg                                                 w, h, RL_GRAVITY_NONE);
1303706f2543Smrg        }
1304706f2543Smrg
1305706f2543Smrg        miSendExposures(pWin, &pWin->borderClip,
1306706f2543Smrg                        pWin->drawable.x, pWin->drawable.y);
1307706f2543Smrg    }
1308706f2543Smrg
1309706f2543Smrg    RL_DEBUG_MSG("resizewindow end\n");
1310706f2543Smrg}
1311706f2543Smrg
1312706f2543Smrg
1313706f2543Smrg/*
1314706f2543Smrg * RootlessRepositionWindow
1315706f2543Smrg *  Called by the implementation when a window needs to be repositioned to
1316706f2543Smrg *  its correct location on the screen. This routine is typically needed
1317706f2543Smrg *  due to changes in the underlying window system, such as a screen layout
1318706f2543Smrg *  change.
1319706f2543Smrg */
1320706f2543Smrgvoid
1321706f2543SmrgRootlessRepositionWindow(WindowPtr pWin)
1322706f2543Smrg{
1323706f2543Smrg    RootlessWindowRec *winRec = WINREC(pWin);
1324706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
1325706f2543Smrg
1326706f2543Smrg    if (winRec == NULL)
1327706f2543Smrg        return;
1328706f2543Smrg
1329706f2543Smrg    RootlessStopDrawing(pWin, FALSE);
1330706f2543Smrg    SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen,
1331706f2543Smrg                                       winRec->x + SCREEN_TO_GLOBAL_X,
1332706f2543Smrg                                       winRec->y + SCREEN_TO_GLOBAL_Y);
1333706f2543Smrg
1334706f2543Smrg    RootlessReorderWindow(pWin);
1335706f2543Smrg}
1336706f2543Smrg
1337706f2543Smrg
1338706f2543Smrg/*
1339706f2543Smrg * RootlessReparentWindow
1340706f2543Smrg *  Called after a window has been reparented. Generally windows are not
1341706f2543Smrg *  framed until they are mapped. However, a window may be framed early by the
1342706f2543Smrg *  implementation calling RootlessFrameForWindow. (e.g. this could be needed
1343706f2543Smrg *  to attach a VRAM surface to it.) If the window is subsequently reparented
1344706f2543Smrg *  by the window manager before being mapped, we need to give the frame to
1345706f2543Smrg *  the new top-level window.
1346706f2543Smrg */
1347706f2543Smrgvoid
1348706f2543SmrgRootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent)
1349706f2543Smrg{
1350706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
1351706f2543Smrg    RootlessWindowRec *winRec = WINREC(pWin);
1352706f2543Smrg    WindowPtr pTopWin;
1353706f2543Smrg
1354706f2543Smrg    /* Check that window is not top-level now, but used to be. */
1355706f2543Smrg    if (IsRoot(pWin) || IsRoot(pWin->parent)
1356706f2543Smrg        || IsTopLevel(pWin) || winRec == NULL)
1357706f2543Smrg    {
1358706f2543Smrg        goto out;
1359706f2543Smrg    }
1360706f2543Smrg
1361706f2543Smrg    /* If the formerly top-level window has a frame, we want to give the
1362706f2543Smrg       frame to its new top-level parent. If we can't do that, we'll just
1363706f2543Smrg       have to jettison it... */
1364706f2543Smrg
1365706f2543Smrg    pTopWin = TopLevelParent(pWin);
1366706f2543Smrg    assert(pTopWin != pWin);
1367706f2543Smrg
1368706f2543Smrg    pWin->rootlessUnhittable = FALSE;
1369706f2543Smrg
1370706f2543Smrg    DeleteProperty (serverClient, pWin, xa_native_window_id ());
1371706f2543Smrg
1372706f2543Smrg    if (WINREC(pTopWin) != NULL) {
1373706f2543Smrg        /* We're screwed. */
1374706f2543Smrg        RootlessDestroyFrame(pWin, winRec);
1375706f2543Smrg    } else {
1376706f2543Smrg        if (!pTopWin->realized && pWin->realized) {
1377706f2543Smrg            SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid);
1378706f2543Smrg        }
1379706f2543Smrg
1380706f2543Smrg        /* Switch the frame record from one to the other. */
1381706f2543Smrg
1382706f2543Smrg        SETWINREC(pWin, NULL);
1383706f2543Smrg        SETWINREC(pTopWin, winRec);
1384706f2543Smrg
1385706f2543Smrg        RootlessInitializeFrame(pTopWin, winRec);
1386706f2543Smrg        RootlessReshapeFrame(pTopWin);
1387706f2543Smrg
1388706f2543Smrg        SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
1389706f2543Smrg                                             winRec->x + SCREEN_TO_GLOBAL_X,
1390706f2543Smrg                                             winRec->y + SCREEN_TO_GLOBAL_Y,
1391706f2543Smrg                                             winRec->width, winRec->height,
1392706f2543Smrg                                             RL_GRAVITY_NONE);
1393706f2543Smrg
1394706f2543Smrg        if (SCREENREC(pScreen)->imp->SwitchWindow) {
1395706f2543Smrg            SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin);
1396706f2543Smrg        }
1397706f2543Smrg
1398706f2543Smrg        if (pTopWin->realized && !pWin->realized)
1399706f2543Smrg            winRec->is_reorder_pending = TRUE;
1400706f2543Smrg    }
1401706f2543Smrg
1402706f2543Smrgout:
1403706f2543Smrg    if (SCREENREC(pScreen)->ReparentWindow) {
1404706f2543Smrg        SCREEN_UNWRAP(pScreen, ReparentWindow);
1405706f2543Smrg        pScreen->ReparentWindow(pWin, pPriorParent);
1406706f2543Smrg        SCREEN_WRAP(pScreen, ReparentWindow);
1407706f2543Smrg    }
1408706f2543Smrg}
1409706f2543Smrg
1410706f2543Smrg
1411706f2543Smrgvoid
1412706f2543SmrgRootlessFlushWindowColormap (WindowPtr pWin)
1413706f2543Smrg{
1414706f2543Smrg  RootlessWindowRec *winRec = WINREC (pWin);
1415706f2543Smrg  ScreenPtr pScreen = pWin->drawable.pScreen;
1416706f2543Smrg
1417706f2543Smrg  if (winRec == NULL)
1418706f2543Smrg    return;
1419706f2543Smrg
1420706f2543Smrg  RootlessStopDrawing (pWin, FALSE);
1421706f2543Smrg
1422706f2543Smrg  if (SCREENREC(pScreen)->imp->UpdateColormap)
1423706f2543Smrg    SCREENREC(pScreen)->imp->UpdateColormap(winRec->wid, pScreen);
1424706f2543Smrg}
1425706f2543Smrg
1426706f2543Smrg/*
1427706f2543Smrg * RootlessChangeBorderWidth
1428706f2543Smrg *  FIXME: untested!
1429706f2543Smrg *  pWin inside corner stays the same; pWin->drawable.[xy] stays the same
1430706f2543Smrg *  Frame moves and resizes.
1431706f2543Smrg */
1432706f2543Smrgvoid
1433706f2543SmrgRootlessChangeBorderWidth(WindowPtr pWin, unsigned int width)
1434706f2543Smrg{
1435706f2543Smrg    RegionRec saveRoot;
1436706f2543Smrg    Bool resize_after = FALSE;
1437706f2543Smrg
1438706f2543Smrg    RL_DEBUG_MSG("change border width ");
1439706f2543Smrg
1440706f2543Smrg    if (width != wBorderWidth(pWin)) {
1441706f2543Smrg        RootlessWindowRec *winRec = WINREC(pWin);
1442706f2543Smrg        int oldX = 0, oldY = 0, newX = 0, newY = 0;
1443706f2543Smrg        unsigned int oldW = 0, oldH = 0, oldBW = 0;
1444706f2543Smrg        unsigned int newW = 0, newH = 0, newBW = 0;
1445706f2543Smrg
1446706f2543Smrg        if (winRec) {
1447706f2543Smrg            oldBW = winRec->borderWidth;
1448706f2543Smrg            oldX = winRec->x;
1449706f2543Smrg            oldY = winRec->y;
1450706f2543Smrg            oldW = winRec->width;
1451706f2543Smrg            oldH = winRec->height;
1452706f2543Smrg
1453706f2543Smrg            newBW = width;
1454706f2543Smrg            newX = pWin->drawable.x - newBW;
1455706f2543Smrg            newY = pWin->drawable.y - newBW;
1456706f2543Smrg            newW = pWin->drawable.width  + 2*newBW;
1457706f2543Smrg            newH = pWin->drawable.height + 2*newBW;
1458706f2543Smrg
1459706f2543Smrg            resize_after = StartFrameResize(pWin, FALSE,
1460706f2543Smrg                                            oldX, oldY, oldW, oldH, oldBW,
1461706f2543Smrg                                            newX, newY, newW, newH, newBW);
1462706f2543Smrg        }
1463706f2543Smrg
1464706f2543Smrg        HUGE_ROOT(pWin);
1465706f2543Smrg        SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth);
1466706f2543Smrg        pWin->drawable.pScreen->ChangeBorderWidth(pWin, width);
1467706f2543Smrg        SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth);
1468706f2543Smrg        NORMAL_ROOT(pWin);
1469706f2543Smrg
1470706f2543Smrg        if (winRec) {
1471706f2543Smrg            FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
1472706f2543Smrg                              newX, newY, newW, newH, newBW, resize_after);
1473706f2543Smrg        }
1474706f2543Smrg    }
1475706f2543Smrg
1476706f2543Smrg    RL_DEBUG_MSG("change border width end\n");
1477706f2543Smrg}
1478706f2543Smrg
1479706f2543Smrg/*
1480706f2543Smrg * RootlessOrderAllWindows
1481706f2543Smrg * Brings all X11 windows to the top of the window stack
1482706f2543Smrg * (i.e in front of Aqua windows) -- called when X11.app is given focus
1483706f2543Smrg */
1484706f2543Smrgvoid
1485706f2543SmrgRootlessOrderAllWindows (Bool include_unhitable)
1486706f2543Smrg{
1487706f2543Smrg    int i;
1488706f2543Smrg    WindowPtr pWin;
1489706f2543Smrg
1490706f2543Smrg    if (windows_hidden)
1491706f2543Smrg        return;
1492706f2543Smrg
1493706f2543Smrg    RL_DEBUG_MSG("RootlessOrderAllWindows() ");
1494706f2543Smrg    for (i = 0; i < screenInfo.numScreens; i++) {
1495706f2543Smrg      if (screenInfo.screens[i] == NULL) continue;
1496706f2543Smrg      pWin = screenInfo.screens[i]->root;
1497706f2543Smrg      if (pWin == NULL) continue;
1498706f2543Smrg
1499706f2543Smrg      for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) {
1500706f2543Smrg	if (!pWin->realized) continue;
1501706f2543Smrg	if (RootlessEnsureFrame(pWin) == NULL) continue;
1502706f2543Smrg        if (!include_unhitable && pWin->rootlessUnhittable) continue;
1503706f2543Smrg	RootlessReorderWindow (pWin);
1504706f2543Smrg      }
1505706f2543Smrg    }
1506706f2543Smrg    RL_DEBUG_MSG("RootlessOrderAllWindows() done");
1507706f2543Smrg}
1508706f2543Smrg
1509706f2543Smrgvoid
1510706f2543SmrgRootlessEnableRoot (ScreenPtr pScreen)
1511706f2543Smrg{
1512706f2543Smrg    WindowPtr pRoot;
1513706f2543Smrg    pRoot = pScreen->root;
1514706f2543Smrg
1515706f2543Smrg    RootlessEnsureFrame (pRoot);
1516706f2543Smrg    (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE);
1517706f2543Smrg    RootlessReorderWindow (pRoot);
1518706f2543Smrg}
1519706f2543Smrg
1520706f2543Smrgvoid
1521706f2543SmrgRootlessDisableRoot (ScreenPtr pScreen)
1522706f2543Smrg{
1523706f2543Smrg    WindowPtr pRoot;
1524706f2543Smrg    RootlessWindowRec *winRec;
1525706f2543Smrg
1526706f2543Smrg    pRoot = pScreen->root;
1527706f2543Smrg    winRec = WINREC (pRoot);
1528706f2543Smrg
1529706f2543Smrg    if (NULL == winRec)
1530706f2543Smrg	return;
1531706f2543Smrg
1532706f2543Smrg    RootlessDestroyFrame (pRoot, winRec);
1533706f2543Smrg    DeleteProperty (serverClient, pRoot, xa_native_window_id ());
1534706f2543Smrg}
1535706f2543Smrg
1536706f2543Smrgvoid
1537706f2543SmrgRootlessHideAllWindows (void)
1538706f2543Smrg{
1539706f2543Smrg    int i;
1540706f2543Smrg    ScreenPtr pScreen;
1541706f2543Smrg    WindowPtr pWin;
1542706f2543Smrg    RootlessWindowRec *winRec;
1543706f2543Smrg
1544706f2543Smrg    if (windows_hidden)
1545706f2543Smrg        return;
1546706f2543Smrg
1547706f2543Smrg    windows_hidden = TRUE;
1548706f2543Smrg
1549706f2543Smrg    for (i = 0; i < screenInfo.numScreens; i++)
1550706f2543Smrg    {
1551706f2543Smrg        pScreen = screenInfo.screens[i];
1552706f2543Smrg	if (pScreen == NULL)
1553706f2543Smrg	    continue;
1554706f2543Smrg	pWin = pScreen->root;
1555706f2543Smrg	if (pWin == NULL)
1556706f2543Smrg            continue;
1557706f2543Smrg
1558706f2543Smrg        for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
1559706f2543Smrg        {
1560706f2543Smrg            if (!pWin->realized)
1561706f2543Smrg                continue;
1562706f2543Smrg
1563706f2543Smrg            RootlessStopDrawing (pWin, FALSE);
1564706f2543Smrg
1565706f2543Smrg            winRec = WINREC (pWin);
1566706f2543Smrg            if (winRec != NULL)
1567706f2543Smrg            {
1568706f2543Smrg              if (SCREENREC(pScreen)->imp->HideWindow)
1569706f2543Smrg                SCREENREC(pScreen)->imp->HideWindow(winRec->wid);
1570706f2543Smrg            }
1571706f2543Smrg        }
1572706f2543Smrg    }
1573706f2543Smrg}
1574706f2543Smrg
1575706f2543Smrgvoid
1576706f2543SmrgRootlessShowAllWindows (void)
1577706f2543Smrg{
1578706f2543Smrg    int i;
1579706f2543Smrg    ScreenPtr pScreen;
1580706f2543Smrg    WindowPtr pWin;
1581706f2543Smrg    RootlessWindowRec *winRec;
1582706f2543Smrg
1583706f2543Smrg    if (!windows_hidden)
1584706f2543Smrg        return;
1585706f2543Smrg
1586706f2543Smrg    windows_hidden = FALSE;
1587706f2543Smrg
1588706f2543Smrg    for (i = 0; i < screenInfo.numScreens; i++)
1589706f2543Smrg    {
1590706f2543Smrg        pScreen = screenInfo.screens[i];
1591706f2543Smrg	if (pScreen == NULL)
1592706f2543Smrg	    continue;
1593706f2543Smrg	pWin = pScreen->root;
1594706f2543Smrg	if (pWin == NULL)
1595706f2543Smrg            continue;
1596706f2543Smrg
1597706f2543Smrg        for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
1598706f2543Smrg        {
1599706f2543Smrg            if (!pWin->realized)
1600706f2543Smrg                continue;
1601706f2543Smrg
1602706f2543Smrg            winRec = RootlessEnsureFrame (pWin);
1603706f2543Smrg            if (winRec == NULL)
1604706f2543Smrg                continue;
1605706f2543Smrg
1606706f2543Smrg            RootlessReorderWindow (pWin);
1607706f2543Smrg        }
1608706f2543Smrg
1609706f2543Smrg        RootlessScreenExpose (pScreen);
1610706f2543Smrg    }
1611706f2543Smrg}
1612706f2543Smrg
1613706f2543Smrg/*
1614706f2543Smrg * SetPixmapOfAncestors
1615706f2543Smrg *  Set the Pixmaps on all ParentRelative windows up the ancestor chain.
1616706f2543Smrg */
1617706f2543Smrgvoid
1618706f2543SmrgRootlessSetPixmapOfAncestors(WindowPtr pWin)
1619706f2543Smrg{
1620706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
1621706f2543Smrg    WindowPtr topWin = TopLevelParent(pWin);
1622706f2543Smrg    RootlessWindowRec *topWinRec = WINREC(topWin);
1623706f2543Smrg
1624706f2543Smrg    while (pWin->backgroundState == ParentRelative) {
1625706f2543Smrg        if (pWin == topWin) {
1626706f2543Smrg            // disallow ParentRelative background state on top level
1627706f2543Smrg            XID pixel = 0;
1628706f2543Smrg            ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
1629706f2543Smrg            RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin);
1630706f2543Smrg            break;
1631706f2543Smrg        }
1632706f2543Smrg
1633706f2543Smrg        pWin = pWin->parent;
1634706f2543Smrg        pScreen->SetWindowPixmap(pWin, topWinRec->pixmap);
1635706f2543Smrg    }
1636706f2543Smrg}
1637706f2543Smrg
1638