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