~gerchanovsky/xorg-server/trusty

« back to all changes in this revision

Viewing changes to miext/rootless/rootlessWindow.c

  • Committer: Package Import Robot
  • Author(s): Timo Aaltonen
  • Date: 2016-01-13 00:01:28 UTC
  • Revision ID: package-import@ubuntu.com-20160113000128-oc1wb1mr1zfjqlm5
Tags: upstream-1.17.2
ImportĀ upstreamĀ versionĀ 1.17.2

Show diffs side-by-side

added added

removed removed

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