~hypodermia/ubuntu/oneiric/compiz/fix-for-bug-301174

« back to all changes in this revision

Viewing changes to .pc/000_fix_stacking.patch/src/window.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2011-02-24 17:31:29 UTC
  • mfrom: (0.167.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20110224173129-hsczyk7yw7s21flf
Tags: 1:0.9.4-0ubuntu1
* New upstream release:
  - Fix no windows receiving the focus if someone got the focus then was
    destroyed
  - Fix crash when resizing using keybindings
  - Fix unresponsive inactive decorations (LP: #703755) 
  - Fix the long awaited gconf crash (LP: #691561)
  - gtk-window-decorator doesn't respect special decoration styles
    (LP: #290835)
* debian/compiz-core.links,
  debian/source_compiz.py,
  debian/compiz-core.install:
  - install again a richer apport hook to redirect nux/libunity/unityshell
    crash. It also asks the user to redirect unity issues against unity (still
    incuding xorg info when needed)
* Removed a bunch of patches either cherry-picked or pushed upstream. With the
  other fixes, the gconf workaround is hopefully not needed anymore.
* refresh existing patches to still apply
* debian/control:
  - rename dep on compiz-fusion* to compiz*
* debian/patches/085_add_grid_plugin.patch:
  - refresh the grid plugin from new release
* debian/patches/086_new_grid_defaults.patch
  - separate tweaking the default settings to only have the effect that were
    specified:
    top -> maximize, left (top or bottom left) -> window half left of the
    screen, right (top or bottom right) -> window half right of the screen,
    bottom -> do nothing

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © 2005 Novell, Inc.
3
 
 *
4
 
 * Permission to use, copy, modify, distribute, and sell this software
5
 
 * and its documentation for any purpose is hereby granted without
6
 
 * fee, provided that the above copyright notice appear in all copies
7
 
 * and that both that copyright notice and this permission notice
8
 
 * appear in supporting documentation, and that the name of
9
 
 * Novell, Inc. not be used in advertising or publicity pertaining to
10
 
 * distribution of the software without specific, written prior permission.
11
 
 * Novell, Inc. makes no representations about the suitability of this
12
 
 * software for any purpose. It is provided "as is" without express or
13
 
 * implied warranty.
14
 
 *
15
 
 * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
 
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17
 
 * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
 
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19
 
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20
 
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21
 
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
 
 *
23
 
 * Author: David Reveman <davidr@novell.com>
24
 
 */
25
 
 
26
 
#include <compiz.h>
27
 
 
28
 
#include <X11/Xlib.h>
29
 
#include <X11/Xatom.h>
30
 
#include <X11/Xproto.h>
31
 
#include <X11/extensions/shape.h>
32
 
 
33
 
#include <stdio.h>
34
 
#include <string.h>
35
 
#include <strings.h>
36
 
#include <stdlib.h>
37
 
#include <stdint.h>
38
 
#include <assert.h>
39
 
#include <math.h>
40
 
 
41
 
#include <boost/bind.hpp>
42
 
 
43
 
#include <core/core.h>
44
 
#include <core/icon.h>
45
 
#include <core/atoms.h>
46
 
#include "privatewindow.h"
47
 
#include "privatescreen.h"
48
 
 
49
 
PluginClassStorage::Indices windowPluginClassIndices (0);
50
 
 
51
 
unsigned int
52
 
CompWindow::allocPluginClassIndex ()
53
 
{
54
 
    unsigned int i = PluginClassStorage::allocatePluginClassIndex (windowPluginClassIndices);
55
 
 
56
 
    foreach (CompWindow *w, screen->windows ())
57
 
        if (windowPluginClassIndices.size () != w->pluginClasses.size ())
58
 
            w->pluginClasses.resize (windowPluginClassIndices.size ());
59
 
 
60
 
    return i;
61
 
}
62
 
 
63
 
void
64
 
CompWindow::freePluginClassIndex (unsigned int index)
65
 
{
66
 
    PluginClassStorage::freePluginClassIndex (windowPluginClassIndices, index);
67
 
 
68
 
    foreach (CompWindow *w, ::screen->windows ())
69
 
        if (windowPluginClassIndices.size () != w->pluginClasses.size ())
70
 
            w->pluginClasses.resize (windowPluginClassIndices.size ());
71
 
}
72
 
 
73
 
bool
74
 
PrivateWindow::isAncestorTo (CompWindow *transient,
75
 
                             CompWindow *ancestor)
76
 
{
77
 
    if (transient->priv->transientFor)
78
 
    {
79
 
        if (transient->priv->transientFor == ancestor->priv->id)
80
 
            return true;
81
 
 
82
 
        transient = screen->findWindow (transient->priv->transientFor);
83
 
        if (transient)
84
 
            return isAncestorTo (transient, ancestor);
85
 
    }
86
 
 
87
 
    return false;
88
 
}
89
 
 
90
 
void
91
 
PrivateWindow::recalcNormalHints ()
92
 
{
93
 
    int maxSize;
94
 
 
95
 
#warning fixme to max Texture size
96
 
    maxSize  = MAXSHORT;
97
 
    maxSize -= serverGeometry.border () * 2;
98
 
 
99
 
    sizeHints.x      = serverGeometry.x ();
100
 
    sizeHints.y      = serverGeometry.y ();
101
 
    sizeHints.width  = serverGeometry.width ();
102
 
    sizeHints.height = serverGeometry.height ();
103
 
 
104
 
    if (!(sizeHints.flags & PBaseSize))
105
 
    {
106
 
        if (sizeHints.flags & PMinSize)
107
 
        {
108
 
            sizeHints.base_width  = sizeHints.min_width;
109
 
            sizeHints.base_height = sizeHints.min_height;
110
 
        }
111
 
        else
112
 
        {
113
 
            sizeHints.base_width  = 0;
114
 
            sizeHints.base_height = 0;
115
 
        }
116
 
 
117
 
        sizeHints.flags |= PBaseSize;
118
 
    }
119
 
 
120
 
    if (!(sizeHints.flags & PMinSize))
121
 
    {
122
 
        sizeHints.min_width  = sizeHints.base_width;
123
 
        sizeHints.min_height = sizeHints.base_height;
124
 
        sizeHints.flags |= PMinSize;
125
 
    }
126
 
 
127
 
    if (!(sizeHints.flags & PMaxSize))
128
 
    {
129
 
        sizeHints.max_width  = 65535;
130
 
        sizeHints.max_height = 65535;
131
 
        sizeHints.flags |= PMaxSize;
132
 
    }
133
 
 
134
 
    if (sizeHints.max_width < sizeHints.min_width)
135
 
        sizeHints.max_width = sizeHints.min_width;
136
 
 
137
 
    if (sizeHints.max_height < sizeHints.min_height)
138
 
        sizeHints.max_height = sizeHints.min_height;
139
 
 
140
 
    if (sizeHints.min_width < 1)
141
 
        sizeHints.min_width = 1;
142
 
 
143
 
    if (sizeHints.max_width < 1)
144
 
        sizeHints.max_width = 1;
145
 
 
146
 
    if (sizeHints.min_height < 1)
147
 
        sizeHints.min_height = 1;
148
 
 
149
 
    if (sizeHints.max_height < 1)
150
 
        sizeHints.max_height = 1;
151
 
 
152
 
    if (sizeHints.max_width > maxSize)
153
 
        sizeHints.max_width = maxSize;
154
 
 
155
 
    if (sizeHints.max_height > maxSize)
156
 
        sizeHints.max_height = maxSize;
157
 
 
158
 
    if (sizeHints.min_width > maxSize)
159
 
        sizeHints.min_width = maxSize;
160
 
 
161
 
    if (sizeHints.min_height > maxSize)
162
 
        sizeHints.min_height = maxSize;
163
 
 
164
 
    if (sizeHints.base_width > maxSize)
165
 
        sizeHints.base_width = maxSize;
166
 
 
167
 
    if (sizeHints.base_height > maxSize)
168
 
        sizeHints.base_height = maxSize;
169
 
 
170
 
    if (sizeHints.flags & PResizeInc)
171
 
    {
172
 
        if (sizeHints.width_inc == 0)
173
 
            sizeHints.width_inc = 1;
174
 
 
175
 
        if (sizeHints.height_inc == 0)
176
 
            sizeHints.height_inc = 1;
177
 
    }
178
 
    else
179
 
    {
180
 
        sizeHints.width_inc  = 1;
181
 
        sizeHints.height_inc = 1;
182
 
        sizeHints.flags |= PResizeInc;
183
 
    }
184
 
 
185
 
    if (sizeHints.flags & PAspect)
186
 
    {
187
 
        /* don't divide by 0 */
188
 
        if (sizeHints.min_aspect.y < 1)
189
 
            sizeHints.min_aspect.y = 1;
190
 
 
191
 
        if (sizeHints.max_aspect.y < 1)
192
 
            sizeHints.max_aspect.y = 1;
193
 
    }
194
 
    else
195
 
    {
196
 
        sizeHints.min_aspect.x = 1;
197
 
        sizeHints.min_aspect.y = 65535;
198
 
        sizeHints.max_aspect.x = 65535;
199
 
        sizeHints.max_aspect.y = 1;
200
 
        sizeHints.flags |= PAspect;
201
 
    }
202
 
 
203
 
    if (!(sizeHints.flags & PWinGravity))
204
 
    {
205
 
        sizeHints.win_gravity = NorthWestGravity;
206
 
        sizeHints.flags |= PWinGravity;
207
 
    }
208
 
}
209
 
 
210
 
void
211
 
PrivateWindow::updateNormalHints ()
212
 
{
213
 
    Status status;
214
 
    long   supplied;
215
 
 
216
 
    status = XGetWMNormalHints (screen->dpy (), priv->id,
217
 
                                &priv->sizeHints, &supplied);
218
 
 
219
 
    if (!status)
220
 
        priv->sizeHints.flags = 0;
221
 
 
222
 
    priv->recalcNormalHints ();
223
 
}
224
 
 
225
 
void
226
 
PrivateWindow::updateWmHints ()
227
 
{
228
 
    XWMHints *newHints;
229
 
    long     dFlags = 0;
230
 
    bool     iconChanged = false;
231
 
 
232
 
    if (hints)
233
 
        dFlags = hints->flags;
234
 
 
235
 
    inputHint = true;
236
 
 
237
 
    newHints = XGetWMHints (screen->dpy (), id);
238
 
    if (newHints)
239
 
    {
240
 
        dFlags ^= newHints->flags;
241
 
 
242
 
        if (newHints->flags & InputHint)
243
 
            inputHint = newHints->input;
244
 
 
245
 
        if (hints)
246
 
        {
247
 
            if ((newHints->flags & IconPixmapHint) &&
248
 
                (hints->icon_pixmap != newHints->icon_pixmap))
249
 
            {
250
 
                iconChanged = true;
251
 
            }
252
 
            else if ((newHints->flags & IconMaskHint) &&
253
 
                     (hints->icon_mask != newHints->icon_mask))
254
 
            {
255
 
                iconChanged = true;
256
 
            }
257
 
        }
258
 
    }
259
 
 
260
 
    iconChanged |= (dFlags & (IconPixmapHint | IconMaskHint));
261
 
 
262
 
    if (iconChanged)
263
 
        freeIcons ();
264
 
 
265
 
    if (hints)
266
 
        XFree (hints);
267
 
 
268
 
    hints = newHints;
269
 
}
270
 
 
271
 
void
272
 
PrivateWindow::updateClassHints ()
273
 
{
274
 
    XClassHint classHint;
275
 
    int        status;
276
 
 
277
 
    if (priv->resName)
278
 
    {
279
 
        free (priv->resName);
280
 
        priv->resName = NULL;
281
 
    }
282
 
 
283
 
    if (priv->resClass)
284
 
    {
285
 
        free (priv->resClass);
286
 
        priv->resClass = NULL;
287
 
    }
288
 
 
289
 
    status = XGetClassHint (screen->dpy (),
290
 
                            priv->id, &classHint);
291
 
    if (status)
292
 
    {
293
 
        if (classHint.res_name)
294
 
        {
295
 
            priv->resName = strdup (classHint.res_name);
296
 
            XFree (classHint.res_name);
297
 
        }
298
 
 
299
 
        if (classHint.res_class)
300
 
        {
301
 
            priv->resClass = strdup (classHint.res_class);
302
 
            XFree (classHint.res_class);
303
 
        }
304
 
    }
305
 
}
306
 
 
307
 
void
308
 
PrivateWindow::updateTransientHint ()
309
 
{
310
 
    Window transientFor;
311
 
    Status status;
312
 
 
313
 
    priv->transientFor = None;
314
 
 
315
 
    status = XGetTransientForHint (screen->dpy (),
316
 
                                   priv->id, &transientFor);
317
 
 
318
 
    if (status)
319
 
    {
320
 
        CompWindow *ancestor;
321
 
 
322
 
        ancestor = screen->findWindow (transientFor);
323
 
        if (!ancestor)
324
 
            return;
325
 
 
326
 
        /* protect against circular transient dependencies */
327
 
        if (transientFor == priv->id ||
328
 
            PrivateWindow::isAncestorTo (ancestor, window))
329
 
            return;
330
 
 
331
 
        priv->transientFor = transientFor;
332
 
    }
333
 
}
334
 
 
335
 
void
336
 
PrivateWindow::updateIconGeometry ()
337
 
{
338
 
    Atom          actual;
339
 
    int           result, format;
340
 
    unsigned long n, left;
341
 
    unsigned char *data;
342
 
 
343
 
    priv->iconGeometry.setGeometry (0, 0, 0, 0);
344
 
 
345
 
    result = XGetWindowProperty (screen->dpy (), priv->id,
346
 
                                 Atoms::wmIconGeometry,
347
 
                                 0L, 1024L, False, XA_CARDINAL,
348
 
                                 &actual, &format, &n, &left, &data);
349
 
 
350
 
    if (result == Success && data)
351
 
    {
352
 
        if (n == 4)
353
 
        {
354
 
            unsigned long *geometry = (unsigned long *) data;
355
 
 
356
 
            priv->iconGeometry.setX (geometry[0]);
357
 
            priv->iconGeometry.setY (geometry[1]);
358
 
            priv->iconGeometry.setWidth (geometry[2]);
359
 
            priv->iconGeometry.setHeight (geometry[3]);
360
 
        }
361
 
 
362
 
        XFree (data);
363
 
    }
364
 
}
365
 
 
366
 
Window
367
 
PrivateWindow::getClientLeaderOfAncestor ()
368
 
{
369
 
    if (transientFor)
370
 
    {
371
 
        CompWindow *w = screen->findWindow (transientFor);
372
 
        if (w)
373
 
        {
374
 
            if (w->priv->clientLeader)
375
 
                return w->priv->clientLeader;
376
 
 
377
 
            return w->priv->getClientLeaderOfAncestor ();
378
 
        }
379
 
    }
380
 
 
381
 
    return None;
382
 
}
383
 
 
384
 
Window
385
 
PrivateWindow::getClientLeader ()
386
 
{
387
 
    Atom          actual;
388
 
    int           result, format;
389
 
    unsigned long n, left;
390
 
    unsigned char *data;
391
 
 
392
 
    result = XGetWindowProperty (screen->dpy (), priv->id,
393
 
                                 Atoms::wmClientLeader,
394
 
                                 0L, 1L, False, XA_WINDOW, &actual, &format,
395
 
                                 &n, &left, &data);
396
 
 
397
 
    if (result == Success && data)
398
 
    {
399
 
        Window win = None;
400
 
 
401
 
        if (n)
402
 
            memcpy (&win, data, sizeof (Window));
403
 
 
404
 
        XFree ((void *) data);
405
 
 
406
 
        if (win)
407
 
            return win;
408
 
    }
409
 
 
410
 
    return priv->getClientLeaderOfAncestor ();
411
 
}
412
 
 
413
 
char *
414
 
PrivateWindow::getStartupId ()
415
 
{
416
 
    Atom          actual;
417
 
    int           result, format;
418
 
    unsigned long n, left;
419
 
    unsigned char *data;
420
 
 
421
 
    result = XGetWindowProperty (screen->dpy (), priv->id,
422
 
                                 Atoms::startupId,
423
 
                                 0L, 1024L, False,
424
 
                                 Atoms::utf8String,
425
 
                                 &actual, &format,
426
 
                                 &n, &left, &data);
427
 
 
428
 
    if (result == Success && data)
429
 
    {
430
 
        char *id = NULL;
431
 
 
432
 
        if (n)
433
 
            id = strdup ((char *) data);
434
 
        XFree ((void *) data);
435
 
 
436
 
        return id;
437
 
    }
438
 
 
439
 
    return NULL;
440
 
}
441
 
 
442
 
void
443
 
PrivateWindow::setFullscreenMonitors (CompFullscreenMonitorSet *monitors)
444
 
{
445
 
    bool         hadFsMonitors = fullscreenMonitorsSet;
446
 
    unsigned int outputs = screen->outputDevs ().size ();
447
 
 
448
 
    fullscreenMonitorsSet = false;
449
 
 
450
 
    if (monitors                   &&
451
 
        (unsigned int) monitors->left   < outputs &&
452
 
        (unsigned int) monitors->right  < outputs &&
453
 
        (unsigned int) monitors->top    < outputs &&
454
 
        (unsigned int) monitors->bottom < outputs)
455
 
    {
456
 
        CompRect fsRect (screen->outputDevs ()[monitors->left].x1 (),
457
 
                         screen->outputDevs ()[monitors->top].y1 (),
458
 
                         screen->outputDevs ()[monitors->right].x2 (),
459
 
                         screen->outputDevs ()[monitors->bottom].y2 ());
460
 
 
461
 
        if (fsRect.x1 () < fsRect.x2 () && fsRect.y1 () < fsRect.y2 ())
462
 
        {
463
 
            fullscreenMonitorsSet = true;
464
 
            fullscreenMonitorRect = fsRect;
465
 
        }
466
 
    }
467
 
 
468
 
    if (fullscreenMonitorsSet)
469
 
    {
470
 
        long data[4];
471
 
 
472
 
        data[0] = monitors->top;
473
 
        data[1] = monitors->bottom;
474
 
        data[2] = monitors->left;
475
 
        data[3] = monitors->right;
476
 
 
477
 
        XChangeProperty (screen->dpy (), id, Atoms::wmFullscreenMonitors,
478
 
                         XA_CARDINAL, 32, PropModeReplace,
479
 
                         (unsigned char *) data, 4);
480
 
    }
481
 
    else if (hadFsMonitors)
482
 
    {
483
 
        XDeleteProperty (screen->dpy (), id, Atoms::wmFullscreenMonitors);
484
 
    }
485
 
 
486
 
    if (state & CompWindowStateFullscreenMask)
487
 
        if (fullscreenMonitorsSet || hadFsMonitors)
488
 
            window->updateAttributes (CompStackingUpdateModeNone);
489
 
}
490
 
 
491
 
void
492
 
CompWindow::changeState (unsigned int newState)
493
 
{
494
 
    unsigned int oldState;
495
 
 
496
 
    if (priv->state == newState)
497
 
        return;
498
 
 
499
 
    oldState = priv->state;
500
 
    priv->state = newState;
501
 
 
502
 
    recalcType ();
503
 
    recalcActions ();
504
 
 
505
 
    if (priv->managed)
506
 
        screen->priv->setWindowState (priv->state, priv->id);
507
 
 
508
 
    stateChangeNotify (oldState);
509
 
    screen->matchPropertyChanged (this);
510
 
}
511
 
 
512
 
static void
513
 
setWindowActions (CompScreen   *s,
514
 
                  unsigned int actions,
515
 
                  Window       id)
516
 
{
517
 
    Atom data[32];
518
 
    int  i = 0;
519
 
 
520
 
    if (actions & CompWindowActionMoveMask)
521
 
        data[i++] = Atoms::winActionMove;
522
 
    if (actions & CompWindowActionResizeMask)
523
 
        data[i++] = Atoms::winActionResize;
524
 
    if (actions & CompWindowActionStickMask)
525
 
        data[i++] = Atoms::winActionStick;
526
 
    if (actions & CompWindowActionMinimizeMask)
527
 
        data[i++] = Atoms::winActionMinimize;
528
 
    if (actions & CompWindowActionMaximizeHorzMask)
529
 
        data[i++] = Atoms::winActionMaximizeHorz;
530
 
    if (actions & CompWindowActionMaximizeVertMask)
531
 
        data[i++] = Atoms::winActionMaximizeVert;
532
 
    if (actions & CompWindowActionFullscreenMask)
533
 
        data[i++] = Atoms::winActionFullscreen;
534
 
    if (actions & CompWindowActionCloseMask)
535
 
        data[i++] = Atoms::winActionClose;
536
 
    if (actions & CompWindowActionShadeMask)
537
 
        data[i++] = Atoms::winActionShade;
538
 
    if (actions & CompWindowActionChangeDesktopMask)
539
 
        data[i++] = Atoms::winActionChangeDesktop;
540
 
    if (actions & CompWindowActionAboveMask)
541
 
        data[i++] = Atoms::winActionAbove;
542
 
    if (actions & CompWindowActionBelowMask)
543
 
        data[i++] = Atoms::winActionBelow;
544
 
 
545
 
    XChangeProperty (s->dpy (), id, Atoms::wmAllowedActions,
546
 
                     XA_ATOM, 32, PropModeReplace,
547
 
                     (unsigned char *) data, i);
548
 
}
549
 
 
550
 
void
551
 
CompWindow::recalcActions ()
552
 
{
553
 
    unsigned int actions = 0;
554
 
    unsigned int setActions, clearActions;
555
 
 
556
 
    switch (priv->type) {
557
 
    case CompWindowTypeFullscreenMask:
558
 
    case CompWindowTypeNormalMask:
559
 
        actions =
560
 
            CompWindowActionMaximizeHorzMask |
561
 
            CompWindowActionMaximizeVertMask |
562
 
            CompWindowActionFullscreenMask   |
563
 
            CompWindowActionMoveMask         |
564
 
            CompWindowActionResizeMask       |
565
 
            CompWindowActionStickMask        |
566
 
            CompWindowActionMinimizeMask     |
567
 
            CompWindowActionCloseMask        |
568
 
            CompWindowActionChangeDesktopMask;
569
 
        break;
570
 
    case CompWindowTypeUtilMask:
571
 
    case CompWindowTypeMenuMask:
572
 
    case CompWindowTypeToolbarMask:
573
 
        actions =
574
 
            CompWindowActionMoveMask   |
575
 
            CompWindowActionResizeMask |
576
 
            CompWindowActionStickMask  |
577
 
            CompWindowActionCloseMask  |
578
 
            CompWindowActionChangeDesktopMask;
579
 
        break;
580
 
    case CompWindowTypeDialogMask:
581
 
    case CompWindowTypeModalDialogMask:
582
 
        actions =
583
 
            CompWindowActionMaximizeHorzMask |
584
 
            CompWindowActionMaximizeVertMask |
585
 
            CompWindowActionMoveMask         |
586
 
            CompWindowActionResizeMask       |
587
 
            CompWindowActionStickMask        |
588
 
            CompWindowActionCloseMask        |
589
 
            CompWindowActionChangeDesktopMask;
590
 
 
591
 
        /* allow minimization for dialog windows if they
592
 
           a) are not a transient (transients can be minimized
593
 
              with their parent)
594
 
           b) don't have the skip taskbar hint set (as those
595
 
              have no target to be minimized to)
596
 
        */
597
 
        if (!priv->transientFor &&
598
 
            !(priv->state & CompWindowStateSkipTaskbarMask))
599
 
        {
600
 
            actions |= CompWindowActionMinimizeMask;
601
 
        }
602
 
    default:
603
 
        break;
604
 
    }
605
 
 
606
 
    if (priv->input.top)
607
 
        actions |= CompWindowActionShadeMask;
608
 
 
609
 
    actions |= (CompWindowActionAboveMask | CompWindowActionBelowMask);
610
 
 
611
 
    switch (priv->wmType) {
612
 
    case CompWindowTypeNormalMask:
613
 
        actions |= CompWindowActionFullscreenMask |
614
 
                   CompWindowActionMinimizeMask;
615
 
    default:
616
 
        break;
617
 
    }
618
 
 
619
 
    if (priv->sizeHints.min_width  == priv->sizeHints.max_width &&
620
 
        priv->sizeHints.min_height == priv->sizeHints.max_height)
621
 
        actions &= ~(CompWindowActionResizeMask       |
622
 
                     CompWindowActionMaximizeHorzMask |
623
 
                     CompWindowActionMaximizeVertMask |
624
 
                     CompWindowActionFullscreenMask);
625
 
 
626
 
    if (!(priv->mwmFunc & MwmFuncAll))
627
 
    {
628
 
        if (!(priv->mwmFunc & MwmFuncResize))
629
 
            actions &= ~(CompWindowActionResizeMask       |
630
 
                         CompWindowActionMaximizeHorzMask |
631
 
                         CompWindowActionMaximizeVertMask |
632
 
                         CompWindowActionFullscreenMask);
633
 
 
634
 
        if (!(priv->mwmFunc & MwmFuncMove))
635
 
            actions &= ~(CompWindowActionMoveMask         |
636
 
                         CompWindowActionMaximizeHorzMask |
637
 
                         CompWindowActionMaximizeVertMask |
638
 
                         CompWindowActionFullscreenMask);
639
 
 
640
 
        if (!(priv->mwmFunc & MwmFuncIconify))
641
 
            actions &= ~CompWindowActionMinimizeMask;
642
 
 
643
 
        if (!(priv->mwmFunc & MwmFuncClose))
644
 
            actions &= ~CompWindowActionCloseMask;
645
 
    }
646
 
 
647
 
    getAllowedActions (setActions, clearActions);
648
 
    actions &= ~clearActions;
649
 
    actions |= setActions;
650
 
 
651
 
    if (actions != priv->actions)
652
 
    {
653
 
        priv->actions = actions;
654
 
        setWindowActions (screen, actions, priv->id);
655
 
    }
656
 
}
657
 
 
658
 
void
659
 
CompWindow::getAllowedActions (unsigned int &setActions,
660
 
                               unsigned int &clearActions)
661
 
{
662
 
    WRAPABLE_HND_FUNC (1, getAllowedActions, setActions, clearActions)
663
 
 
664
 
    setActions   = 0;
665
 
    clearActions = 0;
666
 
}
667
 
 
668
 
unsigned int
669
 
CompWindow::constrainWindowState (unsigned int state,
670
 
                                  unsigned int actions)
671
 
{
672
 
    if (!(actions & CompWindowActionMaximizeHorzMask))
673
 
        state &= ~CompWindowStateMaximizedHorzMask;
674
 
 
675
 
    if (!(actions & CompWindowActionMaximizeVertMask))
676
 
        state &= ~CompWindowStateMaximizedVertMask;
677
 
 
678
 
    if (!(actions & CompWindowActionShadeMask))
679
 
        state &= ~CompWindowStateShadedMask;
680
 
 
681
 
    if (!(actions & CompWindowActionFullscreenMask))
682
 
        state &= ~CompWindowStateFullscreenMask;
683
 
 
684
 
    return state;
685
 
}
686
 
 
687
 
unsigned int
688
 
PrivateWindow::windowTypeFromString (const char *str)
689
 
{
690
 
    if (strcasecmp (str, "desktop") == 0)
691
 
        return CompWindowTypeDesktopMask;
692
 
    else if (strcasecmp (str, "dock") == 0)
693
 
        return CompWindowTypeDockMask;
694
 
    else if (strcasecmp (str, "toolbar") == 0)
695
 
        return CompWindowTypeToolbarMask;
696
 
    else if (strcasecmp (str, "menu") == 0)
697
 
        return CompWindowTypeMenuMask;
698
 
    else if (strcasecmp (str, "utility") == 0)
699
 
        return CompWindowTypeUtilMask;
700
 
    else if (strcasecmp (str, "splash") == 0)
701
 
        return CompWindowTypeSplashMask;
702
 
    else if (strcasecmp (str, "dialog") == 0)
703
 
        return CompWindowTypeDialogMask;
704
 
    else if (strcasecmp (str, "normal") == 0)
705
 
        return CompWindowTypeNormalMask;
706
 
    else if (strcasecmp (str, "dropdownmenu") == 0)
707
 
        return CompWindowTypeDropdownMenuMask;
708
 
    else if (strcasecmp (str, "popupmenu") == 0)
709
 
        return CompWindowTypePopupMenuMask;
710
 
    else if (strcasecmp (str, "tooltip") == 0)
711
 
        return CompWindowTypeTooltipMask;
712
 
    else if (strcasecmp (str, "notification") == 0)
713
 
        return CompWindowTypeNotificationMask;
714
 
    else if (strcasecmp (str, "combo") == 0)
715
 
        return CompWindowTypeComboMask;
716
 
    else if (strcasecmp (str, "dnd") == 0)
717
 
        return CompWindowTypeDndMask;
718
 
    else if (strcasecmp (str, "modaldialog") == 0)
719
 
        return CompWindowTypeModalDialogMask;
720
 
    else if (strcasecmp (str, "fullscreen") == 0)
721
 
        return CompWindowTypeFullscreenMask;
722
 
    else if (strcasecmp (str, "unknown") == 0)
723
 
        return CompWindowTypeUnknownMask;
724
 
    else if (strcasecmp (str, "any") == 0)
725
 
        return ~0;
726
 
 
727
 
    return 0;
728
 
}
729
 
 
730
 
void
731
 
CompWindow::recalcType ()
732
 
{
733
 
    unsigned int type;
734
 
 
735
 
    type = priv->wmType;
736
 
 
737
 
    if (!overrideRedirect () && priv->wmType == CompWindowTypeUnknownMask)
738
 
        type = CompWindowTypeNormalMask;
739
 
 
740
 
    if (priv->state & CompWindowStateFullscreenMask)
741
 
        type = CompWindowTypeFullscreenMask;
742
 
 
743
 
    if (type == CompWindowTypeNormalMask)
744
 
    {
745
 
        if (priv->transientFor)
746
 
            type = CompWindowTypeDialogMask;
747
 
    }
748
 
 
749
 
    if (type == CompWindowTypeDockMask &&
750
 
        (priv->state & CompWindowStateBelowMask))
751
 
    {
752
 
        type = CompWindowTypeNormalMask;
753
 
    }
754
 
 
755
 
    if ((type & (CompWindowTypeNormalMask | CompWindowTypeDialogMask)) &&
756
 
        (priv->state & CompWindowStateModalMask))
757
 
    {
758
 
        type = CompWindowTypeModalDialogMask;
759
 
    }
760
 
 
761
 
    priv->type = type;
762
 
}
763
 
 
764
 
 
765
 
void
766
 
PrivateWindow::updateFrameWindow ()
767
 
{
768
 
    if (!frame)
769
 
        return;
770
 
 
771
 
    if (input.left || input.right || input.top || input.bottom)
772
 
    {
773
 
        int        x, y, width, height;
774
 
        int        bw = serverGeometry.border () * 2;
775
 
 
776
 
        x      = serverGeometry.x () - input.left;
777
 
        y      = serverGeometry.y () - input.top;
778
 
        width  = serverGeometry.width () + input.left + input.right + bw;
779
 
        height = serverGeometry.height () + input.top  + input.bottom + bw;
780
 
 
781
 
        if (shaded)
782
 
            height = input.top + input.bottom;
783
 
 
784
 
        XMoveResizeWindow (screen->dpy (), frame, x, y, width, height);
785
 
        if (shaded)
786
 
        {
787
 
            XUnmapWindow (screen->dpy (), wrapper);
788
 
        }
789
 
        else
790
 
        {
791
 
            XMapWindow (screen->dpy (), wrapper);
792
 
            XMoveResizeWindow (screen->dpy (), wrapper, input.left, input.top,
793
 
                               serverGeometry.width (), serverGeometry.height ());
794
 
        }
795
 
        XMoveResizeWindow (screen->dpy (), id, 0, 0,
796
 
                           serverGeometry.width (), serverGeometry.height ());
797
 
        window->sendConfigureNotify ();
798
 
 
799
 
        window->updateFrameRegion ();
800
 
        window->windowNotify (CompWindowNotifyFrameUpdate);
801
 
    }
802
 
    else
803
 
    {
804
 
        int        x, y, width, height;
805
 
        int        bw = serverGeometry.border () * 2;
806
 
 
807
 
        x      = serverGeometry.x ();
808
 
        y      = serverGeometry.y ();
809
 
        width  = serverGeometry.width () + bw;
810
 
        height = serverGeometry.height () + bw;
811
 
 
812
 
        if (shaded)
813
 
            height = 0;
814
 
 
815
 
        XMoveResizeWindow (screen->dpy (), frame, x, y, width, height);
816
 
        if (shaded)
817
 
        {
818
 
            XUnmapWindow (screen->dpy (), wrapper);
819
 
        }
820
 
        else
821
 
        {
822
 
            XMapWindow (screen->dpy (), wrapper);
823
 
            XMoveResizeWindow (screen->dpy (), wrapper, 0, 0,
824
 
                               serverGeometry.width (), serverGeometry.height ());
825
 
        }
826
 
        XMoveResizeWindow (screen->dpy (), id, 0, 0,
827
 
                           serverGeometry.width (), serverGeometry.height ());
828
 
        window->sendConfigureNotify ();
829
 
        frameRegion = CompRegion ();
830
 
        window->windowNotify (CompWindowNotifyFrameUpdate);
831
 
    }
832
 
 
833
 
    window->recalcActions ();
834
 
}
835
 
 
836
 
 
837
 
 
838
 
void
839
 
CompWindow::updateWindowOutputExtents ()
840
 
{
841
 
    CompWindowExtents output;
842
 
 
843
 
    getOutputExtents (output);
844
 
 
845
 
    if (output.left   != priv->output.left  ||
846
 
        output.right  != priv->output.right ||
847
 
        output.top    != priv->output.top   ||
848
 
        output.bottom != priv->output.bottom)
849
 
    {
850
 
        priv->output = output;
851
 
 
852
 
        resizeNotify (0, 0, 0, 0);
853
 
    }
854
 
}
855
 
 
856
 
void
857
 
CompWindow::getOutputExtents (CompWindowExtents& output)
858
 
{
859
 
    WRAPABLE_HND_FUNC (0, getOutputExtents, output)
860
 
 
861
 
    output.left   = 0;
862
 
    output.right  = 0;
863
 
    output.top    = 0;
864
 
    output.bottom = 0;
865
 
}
866
 
 
867
 
CompRegion
868
 
PrivateWindow::rectsToRegion (unsigned int n, XRectangle *rects)
869
 
{
870
 
    CompRegion ret;
871
 
    int        x1, x2, y1, y2;
872
 
 
873
 
    for (unsigned int i = 0; i < n; i++)
874
 
    {
875
 
        x1 = rects[i].x + priv->attrib.border_width;
876
 
        y1 = rects[i].y + priv->attrib.border_width;
877
 
        x2 = x1 + rects[i].width;
878
 
        y2 = y1 + rects[i].height;
879
 
 
880
 
        if (x1 < 0)
881
 
            x1 = 0;
882
 
        if (y1 < 0)
883
 
            y1 = 0;
884
 
        if (x2 > priv->width)
885
 
            x2 = priv->width;
886
 
        if (y2 > priv->height)
887
 
            y2 = priv->height;
888
 
 
889
 
        if (y1 < y2 && x1 < x2)
890
 
        {
891
 
            x1 += priv->attrib.x;
892
 
            y1 += priv->attrib.y;
893
 
            x2 += priv->attrib.x;
894
 
            y2 += priv->attrib.y;
895
 
 
896
 
            ret += CompRect (x1, y1, x2 - x1, y2 - y1);
897
 
        }
898
 
    }
899
 
 
900
 
    return ret;
901
 
}
902
 
 
903
 
/* TODO: This function should be able to check the XShape event
904
 
 * kind and only get/set shape rectangles for either ShapeInput
905
 
 * or ShapeBounding, but not both at the same time
906
 
 */
907
 
 
908
 
void
909
 
PrivateWindow::updateRegion ()
910
 
{
911
 
    XRectangle r, *boundingShapeRects = NULL;
912
 
    XRectangle *inputShapeRects = NULL;
913
 
    int        nBounding = 0, nInput = 0;
914
 
 
915
 
    priv->region = CompRegion ();
916
 
    priv->inputRegion = CompRegion ();
917
 
 
918
 
    if (screen->XShape ())
919
 
    {
920
 
        int order;
921
 
 
922
 
        boundingShapeRects = XShapeGetRectangles (screen->dpy (), priv->id,
923
 
                                                  ShapeBounding, &nBounding, &order);
924
 
        inputShapeRects = XShapeGetRectangles (screen->dpy (), priv->id,
925
 
                                               ShapeInput, &nInput, &order);
926
 
 
927
 
    }
928
 
 
929
 
    r.x      = -priv->attrib.border_width;
930
 
    r.y      = -priv->attrib.border_width;
931
 
    r.width  = priv->width + priv->attrib.border_width;
932
 
    r.height = priv->height + priv->attrib.border_width;
933
 
 
934
 
    if (nBounding < 1)
935
 
    {
936
 
        boundingShapeRects = &r;
937
 
        nBounding = 1;
938
 
    }
939
 
 
940
 
    if (nInput < 1)
941
 
    {
942
 
        inputShapeRects = &r;
943
 
        nBounding = 1;
944
 
    }
945
 
 
946
 
    priv->region += rectsToRegion (nBounding, boundingShapeRects);
947
 
    priv->inputRegion += rectsToRegion (nInput, inputShapeRects);
948
 
 
949
 
    if (boundingShapeRects && boundingShapeRects != &r)
950
 
        XFree (boundingShapeRects);
951
 
    if (inputShapeRects && inputShapeRects != &r)
952
 
        XFree (inputShapeRects);
953
 
 
954
 
    window->updateFrameRegion ();
955
 
}
956
 
 
957
 
bool
958
 
CompWindow::updateStruts ()
959
 
{
960
 
    Atom          actual;
961
 
    int           result, format;
962
 
    unsigned long n, left;
963
 
    unsigned char *data;
964
 
    bool          hasOld, hasNew;
965
 
    CompStruts    oldStrut, newStrut;
966
 
 
967
 
    if (priv->struts)
968
 
    {
969
 
        hasOld = true;
970
 
 
971
 
        oldStrut.left   = priv->struts->left;
972
 
        oldStrut.right  = priv->struts->right;
973
 
        oldStrut.top    = priv->struts->top;
974
 
        oldStrut.bottom = priv->struts->bottom;
975
 
    }
976
 
    else
977
 
    {
978
 
        hasOld = false;
979
 
    }
980
 
 
981
 
    hasNew = false;
982
 
 
983
 
    newStrut.left.x         = 0;
984
 
    newStrut.left.y         = 0;
985
 
    newStrut.left.width  = 0;
986
 
    newStrut.left.height = screen->height ();
987
 
 
988
 
    newStrut.right.x      = screen->width ();
989
 
    newStrut.right.y      = 0;
990
 
    newStrut.right.width  = 0;
991
 
    newStrut.right.height = screen->height ();
992
 
 
993
 
    newStrut.top.x         = 0;
994
 
    newStrut.top.y         = 0;
995
 
    newStrut.top.width  = screen->width ();
996
 
    newStrut.top.height = 0;
997
 
 
998
 
    newStrut.bottom.x      = 0;
999
 
    newStrut.bottom.y      = screen->height ();
1000
 
    newStrut.bottom.width  = screen->width ();
1001
 
    newStrut.bottom.height = 0;
1002
 
 
1003
 
    result = XGetWindowProperty (screen->dpy (), priv->id,
1004
 
                                 Atoms::wmStrutPartial,
1005
 
                                 0L, 12L, false, XA_CARDINAL, &actual, &format,
1006
 
                                 &n, &left, &data);
1007
 
 
1008
 
    if (result == Success && data)
1009
 
    {
1010
 
        unsigned long *struts = (unsigned long *) data;
1011
 
 
1012
 
        if (n == 12)
1013
 
        {
1014
 
            hasNew = true;
1015
 
 
1016
 
            newStrut.left.y        = struts[4];
1017
 
            newStrut.left.width    = struts[0];
1018
 
            newStrut.left.height   = struts[5] - newStrut.left.y + 1;
1019
 
 
1020
 
            newStrut.right.width   = struts[1];
1021
 
            newStrut.right.x       = screen->width () - newStrut.right.width;
1022
 
            newStrut.right.y       = struts[6];
1023
 
            newStrut.right.height  = struts[7] - newStrut.right.y + 1;
1024
 
 
1025
 
            newStrut.top.x         = struts[8];
1026
 
            newStrut.top.width     = struts[9] - newStrut.top.x + 1;
1027
 
            newStrut.top.height    = struts[2];
1028
 
 
1029
 
            newStrut.bottom.x      = struts[10];
1030
 
            newStrut.bottom.width  = struts[11] - newStrut.bottom.x + 1;
1031
 
            newStrut.bottom.height = struts[3];
1032
 
            newStrut.bottom.y      = screen->height () - newStrut.bottom.height;
1033
 
        }
1034
 
 
1035
 
        XFree (data);
1036
 
    }
1037
 
 
1038
 
    if (!hasNew)
1039
 
    {
1040
 
        result = XGetWindowProperty (screen->dpy (), priv->id,
1041
 
                                     Atoms::wmStrut,
1042
 
                                     0L, 4L, false, XA_CARDINAL,
1043
 
                                     &actual, &format, &n, &left, &data);
1044
 
 
1045
 
        if (result == Success && data)
1046
 
        {
1047
 
            unsigned long *struts = (unsigned long *) data;
1048
 
 
1049
 
            if (n == 4)
1050
 
            {
1051
 
                hasNew = true;
1052
 
 
1053
 
                newStrut.left.x        = 0;
1054
 
                newStrut.left.width    = struts[0];
1055
 
 
1056
 
                newStrut.right.width   = struts[1];
1057
 
                newStrut.right.x       = screen->width () - newStrut.right.width;
1058
 
 
1059
 
                newStrut.top.y         = 0;
1060
 
                newStrut.top.height    = struts[2];
1061
 
 
1062
 
                newStrut.bottom.height = struts[3];
1063
 
                newStrut.bottom.y      = screen->height () - newStrut.bottom.height;
1064
 
            }
1065
 
 
1066
 
            XFree (data);
1067
 
        }
1068
 
    }
1069
 
 
1070
 
    if (hasNew)
1071
 
    {
1072
 
        int strutX1, strutY1, strutX2, strutY2;
1073
 
        int x1, y1, x2, y2;
1074
 
 
1075
 
        /* applications expect us to clip struts to xinerama edges */
1076
 
        for (unsigned int i = 0;
1077
 
             i < screen->screenInfo ().size (); i++)
1078
 
        {
1079
 
            x1 = screen->screenInfo ()[i].x_org;
1080
 
            y1 = screen->screenInfo ()[i].y_org;
1081
 
            x2 = x1 + screen->screenInfo ()[i].width;
1082
 
            y2 = y1 + screen->screenInfo ()[i].height;
1083
 
 
1084
 
            strutX1 = newStrut.left.x;
1085
 
            strutX2 = strutX1 + newStrut.left.width;
1086
 
            strutY1 = newStrut.left.y;
1087
 
            strutY2 = strutY1 + newStrut.left.height;
1088
 
 
1089
 
            if (strutX2 > x1 && strutX2 <= x2 &&
1090
 
                strutY1 < y2 && strutY2 > y1)
1091
 
            {
1092
 
                newStrut.left.x     = x1;
1093
 
                newStrut.left.width = strutX2 - x1;
1094
 
            }
1095
 
 
1096
 
            strutX1 = newStrut.right.x;
1097
 
            strutX2 = strutX1 + newStrut.right.width;
1098
 
            strutY1 = newStrut.right.y;
1099
 
            strutY2 = strutY1 + newStrut.right.height;
1100
 
 
1101
 
            if (strutX1 > x1 && strutX1 <= x2 &&
1102
 
                strutY1 < y2 && strutY2 > y1)
1103
 
            {
1104
 
                newStrut.right.x     = strutX1;
1105
 
                newStrut.right.width = x2 - strutX1;
1106
 
            }
1107
 
 
1108
 
            strutX1 = newStrut.top.x;
1109
 
            strutX2 = strutX1 + newStrut.top.width;
1110
 
            strutY1 = newStrut.top.y;
1111
 
            strutY2 = strutY1 + newStrut.top.height;
1112
 
 
1113
 
            if (strutX1 < x2 && strutX2 > x1 &&
1114
 
                strutY2 > y1 && strutY2 <= y2)
1115
 
            {
1116
 
                newStrut.top.y      = y1;
1117
 
                newStrut.top.height = strutY2 - y1;
1118
 
            }
1119
 
 
1120
 
            strutX1 = newStrut.bottom.x;
1121
 
            strutX2 = strutX1 + newStrut.bottom.width;
1122
 
            strutY1 = newStrut.bottom.y;
1123
 
            strutY2 = strutY1 + newStrut.bottom.height;
1124
 
 
1125
 
            if (strutX1 < x2 && strutX2 > x1 &&
1126
 
                strutY1 > y1 && strutY1 <= y2)
1127
 
            {
1128
 
                newStrut.bottom.y      = strutY1;
1129
 
                newStrut.bottom.height = y2 - strutY1;
1130
 
            }
1131
 
        }
1132
 
    }
1133
 
 
1134
 
    if (hasOld != hasNew ||
1135
 
        (hasNew && hasOld &&
1136
 
         memcmp (&newStrut, &oldStrut, sizeof (CompStruts))))
1137
 
    {
1138
 
        if (hasNew)
1139
 
        {
1140
 
            if (!priv->struts)
1141
 
            {
1142
 
                priv->struts = (CompStruts *) malloc (sizeof (CompStruts));
1143
 
                if (!priv->struts)
1144
 
                    return false;
1145
 
            }
1146
 
 
1147
 
            *priv->struts = newStrut;
1148
 
        }
1149
 
        else
1150
 
        {
1151
 
            free (priv->struts);
1152
 
            priv->struts = NULL;
1153
 
        }
1154
 
 
1155
 
        return true;
1156
 
    }
1157
 
 
1158
 
    return false;
1159
 
}
1160
 
 
1161
 
static void
1162
 
setDefaultWindowAttributes (XWindowAttributes *wa)
1163
 
{
1164
 
    wa->x                     = 0;
1165
 
    wa->y                     = 0;
1166
 
    wa->width                 = 1;
1167
 
    wa->height                = 1;
1168
 
    wa->border_width          = 0;
1169
 
    wa->depth                 = 0;
1170
 
    wa->visual                = NULL;
1171
 
    wa->root                  = None;
1172
 
    wa->c_class               = InputOnly;
1173
 
    wa->bit_gravity           = NorthWestGravity;
1174
 
    wa->win_gravity           = NorthWestGravity;
1175
 
    wa->backing_store         = NotUseful;
1176
 
    wa->backing_planes        = 0;
1177
 
    wa->backing_pixel         = 0;
1178
 
    wa->save_under            = false;
1179
 
    wa->colormap              = None;
1180
 
    wa->map_installed         = false;
1181
 
    wa->map_state             = IsUnviewable;
1182
 
    wa->all_event_masks       = 0;
1183
 
    wa->your_event_mask       = 0;
1184
 
    wa->do_not_propagate_mask = 0;
1185
 
    wa->override_redirect     = true;
1186
 
    wa->screen                = NULL;
1187
 
}
1188
 
 
1189
 
void
1190
 
CompWindow::incrementDestroyReference ()
1191
 
{
1192
 
    priv->destroyRefCnt++;
1193
 
}
1194
 
 
1195
 
void
1196
 
CompWindow::destroy ()
1197
 
{
1198
 
    windowNotify (CompWindowNotifyBeforeDestroy);
1199
 
 
1200
 
    screen->priv->eraseWindowFromMap (id ());
1201
 
 
1202
 
    priv->id = 1;
1203
 
    priv->mapNum = 0;
1204
 
 
1205
 
    priv->destroyRefCnt--;
1206
 
    if (priv->destroyRefCnt)
1207
 
        return;
1208
 
 
1209
 
 
1210
 
    if (!priv->destroyed)
1211
 
    {
1212
 
        priv->destroyed = true;
1213
 
        screen->priv->pendingDestroys++;
1214
 
    }
1215
 
 
1216
 
    if (priv->frame)
1217
 
        priv->unreparent ();
1218
 
 
1219
 
}
1220
 
 
1221
 
void
1222
 
CompWindow::sendConfigureNotify ()
1223
 
{
1224
 
    XConfigureEvent xev;
1225
 
 
1226
 
    xev.type   = ConfigureNotify;
1227
 
    xev.event  = priv->id;
1228
 
    xev.window = priv->id;
1229
 
 
1230
 
    /* normally we should never send configure notify events to override
1231
 
       redirect windows but if they support the _NET_WM_SYNC_REQUEST
1232
 
       protocol we need to do this when the window is mapped. however the
1233
 
       only way we can make sure that the attributes we send are correct
1234
 
       and is to grab the server. */
1235
 
    if (priv->attrib.override_redirect)
1236
 
    {
1237
 
        XWindowAttributes attrib;
1238
 
 
1239
 
        XGrabServer (screen->dpy ());
1240
 
 
1241
 
        if (XGetWindowAttributes (screen->dpy (), priv->id, &attrib))
1242
 
        {
1243
 
            xev.x            = attrib.x;
1244
 
            xev.y            = attrib.y;
1245
 
            xev.width        = attrib.width;
1246
 
            xev.height       = attrib.height;
1247
 
            xev.border_width = attrib.border_width;
1248
 
 
1249
 
            xev.above             = (prev) ? prev->priv->id : None;
1250
 
            xev.override_redirect = true;
1251
 
 
1252
 
            XSendEvent (screen->dpy (), priv->id, false,
1253
 
                        StructureNotifyMask, (XEvent *) &xev);
1254
 
        }
1255
 
 
1256
 
        XUngrabServer (screen->dpy ());
1257
 
    }
1258
 
    else
1259
 
    {
1260
 
        xev.x            = priv->serverGeometry.x ();
1261
 
        xev.y            = priv->serverGeometry.y ();
1262
 
        xev.width        = priv->serverGeometry.width ();
1263
 
        xev.height       = priv->serverGeometry.height ();
1264
 
        xev.border_width = priv->serverGeometry.border ();
1265
 
 
1266
 
        xev.above             = (prev) ? prev->priv->id : None;
1267
 
        xev.override_redirect = priv->attrib.override_redirect;
1268
 
 
1269
 
        XSendEvent (screen->dpy (), priv->id, false,
1270
 
                    StructureNotifyMask, (XEvent *) &xev);
1271
 
    }
1272
 
}
1273
 
 
1274
 
void
1275
 
CompWindow::map ()
1276
 
{
1277
 
    windowNotify (CompWindowNotifyBeforeMap);
1278
 
 
1279
 
    if (!isViewable ())
1280
 
    {
1281
 
        if (priv->pendingMaps > 0)
1282
 
            priv->pendingMaps = 0;
1283
 
 
1284
 
        priv->mapNum = screen->priv->mapNum++;
1285
 
 
1286
 
        if (priv->struts)
1287
 
            screen->updateWorkarea ();
1288
 
 
1289
 
        if (windowClass () == InputOnly)
1290
 
            return;
1291
 
 
1292
 
        priv->unmapRefCnt = 1;
1293
 
 
1294
 
        priv->attrib.map_state = IsViewable;
1295
 
 
1296
 
        if (!overrideRedirect ())
1297
 
            screen->priv->setWmState (NormalState, priv->id);
1298
 
 
1299
 
        priv->invisible  = true;
1300
 
        priv->alive      = true;
1301
 
 
1302
 
        priv->lastPong = screen->priv->lastPing;
1303
 
 
1304
 
        priv->updateRegion ();
1305
 
        priv->updateSize ();
1306
 
 
1307
 
        screen->priv->updateClientList ();
1308
 
 
1309
 
        if (priv->type & CompWindowTypeDesktopMask)
1310
 
            screen->priv->desktopWindowCount++;
1311
 
 
1312
 
        if (priv->protocols & CompWindowProtocolSyncRequestMask)
1313
 
        {
1314
 
            sendSyncRequest ();
1315
 
            sendConfigureNotify ();
1316
 
        }
1317
 
 
1318
 
        if (!overrideRedirect ())
1319
 
        {
1320
 
            /* been shaded */
1321
 
            if (!priv->height)
1322
 
                resize (priv->attrib.x, priv->attrib.y, priv->attrib.width,
1323
 
                        ++priv->attrib.height - 1, priv->attrib.border_width);
1324
 
        }
1325
 
    }
1326
 
 
1327
 
    windowNotify (CompWindowNotifyMap);
1328
 
}
1329
 
 
1330
 
void
1331
 
CompWindow::incrementUnmapReference ()
1332
 
{
1333
 
    priv->unmapRefCnt++;
1334
 
}
1335
 
 
1336
 
void
1337
 
CompWindow::unmap ()
1338
 
{
1339
 
    windowNotify (CompWindowNotifyBeforeUnmap);
1340
 
 
1341
 
    if (priv->mapNum)
1342
 
        priv->mapNum = 0;
1343
 
 
1344
 
    priv->unmapRefCnt--;
1345
 
    if (priv->unmapRefCnt > 0)
1346
 
        return;
1347
 
 
1348
 
    if (priv->unmanaging)
1349
 
    {
1350
 
        XWindowChanges xwc;
1351
 
        unsigned int   xwcm;
1352
 
        int                gravity = priv->sizeHints.win_gravity;
1353
 
 
1354
 
        /* revert gravity adjustment made at MapNotify time */
1355
 
        xwc.x   = priv->serverGeometry.x ();
1356
 
        xwc.y   = priv->serverGeometry.y ();
1357
 
        xwc.width   = 0;
1358
 
        xwc.height  = 0;
1359
 
 
1360
 
        xwcm = priv->adjustConfigureRequestForGravity (&xwc,
1361
 
                                                       CWX | CWY,
1362
 
                                                       gravity,
1363
 
                                                       -1);
1364
 
        if (xwcm)
1365
 
            configureXWindow (xwcm, &xwc);
1366
 
 
1367
 
        priv->unmanaging = false;
1368
 
    }
1369
 
 
1370
 
    if (priv->struts)
1371
 
        screen->updateWorkarea ();
1372
 
 
1373
 
    if (priv->attrib.map_state != IsViewable)
1374
 
        return;
1375
 
 
1376
 
    if (priv->type == CompWindowTypeDesktopMask)
1377
 
        screen->priv->desktopWindowCount--;
1378
 
 
1379
 
    priv->attrib.map_state = IsUnmapped;
1380
 
 
1381
 
    priv->invisible = true;
1382
 
 
1383
 
    if (priv->shaded && priv->height)
1384
 
        resize (priv->attrib.x, priv->attrib.y,
1385
 
                priv->attrib.width, ++priv->attrib.height - 1,
1386
 
                priv->attrib.border_width);
1387
 
 
1388
 
    screen->priv->updateClientList ();
1389
 
 
1390
 
    windowNotify (CompWindowNotifyUnmap);
1391
 
}
1392
 
 
1393
 
bool
1394
 
PrivateWindow::restack (Window aboveId)
1395
 
{
1396
 
    if (aboveId && (aboveId == id || aboveId == frame))
1397
 
        // Don't try to raise a window above itself
1398
 
        return false;
1399
 
    else if (window->prev)
1400
 
    {
1401
 
        if (aboveId && (aboveId == window->prev->id () ||
1402
 
                        aboveId == window->prev->frame ()))
1403
 
            return false;
1404
 
    }
1405
 
    else if (aboveId == None && !window->next)
1406
 
        return false;
1407
 
 
1408
 
    if (aboveId && !screen->findTopLevelWindow (aboveId, true))
1409
 
        return false;
1410
 
 
1411
 
    screen->unhookWindow (window);
1412
 
    screen->insertWindow (window, aboveId);
1413
 
 
1414
 
    screen->priv->updateClientList ();
1415
 
 
1416
 
    window->windowNotify (CompWindowNotifyRestack);
1417
 
 
1418
 
    return true;
1419
 
}
1420
 
 
1421
 
bool
1422
 
CompWindow::resize (XWindowAttributes attr)
1423
 
{
1424
 
    return resize (Geometry (attr.x, attr.y, attr.width, attr.height,
1425
 
                             attr.border_width));
1426
 
}
1427
 
 
1428
 
bool
1429
 
CompWindow::resize (int          x,
1430
 
                    int          y,
1431
 
                    int          width,
1432
 
                    int          height,
1433
 
                    int          border)
1434
 
{
1435
 
    return resize (Geometry (x, y, width, height, border));
1436
 
}
1437
 
 
1438
 
bool
1439
 
CompWindow::resize (CompWindow::Geometry gm)
1440
 
{
1441
 
    if (priv->attrib.width        != gm.width ()  ||
1442
 
        priv->attrib.height       != gm.height () ||
1443
 
        priv->attrib.border_width != gm.border ())
1444
 
    {
1445
 
        int pw, ph;
1446
 
        int dx, dy, dwidth, dheight;
1447
 
 
1448
 
        pw = gm.width () + gm.border () * 2;
1449
 
        ph = gm.height () + gm.border () * 2;
1450
 
 
1451
 
        if (priv->shaded)
1452
 
            ph = 0;
1453
 
 
1454
 
        dx      = gm.x () - priv->attrib.x;
1455
 
        dy      = gm.y () - priv->attrib.y;
1456
 
        dwidth  = gm.width () - priv->attrib.width;
1457
 
        dheight = gm.height () - priv->attrib.height;
1458
 
 
1459
 
        priv->attrib.x            = gm.x ();
1460
 
        priv->attrib.y            = gm.y ();
1461
 
        priv->attrib.width        = gm.width ();
1462
 
        priv->attrib.height       = gm.height ();
1463
 
        priv->attrib.border_width = gm.border ();
1464
 
 
1465
 
        priv->geometry.set (priv->attrib.x, priv->attrib.y,
1466
 
                            priv->attrib.width, priv->attrib.height,
1467
 
                            priv->attrib.border_width);
1468
 
 
1469
 
        if (!priv->mapNum && priv->unmapRefCnt > 0 &&
1470
 
             priv->attrib.map_state == IsViewable)
1471
 
        {
1472
 
            /* keep old pixmap for windows that are unmapped on the client side,
1473
 
             * but not yet on our side as it's pretty likely that plugins are
1474
 
             * currently using it for animations
1475
 
             */
1476
 
        }
1477
 
        else
1478
 
        {
1479
 
            priv->width = pw;
1480
 
            priv->height = ph;
1481
 
        }
1482
 
 
1483
 
        if (priv->mapNum)
1484
 
            priv->updateRegion ();
1485
 
 
1486
 
        resizeNotify (dx, dy, dwidth, dheight);
1487
 
 
1488
 
        priv->invisible = WINDOW_INVISIBLE (priv);
1489
 
        priv->updateFrameWindow ();
1490
 
    }
1491
 
    else if (priv->attrib.x != gm.x () || priv->attrib.y != gm.y ())
1492
 
    {
1493
 
        int dx, dy;
1494
 
 
1495
 
        dx = gm.x () - priv->attrib.x;
1496
 
        dy = gm.y () - priv->attrib.y;
1497
 
 
1498
 
        move (dx, dy);
1499
 
    }
1500
 
 
1501
 
    return true;
1502
 
}
1503
 
 
1504
 
static void
1505
 
syncValueIncrement (XSyncValue *value)
1506
 
{
1507
 
    XSyncValue one;
1508
 
    int        overflow;
1509
 
 
1510
 
    XSyncIntToValue (&one, 1);
1511
 
    XSyncValueAdd (value, *value, one, &overflow);
1512
 
}
1513
 
 
1514
 
bool
1515
 
PrivateWindow::initializeSyncCounter ()
1516
 
{
1517
 
    XSyncAlarmAttributes values;
1518
 
    Atom                 actual;
1519
 
    int                  result, format;
1520
 
    unsigned long        n, left;
1521
 
    unsigned char        *data;
1522
 
 
1523
 
    if (syncCounter)
1524
 
        return syncAlarm != None;
1525
 
 
1526
 
    if (!(protocols & CompWindowProtocolSyncRequestMask))
1527
 
        return false;
1528
 
 
1529
 
    result = XGetWindowProperty (screen->dpy (), id,
1530
 
                                 Atoms::wmSyncRequestCounter,
1531
 
                                 0L, 1L, false, XA_CARDINAL, &actual, &format,
1532
 
                                 &n, &left, &data);
1533
 
 
1534
 
    if (result == Success && n && data)
1535
 
    {
1536
 
        unsigned long *counter = (unsigned long *) data;
1537
 
 
1538
 
        syncCounter = *counter;
1539
 
 
1540
 
        XFree (data);
1541
 
 
1542
 
        XSyncIntsToValue (&syncValue, (unsigned int) rand (), 0);
1543
 
        XSyncSetCounter (screen->dpy (),
1544
 
                         syncCounter,
1545
 
                         syncValue);
1546
 
 
1547
 
        syncValueIncrement (&syncValue);
1548
 
 
1549
 
        values.events = true;
1550
 
 
1551
 
        values.trigger.counter    = syncCounter;
1552
 
        values.trigger.wait_value = syncValue;
1553
 
 
1554
 
        values.trigger.value_type = XSyncAbsolute;
1555
 
        values.trigger.test_type  = XSyncPositiveComparison;
1556
 
 
1557
 
        XSyncIntToValue (&values.delta, 1);
1558
 
 
1559
 
        values.events = true;
1560
 
 
1561
 
        CompScreen::checkForError (screen->dpy ());
1562
 
 
1563
 
        /* Note that by default, the alarm increments the trigger value
1564
 
         * when it fires until the condition (counter.value < trigger.value)
1565
 
         * is false again.
1566
 
         */
1567
 
        syncAlarm = XSyncCreateAlarm (screen->dpy (),
1568
 
                                      XSyncCACounter   |
1569
 
                                      XSyncCAValue     |
1570
 
                                      XSyncCAValueType |
1571
 
                                      XSyncCATestType  |
1572
 
                                      XSyncCADelta     |
1573
 
                                      XSyncCAEvents,
1574
 
                                      &values);
1575
 
 
1576
 
        if (CompScreen::checkForError (screen->dpy ()))
1577
 
            return true;
1578
 
 
1579
 
        XSyncDestroyAlarm (screen->dpy (), syncAlarm);
1580
 
        syncAlarm = None;
1581
 
    }
1582
 
    else if (result == Success && data)
1583
 
    {
1584
 
        XFree (data);
1585
 
    }
1586
 
 
1587
 
    return false;
1588
 
}
1589
 
 
1590
 
void
1591
 
CompWindow::sendSyncRequest ()
1592
 
{
1593
 
    XClientMessageEvent xev;
1594
 
 
1595
 
    if (priv->syncWait)
1596
 
        return;
1597
 
 
1598
 
    if (!priv->initializeSyncCounter ())
1599
 
        return;
1600
 
 
1601
 
    xev.type         = ClientMessage;
1602
 
    xev.window       = priv->id;
1603
 
    xev.message_type = Atoms::wmProtocols;
1604
 
    xev.format       = 32;
1605
 
    xev.data.l[0]    = Atoms::wmSyncRequest;
1606
 
    xev.data.l[1]    = CurrentTime;
1607
 
    xev.data.l[2]    = XSyncValueLow32 (priv->syncValue);
1608
 
    xev.data.l[3]    = XSyncValueHigh32 (priv->syncValue);
1609
 
    xev.data.l[4]    = 0;
1610
 
 
1611
 
    syncValueIncrement (&priv->syncValue);
1612
 
 
1613
 
    XSendEvent (screen->dpy (), priv->id, false, 0, (XEvent *) &xev);
1614
 
 
1615
 
    priv->syncWait     = true;
1616
 
    priv->syncGeometry = priv->serverGeometry;
1617
 
 
1618
 
    if (!priv->syncWaitTimer.active ())
1619
 
        priv->syncWaitTimer.start ();
1620
 
}
1621
 
 
1622
 
void
1623
 
PrivateWindow::configure (XConfigureEvent *ce)
1624
 
{
1625
 
    if (priv->frame)
1626
 
        return;
1627
 
 
1628
 
    priv->attrib.override_redirect = ce->override_redirect;
1629
 
 
1630
 
    if (priv->syncWait)
1631
 
    {
1632
 
        priv->syncGeometry.set (ce->x, ce->y, ce->width, ce->height,
1633
 
                                ce->border_width);
1634
 
    }
1635
 
    else
1636
 
    {
1637
 
        if (ce->override_redirect)
1638
 
        {
1639
 
            priv->serverGeometry.set (ce->x, ce->y, ce->width, ce->height,
1640
 
                                      ce->border_width);
1641
 
        }
1642
 
 
1643
 
        window->resize (ce->x, ce->y, ce->width, ce->height, ce->border_width);
1644
 
    }
1645
 
 
1646
 
    if (ce->event == screen->root ())
1647
 
        priv->restack (ce->above);
1648
 
}
1649
 
 
1650
 
void
1651
 
PrivateWindow::configureFrame (XConfigureEvent *ce)
1652
 
{
1653
 
    int x, y, width, height;
1654
 
    CompWindow       *above;
1655
 
 
1656
 
    if (!priv->frame)
1657
 
        return;
1658
 
 
1659
 
    x      = ce->x + priv->input.left;
1660
 
    y      = ce->y + priv->input.top;
1661
 
    width  = ce->width - priv->input.left - priv->input.right;
1662
 
    height = ce->height - priv->input.top - priv->input.bottom;
1663
 
 
1664
 
    if (priv->syncWait)
1665
 
    {
1666
 
        priv->syncGeometry.set (x, y, width, height, ce->border_width);
1667
 
    }
1668
 
    else
1669
 
    {
1670
 
        if (ce->override_redirect)
1671
 
        {
1672
 
            priv->serverGeometry.set (x, y, width, height, ce->border_width);
1673
 
        }
1674
 
 
1675
 
        window->resize (x, y, width, height, ce->border_width);
1676
 
    }
1677
 
 
1678
 
    if (priv->restack (ce->above))
1679
 
        priv->updatePassiveButtonGrabs ();
1680
 
 
1681
 
    above = screen->findWindow (ce->above);
1682
 
 
1683
 
    if (above)
1684
 
        above->priv->updatePassiveButtonGrabs ();
1685
 
}
1686
 
 
1687
 
void
1688
 
PrivateWindow::circulate (XCirculateEvent *ce)
1689
 
{
1690
 
    Window newAboveId;
1691
 
 
1692
 
    if (ce->place == PlaceOnTop)
1693
 
        newAboveId = screen->priv->getTopWindow ();
1694
 
    else
1695
 
        newAboveId = 0;
1696
 
 
1697
 
    priv->restack (newAboveId);
1698
 
}
1699
 
 
1700
 
void
1701
 
CompWindow::move (int  dx,
1702
 
                  int  dy,
1703
 
                  bool immediate)
1704
 
{
1705
 
    if (dx || dy)
1706
 
    {
1707
 
        priv->attrib.x += dx;
1708
 
        priv->attrib.y += dy;
1709
 
 
1710
 
        priv->geometry.setX (priv->attrib.x);
1711
 
        priv->geometry.setY (priv->attrib.y);
1712
 
 
1713
 
        priv->region.translate (dx, dy);
1714
 
        priv->inputRegion.translate (dx, dy);
1715
 
        if (!priv->frameRegion.isEmpty ())
1716
 
            priv->frameRegion.translate (dx, dy);
1717
 
 
1718
 
        priv->invisible = WINDOW_INVISIBLE (priv);
1719
 
 
1720
 
        moveNotify (dx, dy, immediate);
1721
 
    }
1722
 
}
1723
 
 
1724
 
void
1725
 
CompWindow::syncPosition ()
1726
 
{
1727
 
    priv->serverGeometry.setX (priv->attrib.x);
1728
 
    priv->serverGeometry.setY (priv->attrib.y);
1729
 
 
1730
 
    XMoveWindow (screen->dpy (), ROOTPARENT (this),
1731
 
                 priv->attrib.x - priv->input.left,
1732
 
                 priv->attrib.y - priv->input.top);
1733
 
 
1734
 
    if (priv->frame)
1735
 
    {
1736
 
        XMoveWindow (screen->dpy (), priv->wrapper,
1737
 
                     priv->input.left, priv->input.top);
1738
 
        sendConfigureNotify ();
1739
 
    }
1740
 
}
1741
 
 
1742
 
bool
1743
 
CompWindow::focus ()
1744
 
{
1745
 
    WRAPABLE_HND_FUNC_RETURN (2, bool, focus)
1746
 
 
1747
 
    if (overrideRedirect ())
1748
 
        return false;
1749
 
 
1750
 
    if (!priv->managed || priv->unmanaging)
1751
 
        return false;
1752
 
 
1753
 
    if (!onCurrentDesktop ())
1754
 
        return false;
1755
 
 
1756
 
    if (priv->destroyed)
1757
 
        return false;
1758
 
 
1759
 
    if (!priv->shaded && (priv->state & CompWindowStateHiddenMask))
1760
 
        return false;
1761
 
 
1762
 
    if (priv->attrib.x + priv->width  <= 0      ||
1763
 
        priv->attrib.y + priv->height <= 0      ||
1764
 
        priv->attrib.x >= (int) screen->width ()||
1765
 
        priv->attrib.y >= (int) screen->height ())
1766
 
        return false;
1767
 
 
1768
 
    return true;
1769
 
}
1770
 
 
1771
 
bool
1772
 
CompWindow::place (CompPoint &pos)
1773
 
{
1774
 
    WRAPABLE_HND_FUNC_RETURN (4, bool, place, pos)
1775
 
    return false;
1776
 
}
1777
 
 
1778
 
void
1779
 
CompWindow::validateResizeRequest (unsigned int   &mask,
1780
 
                                   XWindowChanges *xwc,
1781
 
                                   unsigned int   source)
1782
 
{
1783
 
    WRAPABLE_HND_FUNC (5, validateResizeRequest, mask, xwc, source)
1784
 
 
1785
 
    if (!(priv->type & (CompWindowTypeDockMask    |
1786
 
                     CompWindowTypeFullscreenMask |
1787
 
                     CompWindowTypeUnknownMask)))
1788
 
    {
1789
 
        if (mask & CWY)
1790
 
        {
1791
 
            int min, max;
1792
 
 
1793
 
            min = screen->workArea ().y () + priv->input.top;
1794
 
            max = screen->workArea ().bottom ();
1795
 
 
1796
 
            if (priv->state & CompWindowStateStickyMask &&
1797
 
                 (xwc->y < min || xwc->y > max))
1798
 
            {
1799
 
                xwc->y = priv->serverGeometry.y ();
1800
 
            }
1801
 
            else
1802
 
            {
1803
 
                min -= screen->vp ().y () * screen->height ();
1804
 
                max += (screen->vpSize ().height () - screen->vp ().y () - 1) *
1805
 
                        screen->height ();
1806
 
 
1807
 
                if (xwc->y < min)
1808
 
                    xwc->y = min;
1809
 
                else if (xwc->y > max)
1810
 
                    xwc->y = max;
1811
 
            }
1812
 
        }
1813
 
 
1814
 
        if (mask & CWX)
1815
 
        {
1816
 
            int min, max;
1817
 
 
1818
 
            min = screen->workArea ().x () + priv->input.left;
1819
 
            max = screen->workArea ().right ();
1820
 
 
1821
 
            if (priv->state & CompWindowStateStickyMask &&
1822
 
                (xwc->x < min || xwc->x > max))
1823
 
            {
1824
 
                xwc->x = priv->serverGeometry.x ();
1825
 
            }
1826
 
            else
1827
 
            {
1828
 
                min -= screen->vp ().x () * screen->width ();
1829
 
                max += (screen->vpSize ().width () - screen->vp ().x () - 1) *
1830
 
                        screen->width ();
1831
 
 
1832
 
                if (xwc->x < min)
1833
 
                    xwc->x = min;
1834
 
                else if (xwc->x > max)
1835
 
                    xwc->x = max;
1836
 
            }
1837
 
        }
1838
 
    }
1839
 
}
1840
 
 
1841
 
void
1842
 
CompWindow::resizeNotify (int dx,
1843
 
                          int dy,
1844
 
                          int dwidth,
1845
 
                          int dheight)
1846
 
    WRAPABLE_HND_FUNC (6, resizeNotify, dx, dy, dwidth, dheight)
1847
 
 
1848
 
void
1849
 
CompWindow::moveNotify (int  dx,
1850
 
                        int  dy,
1851
 
                        bool immediate)
1852
 
    WRAPABLE_HND_FUNC (7, moveNotify, dx, dy, immediate)
1853
 
 
1854
 
void
1855
 
CompWindow::windowNotify (CompWindowNotify n)
1856
 
    WRAPABLE_HND_FUNC (8, windowNotify, n)
1857
 
 
1858
 
void
1859
 
CompWindow::grabNotify (int          x,
1860
 
                        int          y,
1861
 
                        unsigned int state,
1862
 
                        unsigned int mask)
1863
 
{
1864
 
    WRAPABLE_HND_FUNC (9, grabNotify, x, y, state, mask)
1865
 
    priv->grabbed = true;
1866
 
}
1867
 
 
1868
 
void
1869
 
CompWindow::ungrabNotify ()
1870
 
{
1871
 
    WRAPABLE_HND_FUNC (10, ungrabNotify)
1872
 
    priv->grabbed = false;
1873
 
}
1874
 
 
1875
 
void
1876
 
CompWindow::stateChangeNotify (unsigned int lastState)
1877
 
{
1878
 
    WRAPABLE_HND_FUNC (11, stateChangeNotify, lastState);
1879
 
 
1880
 
    /* if being made sticky */
1881
 
    if (!(lastState & CompWindowStateStickyMask) &&
1882
 
        (priv->state & CompWindowStateStickyMask))
1883
 
    {
1884
 
        CompPoint vp;   /* index of the window's vp */
1885
 
 
1886
 
        /* Find which viewport the window falls in,
1887
 
           and check if it's the current viewport */
1888
 
        vp = defaultViewport ();
1889
 
        if (screen->vp () != vp)
1890
 
        {
1891
 
            int moveX = (screen->vp ().x () - vp.x ()) * screen->width ();
1892
 
            int moveY = (screen->vp ().y () - vp.y ()) * screen->height ();
1893
 
 
1894
 
            move (moveX, moveY, TRUE);
1895
 
            syncPosition ();
1896
 
        }
1897
 
    }
1898
 
}
1899
 
 
1900
 
 
1901
 
bool
1902
 
PrivateWindow::isGroupTransient (Window clientLeader)
1903
 
{
1904
 
    if (!clientLeader)
1905
 
        return false;
1906
 
 
1907
 
    if (transientFor == None || transientFor == screen->root ())
1908
 
    {
1909
 
        if (type & (CompWindowTypeUtilMask    |
1910
 
                    CompWindowTypeToolbarMask |
1911
 
                    CompWindowTypeMenuMask    |
1912
 
                    CompWindowTypeDialogMask  |
1913
 
                    CompWindowTypeModalDialogMask))
1914
 
        {
1915
 
            if (this->clientLeader == clientLeader)
1916
 
                return true;
1917
 
        }
1918
 
    }
1919
 
 
1920
 
    return false;
1921
 
}
1922
 
 
1923
 
CompWindow *
1924
 
PrivateWindow::getModalTransient ()
1925
 
{
1926
 
    CompWindow *w, *modalTransient;
1927
 
 
1928
 
    modalTransient = window;
1929
 
 
1930
 
    for (w = screen->windows ().back (); w; w = w->prev)
1931
 
    {
1932
 
        if (w == modalTransient || w->priv->mapNum == 0)
1933
 
            continue;
1934
 
 
1935
 
        if (w->priv->transientFor == modalTransient->priv->id)
1936
 
        {
1937
 
            if (w->priv->state & CompWindowStateModalMask)
1938
 
            {
1939
 
                modalTransient = w;
1940
 
                w = screen->windows ().back ();
1941
 
            }
1942
 
        }
1943
 
    }
1944
 
 
1945
 
    if (modalTransient == window)
1946
 
    {
1947
 
        /* don't look for group transients with modal state if current window
1948
 
           has modal state */
1949
 
        if (state & CompWindowStateModalMask)
1950
 
            return NULL;
1951
 
 
1952
 
        for (w = screen->windows ().back (); w; w = w->prev)
1953
 
        {
1954
 
            if (w == modalTransient || w->priv->mapNum == 0)
1955
 
                continue;
1956
 
 
1957
 
            if (isAncestorTo (modalTransient, w))
1958
 
                continue;
1959
 
 
1960
 
            if (w->priv->isGroupTransient (modalTransient->priv->clientLeader))
1961
 
            {
1962
 
                if (w->priv->state & CompWindowStateModalMask)
1963
 
                {
1964
 
                    modalTransient = w;
1965
 
                    w = w->priv->getModalTransient ();
1966
 
                    if (w)
1967
 
                        modalTransient = w;
1968
 
 
1969
 
                    break;
1970
 
                }
1971
 
            }
1972
 
        }
1973
 
    }
1974
 
 
1975
 
    if (modalTransient == window)
1976
 
        modalTransient = NULL;
1977
 
 
1978
 
    return modalTransient;
1979
 
}
1980
 
 
1981
 
void
1982
 
CompWindow::moveInputFocusTo ()
1983
 
{
1984
 
    CompScreen  *s = screen;
1985
 
    CompWindow  *modalTransient;
1986
 
 
1987
 
    modalTransient = priv->getModalTransient ();
1988
 
    if (modalTransient)
1989
 
        return modalTransient->moveInputFocusTo ();
1990
 
 
1991
 
    if (priv->state & CompWindowStateHiddenMask)
1992
 
    {
1993
 
        XSetInputFocus (s->dpy (), priv->frame,
1994
 
                        RevertToPointerRoot, CurrentTime);
1995
 
        XChangeProperty (s->dpy (), s->root (), Atoms::winActive,
1996
 
                         XA_WINDOW, 32, PropModeReplace,
1997
 
                         (unsigned char *) &priv->id, 1);
1998
 
    }
1999
 
    else
2000
 
    {
2001
 
        bool setFocus = false;
2002
 
 
2003
 
        if (priv->inputHint)
2004
 
        {
2005
 
            XSetInputFocus (s->dpy (), priv->id, RevertToPointerRoot,
2006
 
                            CurrentTime);
2007
 
            setFocus = true;
2008
 
        }
2009
 
 
2010
 
        if (priv->protocols & CompWindowProtocolTakeFocusMask)
2011
 
        {
2012
 
            XEvent ev;
2013
 
 
2014
 
            ev.type                 = ClientMessage;
2015
 
            ev.xclient.window       = priv->id;
2016
 
            ev.xclient.message_type = Atoms::wmProtocols;
2017
 
            ev.xclient.format       = 32;
2018
 
            ev.xclient.data.l[0]    = Atoms::wmTakeFocus;
2019
 
            ev.xclient.data.l[1]    = s->getCurrentTime ();
2020
 
            ev.xclient.data.l[2]    = 0;
2021
 
            ev.xclient.data.l[3]    = 0;
2022
 
            ev.xclient.data.l[4]    = 0;
2023
 
 
2024
 
            XSendEvent (s->dpy (), priv->id, false, NoEventMask, &ev);
2025
 
 
2026
 
            setFocus = true;
2027
 
        }
2028
 
 
2029
 
        if (setFocus)
2030
 
            screen->priv->nextActiveWindow = priv->id;
2031
 
 
2032
 
        if (!setFocus && !modalTransient)
2033
 
        {
2034
 
            CompWindow *ancestor;
2035
 
 
2036
 
            /* move input to closest ancestor */
2037
 
            for (ancestor = s->windows ().front (); ancestor;
2038
 
                 ancestor = ancestor->next)
2039
 
            {
2040
 
                if (PrivateWindow::isAncestorTo (this, ancestor))
2041
 
                {
2042
 
                    ancestor->moveInputFocusTo ();
2043
 
                    break;
2044
 
                }
2045
 
            }
2046
 
        }
2047
 
    }
2048
 
}
2049
 
 
2050
 
void
2051
 
CompWindow::moveInputFocusToOtherWindow ()
2052
 
{
2053
 
    if (priv->id == screen->activeWindow () ||
2054
 
        priv->id == screen->priv->nextActiveWindow)
2055
 
    {
2056
 
        CompWindow *ancestor;
2057
 
 
2058
 
        if (priv->transientFor && priv->transientFor != screen->root ())
2059
 
        {
2060
 
            ancestor = screen->findWindow (priv->transientFor);
2061
 
            if (ancestor &&
2062
 
                !(ancestor->priv->type & (CompWindowTypeDesktopMask |
2063
 
                                          CompWindowTypeDockMask)))
2064
 
            {
2065
 
                ancestor->moveInputFocusTo ();
2066
 
            }
2067
 
            else
2068
 
                screen->focusDefaultWindow ();
2069
 
        }
2070
 
        else if (priv->type & (CompWindowTypeDialogMask |
2071
 
                               CompWindowTypeModalDialogMask))
2072
 
        {
2073
 
            CompWindow *a, *focus = NULL;
2074
 
 
2075
 
            for (a = screen->windows ().back (); a; a = a->prev)
2076
 
            {
2077
 
                if (a->priv->clientLeader == priv->clientLeader)
2078
 
                {
2079
 
                    if (a->focus ())
2080
 
                    {
2081
 
                        if (focus)
2082
 
                        {
2083
 
                            if (a->priv->type & (CompWindowTypeNormalMask |
2084
 
                                                 CompWindowTypeDialogMask |
2085
 
                                                 CompWindowTypeModalDialogMask))
2086
 
                            {
2087
 
                                if (priv->compareWindowActiveness (focus, a) < 0)
2088
 
                                    focus = a;
2089
 
                            }
2090
 
                        }
2091
 
                        else
2092
 
                            focus = a;
2093
 
                    }
2094
 
                }
2095
 
            }
2096
 
 
2097
 
            if (focus && !(focus->priv->type & (CompWindowTypeDesktopMask |
2098
 
                                                CompWindowTypeDockMask)))
2099
 
            {
2100
 
                focus->moveInputFocusTo ();
2101
 
            }
2102
 
            else
2103
 
                screen->focusDefaultWindow ();
2104
 
        }
2105
 
        else
2106
 
            screen->focusDefaultWindow ();
2107
 
    }
2108
 
}
2109
 
 
2110
 
 
2111
 
bool
2112
 
PrivateWindow::stackLayerCheck (CompWindow *w,
2113
 
                                Window      clientLeader,
2114
 
                                CompWindow *below)
2115
 
{
2116
 
    if (isAncestorTo (w, below))
2117
 
        return true;
2118
 
 
2119
 
    if (isAncestorTo (below, w))
2120
 
        return false;
2121
 
 
2122
 
    if (clientLeader && below->priv->clientLeader == clientLeader)
2123
 
        if (below->priv->isGroupTransient (clientLeader))
2124
 
            return false;
2125
 
 
2126
 
    if (w->priv->state & CompWindowStateAboveMask)
2127
 
    {
2128
 
        return true;
2129
 
    }
2130
 
    else if (w->priv->state & CompWindowStateBelowMask)
2131
 
    {
2132
 
        if (below->priv->state & CompWindowStateBelowMask)
2133
 
            return true;
2134
 
    }
2135
 
    else if (!(below->priv->state & CompWindowStateAboveMask))
2136
 
    {
2137
 
        return true;
2138
 
    }
2139
 
 
2140
 
    return false;
2141
 
}
2142
 
 
2143
 
bool
2144
 
PrivateWindow::avoidStackingRelativeTo (CompWindow *w)
2145
 
{
2146
 
    if (w->overrideRedirect ())
2147
 
        return true;
2148
 
 
2149
 
    if (!w->priv->shaded && !w->priv->pendingMaps)
2150
 
    {
2151
 
        if (!w->isViewable () || !w->isMapped ())
2152
 
            return true;
2153
 
    }
2154
 
 
2155
 
    return false;
2156
 
}
2157
 
 
2158
 
/* goes through the stack, top-down until we find a window we should
2159
 
   stack above, normal windows can be stacked above fullscreen windows
2160
 
   (and fullscreen windows over others in their layer) if aboveFs is true. */
2161
 
CompWindow *
2162
 
PrivateWindow::findSiblingBelow (CompWindow *w,
2163
 
                                 bool       aboveFs)
2164
 
{
2165
 
    CompWindow   *below;
2166
 
    Window       clientLeader = w->priv->clientLeader;
2167
 
    unsigned int type = w->priv->type;
2168
 
    unsigned int belowMask;
2169
 
 
2170
 
    if (aboveFs)
2171
 
        belowMask = CompWindowTypeDockMask;
2172
 
    else
2173
 
        belowMask = CompWindowTypeDockMask | CompWindowTypeFullscreenMask;
2174
 
 
2175
 
    /* normal stacking of fullscreen windows with below state */
2176
 
    if ((type & CompWindowTypeFullscreenMask) &&
2177
 
        (w->priv->state & CompWindowStateBelowMask))
2178
 
        type = CompWindowTypeNormalMask;
2179
 
 
2180
 
    if (w->priv->transientFor || w->priv->isGroupTransient (clientLeader))
2181
 
        clientLeader = None;
2182
 
 
2183
 
    for (below = screen->windows ().back (); below;
2184
 
         below = below->prev)
2185
 
    {
2186
 
        if (below == w || avoidStackingRelativeTo (below))
2187
 
            continue;
2188
 
 
2189
 
        /* always above desktop windows */
2190
 
        if (below->priv->type & CompWindowTypeDesktopMask)
2191
 
            return below;
2192
 
 
2193
 
        switch (type) {
2194
 
        case CompWindowTypeDesktopMask:
2195
 
            /* desktop window layer */
2196
 
            break;
2197
 
        case CompWindowTypeFullscreenMask:
2198
 
            if (aboveFs)
2199
 
                return below;
2200
 
            /* otherwise fall-through */
2201
 
        case CompWindowTypeDockMask:
2202
 
            /* fullscreen and dock layer */
2203
 
            if (below->priv->type & (CompWindowTypeFullscreenMask |
2204
 
                               CompWindowTypeDockMask))
2205
 
            {
2206
 
                if (stackLayerCheck (w, clientLeader, below))
2207
 
                    return below;
2208
 
            }
2209
 
            else
2210
 
            {
2211
 
                return below;
2212
 
            }
2213
 
            break;
2214
 
        default:
2215
 
            /* fullscreen and normal layer */
2216
 
            if (!(below->priv->type & belowMask))
2217
 
            {
2218
 
                if (stackLayerCheck (w, clientLeader, below))
2219
 
                    return below;
2220
 
            }
2221
 
            break;
2222
 
        }
2223
 
    }
2224
 
 
2225
 
    return NULL;
2226
 
}
2227
 
 
2228
 
/* goes through the stack, top-down and returns the lowest window we
2229
 
   can stack above. */
2230
 
CompWindow *
2231
 
PrivateWindow::findLowestSiblingBelow (CompWindow *w)
2232
 
{
2233
 
    CompWindow   *below, *lowest = screen->windows ().back ();
2234
 
    Window       clientLeader = w->priv->clientLeader;
2235
 
    unsigned int type = w->priv->type;
2236
 
 
2237
 
    /* normal stacking fullscreen windows with below state */
2238
 
    if ((type & CompWindowTypeFullscreenMask) &&
2239
 
        (w->priv->state & CompWindowStateBelowMask))
2240
 
        type = CompWindowTypeNormalMask;
2241
 
 
2242
 
    if (w->priv->transientFor || w->priv->isGroupTransient (clientLeader))
2243
 
        clientLeader = None;
2244
 
 
2245
 
    for (below = screen->windows ().back (); below;
2246
 
         below = below->prev)
2247
 
    {
2248
 
        if (below == w || avoidStackingRelativeTo (below))
2249
 
            continue;
2250
 
 
2251
 
        /* always above desktop windows */
2252
 
        if (below->priv->type & CompWindowTypeDesktopMask)
2253
 
            return below;
2254
 
 
2255
 
        switch (type) {
2256
 
        case CompWindowTypeDesktopMask:
2257
 
            /* desktop window layer - desktop windows always should be
2258
 
               stacked at the bottom; no other window should be below them */
2259
 
            return NULL;
2260
 
            break;
2261
 
        case CompWindowTypeFullscreenMask:
2262
 
        case CompWindowTypeDockMask:
2263
 
            /* fullscreen and dock layer */
2264
 
            if (below->priv->type & (CompWindowTypeFullscreenMask |
2265
 
                               CompWindowTypeDockMask))
2266
 
            {
2267
 
                if (!stackLayerCheck (below, clientLeader, w))
2268
 
                    return lowest;
2269
 
            }
2270
 
            else
2271
 
            {
2272
 
                return lowest;
2273
 
            }
2274
 
            break;
2275
 
        default:
2276
 
            /* fullscreen and normal layer */
2277
 
            if (!(below->priv->type & CompWindowTypeDockMask))
2278
 
            {
2279
 
                if (!stackLayerCheck (below, clientLeader, w))
2280
 
                    return lowest;
2281
 
            }
2282
 
            break;
2283
 
        }
2284
 
 
2285
 
        lowest = below;
2286
 
    }
2287
 
 
2288
 
    return lowest;
2289
 
}
2290
 
 
2291
 
bool
2292
 
PrivateWindow::validSiblingBelow (CompWindow *w,
2293
 
                                  CompWindow *sibling)
2294
 
{
2295
 
    Window       clientLeader = w->priv->clientLeader;
2296
 
    unsigned int type = w->priv->type;
2297
 
 
2298
 
    /* normal stacking fullscreen windows with below state */
2299
 
    if ((type & CompWindowTypeFullscreenMask) &&
2300
 
        (w->priv->state & CompWindowStateBelowMask))
2301
 
        type = CompWindowTypeNormalMask;
2302
 
 
2303
 
    if (w->priv->transientFor || w->priv->isGroupTransient (clientLeader))
2304
 
        clientLeader = None;
2305
 
 
2306
 
    if (sibling == w || avoidStackingRelativeTo (sibling))
2307
 
        return false;
2308
 
 
2309
 
    /* always above desktop windows */
2310
 
    if (sibling->priv->type & CompWindowTypeDesktopMask)
2311
 
        return true;
2312
 
 
2313
 
    switch (type) {
2314
 
    case CompWindowTypeDesktopMask:
2315
 
        /* desktop window layer */
2316
 
        break;
2317
 
    case CompWindowTypeFullscreenMask:
2318
 
    case CompWindowTypeDockMask:
2319
 
        /* fullscreen and dock layer */
2320
 
        if (sibling->priv->type & (CompWindowTypeFullscreenMask |
2321
 
                             CompWindowTypeDockMask))
2322
 
        {
2323
 
            if (stackLayerCheck (w, clientLeader, sibling))
2324
 
                return true;
2325
 
        }
2326
 
        else
2327
 
        {
2328
 
            return true;
2329
 
        }
2330
 
        break;
2331
 
    default:
2332
 
        /* fullscreen and normal layer */
2333
 
        if (!(sibling->priv->type & CompWindowTypeDockMask))
2334
 
        {
2335
 
            if (stackLayerCheck (w, clientLeader, sibling))
2336
 
                return true;
2337
 
        }
2338
 
        break;
2339
 
    }
2340
 
 
2341
 
    return false;
2342
 
}
2343
 
 
2344
 
void
2345
 
PrivateWindow::saveGeometry (int mask)
2346
 
{
2347
 
    int m = mask & ~saveMask;
2348
 
 
2349
 
    /* only save geometry if window has been placed */
2350
 
    if (!placed)
2351
 
        return;
2352
 
 
2353
 
    if (m & CWX)
2354
 
        saveWc.x = serverGeometry.x ();
2355
 
 
2356
 
    if (m & CWY)
2357
 
        saveWc.y = serverGeometry.y ();
2358
 
 
2359
 
    if (m & CWWidth)
2360
 
        saveWc.width = serverGeometry.width ();
2361
 
 
2362
 
    if (m & CWHeight)
2363
 
        saveWc.height = serverGeometry.height ();
2364
 
 
2365
 
    if (m & CWBorderWidth)
2366
 
        saveWc.border_width = serverGeometry.border ();
2367
 
 
2368
 
    saveMask |= m;
2369
 
}
2370
 
 
2371
 
int
2372
 
PrivateWindow::restoreGeometry (XWindowChanges *xwc,
2373
 
                                int            mask)
2374
 
{
2375
 
    int m = mask & saveMask;
2376
 
 
2377
 
    if (m & CWX)
2378
 
        xwc->x = saveWc.x;
2379
 
 
2380
 
    if (m & CWY)
2381
 
        xwc->y = saveWc.y;
2382
 
 
2383
 
    if (m & CWWidth)
2384
 
    {
2385
 
        xwc->width = saveWc.width;
2386
 
 
2387
 
        /* This is not perfect but it works OK for now. If the saved width is
2388
 
           the same as the current width then make it a little be smaller so
2389
 
           the user can see that it changed and it also makes sure that
2390
 
           windowResizeNotify is called and plugins are notified. */
2391
 
        if (xwc->width == (int) serverGeometry.width ())
2392
 
        {
2393
 
            xwc->width -= 10;
2394
 
            if (m & CWX)
2395
 
                xwc->x += 5;
2396
 
        }
2397
 
    }
2398
 
 
2399
 
    if (m & CWHeight)
2400
 
    {
2401
 
        xwc->height = saveWc.height;
2402
 
 
2403
 
        /* As above, if the saved height is the same as the current height
2404
 
           then make it a little be smaller. */
2405
 
        if (xwc->height == (int) serverGeometry.height ())
2406
 
        {
2407
 
            xwc->height -= 10;
2408
 
            if (m & CWY)
2409
 
                xwc->y += 5;
2410
 
        }
2411
 
    }
2412
 
 
2413
 
    if (m & CWBorderWidth)
2414
 
        xwc->border_width = saveWc.border_width;
2415
 
 
2416
 
    saveMask &= ~mask;
2417
 
 
2418
 
    return m;
2419
 
}
2420
 
 
2421
 
void
2422
 
PrivateWindow::reconfigureXWindow (unsigned int   valueMask,
2423
 
                                   XWindowChanges *xwc)
2424
 
{
2425
 
    if (valueMask & CWX)
2426
 
        serverGeometry.setX (xwc->x);
2427
 
 
2428
 
    if (valueMask & CWY)
2429
 
        serverGeometry.setY (xwc->y);
2430
 
 
2431
 
    if (valueMask & CWWidth)
2432
 
        serverGeometry.setWidth (xwc->width);
2433
 
 
2434
 
    if (valueMask & CWHeight)
2435
 
        serverGeometry.setHeight (xwc->height);
2436
 
 
2437
 
    if (valueMask & CWBorderWidth)
2438
 
        serverGeometry.setBorder (xwc->border_width);
2439
 
 
2440
 
    /* Compiz's window list is immediately restacked on reconfigureXWindow
2441
 
       in order to ensure correct operation of the raise, lower and restacking
2442
 
       functions. This function should only recieve stack_mode == Above
2443
 
       but warn incase something else does get through, to make the cause
2444
 
       of any potential misbehaviour obvious. */
2445
 
    if (valueMask & (CWSibling | CWStackMode))
2446
 
    {
2447
 
        if (xwc->stack_mode == Above)
2448
 
            restack (xwc->sibling);
2449
 
        else
2450
 
            compLogMessage ("core", CompLogLevelWarn, "restack_mode not Above");
2451
 
    }
2452
 
 
2453
 
    if (frame)
2454
 
    {
2455
 
        XWindowChanges wc = *xwc;
2456
 
 
2457
 
        wc.x      -= input.left;
2458
 
        wc.y      -= input.top;
2459
 
        wc.width  += input.left + input.right;
2460
 
        wc.height += input.top + input.bottom;
2461
 
 
2462
 
        XConfigureWindow (screen->dpy (), frame, valueMask, &wc);
2463
 
        valueMask &= ~(CWSibling | CWStackMode);
2464
 
 
2465
 
        xwc->x = input.left;
2466
 
        xwc->y = input.top;
2467
 
        XConfigureWindow (screen->dpy (), wrapper, valueMask, xwc);
2468
 
 
2469
 
        xwc->x = 0;
2470
 
        xwc->y = 0;
2471
 
    }
2472
 
 
2473
 
    XConfigureWindow (screen->dpy (), id, valueMask, xwc);
2474
 
}
2475
 
 
2476
 
bool
2477
 
PrivateWindow::stackTransients (CompWindow      *w,
2478
 
                                CompWindow      *avoid,
2479
 
                                XWindowChanges *xwc,
2480
 
                                CompWindowList &updateList)
2481
 
{
2482
 
    CompWindow *t;
2483
 
    Window     clientLeader = w->priv->clientLeader;
2484
 
 
2485
 
    if (w->priv->transientFor || w->priv->isGroupTransient (clientLeader))
2486
 
        clientLeader = None;
2487
 
 
2488
 
    for (t = screen->windows ().back (); t; t = t->prev)
2489
 
    {
2490
 
        if (t == w || t == avoid)
2491
 
            continue;
2492
 
 
2493
 
        if (t->priv->transientFor == w->priv->id ||
2494
 
            t->priv->isGroupTransient (clientLeader))
2495
 
        {
2496
 
            if (w->priv->type & CompWindowTypeDockMask)
2497
 
                if (!(t->priv->type & CompWindowTypeDockMask))
2498
 
                    return false;
2499
 
 
2500
 
            if (!stackTransients (t, avoid, xwc, updateList))
2501
 
                return false;
2502
 
 
2503
 
            if (xwc->sibling == t->priv->id ||
2504
 
                (t->priv->frame && xwc->sibling == t->priv->frame))
2505
 
                return false;
2506
 
 
2507
 
            if (t->priv->mapNum || t->priv->pendingMaps)
2508
 
                updateList.push_back (t);
2509
 
        }
2510
 
    }
2511
 
 
2512
 
    return true;
2513
 
}
2514
 
 
2515
 
void
2516
 
PrivateWindow::stackAncestors (CompWindow     *w,
2517
 
                               XWindowChanges *xwc,
2518
 
                               CompWindowList &updateList)
2519
 
{
2520
 
    CompWindow *transient = NULL;
2521
 
 
2522
 
    if (w->priv->transientFor)
2523
 
        transient = screen->findWindow (w->priv->transientFor);
2524
 
 
2525
 
    if (transient                           &&
2526
 
        xwc->sibling != transient->priv->id &&
2527
 
        (!transient->priv->frame || xwc->sibling != transient->priv->frame))
2528
 
    {
2529
 
        CompWindow *ancestor;
2530
 
 
2531
 
        ancestor = screen->findWindow (w->priv->transientFor);
2532
 
        if (ancestor)
2533
 
        {
2534
 
            if (!stackTransients (ancestor, w, xwc, updateList))
2535
 
                return;
2536
 
 
2537
 
            if (ancestor->priv->type & CompWindowTypeDesktopMask)
2538
 
                return;
2539
 
 
2540
 
            if (ancestor->priv->type & CompWindowTypeDockMask)
2541
 
                if (!(w->priv->type & CompWindowTypeDockMask))
2542
 
                    return;
2543
 
 
2544
 
            if (ancestor->priv->mapNum || ancestor->priv->pendingMaps)
2545
 
                updateList.push_back (ancestor);
2546
 
 
2547
 
            stackAncestors (ancestor, xwc, updateList);
2548
 
        }
2549
 
    }
2550
 
    else if (w->priv->isGroupTransient (w->priv->clientLeader))
2551
 
    {
2552
 
        CompWindow *a;
2553
 
 
2554
 
        for (a = screen->windows ().back (); a; a = a->prev)
2555
 
        {
2556
 
            if (a->priv->clientLeader == w->priv->clientLeader &&
2557
 
                a->priv->transientFor == None                  &&
2558
 
                !a->priv->isGroupTransient (w->priv->clientLeader))
2559
 
            {
2560
 
                if (xwc->sibling == a->priv->id ||
2561
 
                    (a->priv->frame && xwc->sibling == a->priv->frame))
2562
 
                    break;
2563
 
 
2564
 
                if (!stackTransients (a, w, xwc, updateList))
2565
 
                    break;
2566
 
 
2567
 
                if (a->priv->type & CompWindowTypeDesktopMask)
2568
 
                    continue;
2569
 
 
2570
 
                if (a->priv->type & CompWindowTypeDockMask)
2571
 
                    if (!(w->priv->type & CompWindowTypeDockMask))
2572
 
                        break;
2573
 
 
2574
 
                if (a->priv->mapNum || a->priv->pendingMaps)
2575
 
                    updateList.push_back (a);
2576
 
            }
2577
 
        }
2578
 
    }
2579
 
}
2580
 
 
2581
 
void
2582
 
CompWindow::configureXWindow (unsigned int valueMask,
2583
 
                              XWindowChanges *xwc)
2584
 
{
2585
 
    if (priv->managed && (valueMask & (CWSibling | CWStackMode)))
2586
 
    {
2587
 
        CompWindowList transients;
2588
 
        CompWindowList ancestors;
2589
 
 
2590
 
        /* Since the window list is being reordered in reconfigureXWindow
2591
 
           the list of windows which need to be restacked must be stored
2592
 
           first. The windows are stacked in the opposite order than they
2593
 
           were previously stacked, in order that they are above xwc->sibling
2594
 
           so that when compiz gets the ConfigureNotify event it doesn't
2595
 
           have to restack all the windows again. */
2596
 
 
2597
 
        /* transient children above */
2598
 
        if (PrivateWindow::stackTransients (this, NULL, xwc, transients))
2599
 
        {
2600
 
            /* ancestors, siblings and sibling transients below */
2601
 
            PrivateWindow::stackAncestors (this, xwc, ancestors);
2602
 
 
2603
 
            for (CompWindowList::reverse_iterator w = ancestors.rbegin ();
2604
 
                 w != ancestors.rend (); w++)
2605
 
            {
2606
 
                (*w)->priv->reconfigureXWindow (CWSibling | CWStackMode, xwc);
2607
 
                xwc->sibling = ROOTPARENT (*w);
2608
 
            }
2609
 
 
2610
 
            this->priv->reconfigureXWindow (valueMask, xwc);
2611
 
            xwc->sibling = ROOTPARENT (this);
2612
 
 
2613
 
            for (CompWindowList::reverse_iterator w = transients.rbegin ();
2614
 
                 w != transients.rend (); w++)
2615
 
            {
2616
 
                (*w)->priv->reconfigureXWindow (CWSibling | CWStackMode, xwc);
2617
 
                xwc->sibling = ROOTPARENT (*w);
2618
 
            }
2619
 
        }
2620
 
    }
2621
 
    else
2622
 
    {
2623
 
        priv->reconfigureXWindow (valueMask, xwc);
2624
 
    }
2625
 
}
2626
 
 
2627
 
int
2628
 
PrivateWindow::addWindowSizeChanges (XWindowChanges       *xwc,
2629
 
                                     CompWindow::Geometry old)
2630
 
{
2631
 
    CompRect  workArea;
2632
 
    int       mask = 0;
2633
 
    int       x, y;
2634
 
    int       output;
2635
 
    CompPoint viewport;
2636
 
 
2637
 
    screen->viewportForGeometry (old, viewport);
2638
 
 
2639
 
    x = (viewport.x () - screen->vp ().x ()) * screen->width ();
2640
 
    y = (viewport.y () - screen->vp ().y ()) * screen->height ();
2641
 
 
2642
 
    output   = screen->outputDeviceForGeometry (old);
2643
 
    workArea = screen->getWorkareaForOutput (output);
2644
 
 
2645
 
    if (type & CompWindowTypeFullscreenMask)
2646
 
    {
2647
 
        saveGeometry (CWX | CWY | CWWidth | CWHeight | CWBorderWidth);
2648
 
 
2649
 
        if (fullscreenMonitorsSet)
2650
 
        {
2651
 
            xwc->x      = x + fullscreenMonitorRect.x ();
2652
 
            xwc->y      = y + fullscreenMonitorRect.y ();
2653
 
            xwc->width  = fullscreenMonitorRect.width ();
2654
 
            xwc->height = fullscreenMonitorRect.height ();
2655
 
        }
2656
 
        else
2657
 
        {
2658
 
            xwc->x      = x + screen->outputDevs ()[output].x ();
2659
 
            xwc->y      = y + screen->outputDevs ()[output].y ();
2660
 
            xwc->width  = screen->outputDevs ()[output].width ();
2661
 
            xwc->height = screen->outputDevs ()[output].height ();
2662
 
        }
2663
 
 
2664
 
        xwc->border_width = 0;
2665
 
 
2666
 
        mask |= CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
2667
 
    }
2668
 
    else
2669
 
    {
2670
 
        mask |= restoreGeometry (xwc, CWBorderWidth);
2671
 
 
2672
 
        if (state & CompWindowStateMaximizedVertMask)
2673
 
        {
2674
 
            saveGeometry (CWY | CWHeight);
2675
 
 
2676
 
            xwc->height = workArea.height () - input.top -
2677
 
                          input.bottom - old.border () * 2;
2678
 
 
2679
 
            mask |= CWHeight;
2680
 
        }
2681
 
        else
2682
 
        {
2683
 
            mask |= restoreGeometry (xwc, CWY | CWHeight);
2684
 
        }
2685
 
 
2686
 
        if (state & CompWindowStateMaximizedHorzMask)
2687
 
        {
2688
 
            saveGeometry (CWX | CWWidth);
2689
 
 
2690
 
            xwc->width = workArea.width () - input.left -
2691
 
                         input.right - old.border () * 2;
2692
 
 
2693
 
            mask |= CWWidth;
2694
 
        }
2695
 
        else
2696
 
        {
2697
 
            mask |= restoreGeometry (xwc, CWX | CWWidth);
2698
 
        }
2699
 
 
2700
 
        /* constrain window width if smaller than minimum width */
2701
 
        if (!(mask & CWWidth) && (int) old.width () < sizeHints.min_width)
2702
 
        {
2703
 
            xwc->width = sizeHints.min_width;
2704
 
            mask |= CWWidth;
2705
 
        }
2706
 
 
2707
 
        /* constrain window width if greater than maximum width */
2708
 
        if (!(mask & CWWidth) && (int) old.width () > sizeHints.max_width)
2709
 
        {
2710
 
            xwc->width = sizeHints.max_width;
2711
 
            mask |= CWWidth;
2712
 
        }
2713
 
 
2714
 
        /* constrain window height if smaller than minimum height */
2715
 
        if (!(mask & CWHeight) && (int) old.height () < sizeHints.min_height)
2716
 
        {
2717
 
            xwc->height = sizeHints.min_height;
2718
 
            mask |= CWHeight;
2719
 
        }
2720
 
 
2721
 
        /* constrain window height if greater than maximum height */
2722
 
        if (!(mask & CWHeight) && (int) old.height () > sizeHints.max_height)
2723
 
        {
2724
 
            xwc->height = sizeHints.max_height;
2725
 
            mask |= CWHeight;
2726
 
        }
2727
 
 
2728
 
        if (mask & (CWWidth | CWHeight))
2729
 
        {
2730
 
            int width, height, max;
2731
 
 
2732
 
            width  = (mask & CWWidth)  ? xwc->width  : old.width ();
2733
 
            height = (mask & CWHeight) ? xwc->height : old.height ();
2734
 
 
2735
 
            xwc->width  = old.width ();
2736
 
            xwc->height = old.height ();
2737
 
 
2738
 
            window->constrainNewWindowSize (width, height, &width, &height);
2739
 
 
2740
 
            if (width != (int) old.width ())
2741
 
            {
2742
 
                mask |= CWWidth;
2743
 
                xwc->width = width;
2744
 
            }
2745
 
            else
2746
 
                mask &= ~CWWidth;
2747
 
 
2748
 
            if (height != (int) old.height ())
2749
 
            {
2750
 
                mask |= CWHeight;
2751
 
                xwc->height = height;
2752
 
            }
2753
 
            else
2754
 
                mask &= ~CWHeight;
2755
 
 
2756
 
            if (state & CompWindowStateMaximizedVertMask)
2757
 
            {
2758
 
                if (old.y () < y + workArea.y () + input.top)
2759
 
                {
2760
 
                    xwc->y = y + workArea.y () + input.top;
2761
 
                    mask |= CWY;
2762
 
                }
2763
 
                else
2764
 
                {
2765
 
                    height = xwc->height + old.border () * 2;
2766
 
 
2767
 
                    max = y + workArea.bottom ();
2768
 
                    if (old.y () + (int) old.height () + input.bottom > max)
2769
 
                    {
2770
 
                        xwc->y = max - height - input.bottom;
2771
 
                        mask |= CWY;
2772
 
                    }
2773
 
                    else if (old.y () + height + input.bottom > max)
2774
 
                    {
2775
 
                        xwc->y = y + workArea.y () +
2776
 
                                 (workArea.height () - input.top - height -
2777
 
                                  input.bottom) / 2 + input.top;
2778
 
                        mask |= CWY;
2779
 
                    }
2780
 
                }
2781
 
            }
2782
 
 
2783
 
            if (state & CompWindowStateMaximizedHorzMask)
2784
 
            {
2785
 
                if (old.x () < x + workArea.x () + input.left)
2786
 
                {
2787
 
                    xwc->x = x + workArea.x () + input.left;
2788
 
                    mask |= CWX;
2789
 
                }
2790
 
                else
2791
 
                {
2792
 
                    width = xwc->width + old.border () * 2;
2793
 
 
2794
 
                    max = x + workArea.right ();
2795
 
                    if (old.x () + (int) old.width () + input.right > max)
2796
 
                    {
2797
 
                        xwc->x = max - width - input.right;
2798
 
                        mask |= CWX;
2799
 
                    }
2800
 
                    else if (old.x () + width + input.right > max)
2801
 
                    {
2802
 
                        xwc->x = x + workArea.x () +
2803
 
                                 (workArea.width () - input.left - width -
2804
 
                                  input.right) / 2 + input.left;
2805
 
                        mask |= CWX;
2806
 
                    }
2807
 
                }
2808
 
            }
2809
 
        }
2810
 
    }
2811
 
 
2812
 
    if ((mask & CWX) && (xwc->x == old.x ()))
2813
 
        mask &= ~CWX;
2814
 
 
2815
 
    if ((mask & CWY) && (xwc->y == old.y ()))
2816
 
        mask &= ~CWY;
2817
 
 
2818
 
    if ((mask & CWWidth) && (xwc->width == (int) old.width ()))
2819
 
        mask &= ~CWWidth;
2820
 
 
2821
 
    if ((mask & CWHeight) && (xwc->height == (int) old.height ()))
2822
 
        mask &= ~CWHeight;
2823
 
 
2824
 
    return mask;
2825
 
}
2826
 
 
2827
 
unsigned int
2828
 
PrivateWindow::adjustConfigureRequestForGravity (XWindowChanges *xwc,
2829
 
                                                 unsigned int   xwcm,
2830
 
                                                 int            gravity,
2831
 
                                                 int            direction)
2832
 
{
2833
 
    int          newX, newY;
2834
 
    unsigned int mask = 0;
2835
 
 
2836
 
    newX = xwc->x;
2837
 
    newY = xwc->y;
2838
 
 
2839
 
    if (xwcm & (CWX | CWWidth))
2840
 
    {
2841
 
        switch (gravity) {
2842
 
        case NorthWestGravity:
2843
 
        case WestGravity:
2844
 
        case SouthWestGravity:
2845
 
            if (xwcm & CWX)
2846
 
                newX += priv->input.left * direction;
2847
 
            break;
2848
 
 
2849
 
        case NorthGravity:
2850
 
        case CenterGravity:
2851
 
        case SouthGravity:
2852
 
            if (xwcm & CWX)
2853
 
                newX -= (xwc->width / 2 - priv->input.left +
2854
 
                        (priv->input.left + priv->input.right) / 2) * direction;
2855
 
            else
2856
 
                newX -= (xwc->width - priv->serverGeometry.width ()) * direction;
2857
 
            break;
2858
 
 
2859
 
        case NorthEastGravity:
2860
 
        case EastGravity:
2861
 
        case SouthEastGravity:
2862
 
            if (xwcm & CWX)
2863
 
                newX -= xwc->width + priv->input.right * direction;
2864
 
            else
2865
 
                newX -= (xwc->width - priv->serverGeometry.width ()) * direction;
2866
 
            break;
2867
 
 
2868
 
        case StaticGravity:
2869
 
        default:
2870
 
            break;
2871
 
        }
2872
 
    }
2873
 
 
2874
 
    if (xwcm & (CWY | CWHeight))
2875
 
    {
2876
 
        switch (gravity) {
2877
 
        case NorthWestGravity:
2878
 
        case NorthGravity:
2879
 
        case NorthEastGravity:
2880
 
            if (xwcm & CWY)
2881
 
                newY = xwc->y + priv->input.top * direction;
2882
 
            break;
2883
 
 
2884
 
        case WestGravity:
2885
 
        case CenterGravity:
2886
 
        case EastGravity:
2887
 
            if (xwcm & CWY)
2888
 
                newY -= (xwc->height / 2 - priv->input.top +
2889
 
                        (priv->input.top + priv->input.bottom) / 2) * direction;
2890
 
            else
2891
 
                newY -= ((xwc->height - priv->serverGeometry.height ()) / 2) * direction;
2892
 
            break;
2893
 
 
2894
 
        case SouthWestGravity:
2895
 
        case SouthGravity:
2896
 
        case SouthEastGravity:
2897
 
            if (xwcm & CWY)
2898
 
                newY -= xwc->height + priv->input.bottom * direction;
2899
 
            else
2900
 
                newY -= (xwc->height - priv->serverGeometry.height ()) * direction;
2901
 
            break;
2902
 
 
2903
 
        case StaticGravity:
2904
 
        default:
2905
 
            break;
2906
 
        }
2907
 
    }
2908
 
 
2909
 
    if (newX != xwc->x)
2910
 
    {
2911
 
        xwc->x += (newX - xwc->x);
2912
 
        mask |= CWX;
2913
 
    }
2914
 
 
2915
 
    if (newY != xwc->y)
2916
 
    {
2917
 
        xwc->y += (newY - xwc->y);
2918
 
        mask |= CWY;
2919
 
    }
2920
 
 
2921
 
    return mask;
2922
 
}
2923
 
 
2924
 
void
2925
 
CompWindow::moveResize (XWindowChanges *xwc,
2926
 
                        unsigned int   xwcm,
2927
 
                        int            gravity,
2928
 
                        unsigned int   source)
2929
 
{
2930
 
    bool placed = false;
2931
 
 
2932
 
    xwcm &= (CWX | CWY | CWWidth | CWHeight | CWBorderWidth);
2933
 
 
2934
 
    if (xwcm & (CWX | CWY))
2935
 
        if (priv->sizeHints.flags & (USPosition | PPosition))
2936
 
            placed = true;
2937
 
 
2938
 
    if (gravity == 0)
2939
 
        gravity = priv->sizeHints.win_gravity;
2940
 
 
2941
 
    if (!(xwcm & CWX))
2942
 
        xwc->x = priv->serverGeometry.x ();
2943
 
    if (!(xwcm & CWY))
2944
 
        xwc->y = priv->serverGeometry.y ();
2945
 
    if (!(xwcm & CWWidth))
2946
 
        xwc->width = priv->serverGeometry.width ();
2947
 
    if (!(xwcm & CWHeight))
2948
 
        xwc->height = priv->serverGeometry.height ();
2949
 
 
2950
 
    if (xwcm & (CWWidth | CWHeight))
2951
 
    {
2952
 
        int width, height;
2953
 
 
2954
 
        if (constrainNewWindowSize (xwc->width, xwc->height, &width, &height))
2955
 
        {
2956
 
            if (width != xwc->width)
2957
 
                xwcm |= CWWidth;
2958
 
 
2959
 
            if (height != xwc->height)
2960
 
                xwcm |= CWHeight;
2961
 
 
2962
 
            xwc->width = width;
2963
 
            xwc->height = height;
2964
 
        }
2965
 
    }
2966
 
 
2967
 
    xwcm |= priv->adjustConfigureRequestForGravity (xwc, xwcm, gravity, 1);
2968
 
 
2969
 
    validateResizeRequest (xwcm, xwc, source);
2970
 
 
2971
 
    /* when horizontally maximized only allow width changes added by
2972
 
       addWindowSizeChanges */
2973
 
    if (priv->state & CompWindowStateMaximizedHorzMask)
2974
 
        xwcm &= ~CWWidth;
2975
 
 
2976
 
    /* when vertically maximized only allow height changes added by
2977
 
       addWindowSizeChanges */
2978
 
    if (priv->state & CompWindowStateMaximizedVertMask)
2979
 
        xwcm &= ~CWHeight;
2980
 
 
2981
 
    xwcm |= priv->addWindowSizeChanges (xwc, Geometry (xwc->x, xwc->y,
2982
 
                                        xwc->width, xwc->height,
2983
 
                                        xwc->border_width));
2984
 
 
2985
 
    /* check if the new coordinates are useful and valid (different
2986
 
       to current size); if not, we have to clear them to make sure
2987
 
       we send a synthetic ConfigureNotify event if all coordinates
2988
 
       match the server coordinates */
2989
 
    if (xwc->x == priv->serverGeometry.x ())
2990
 
        xwcm &= ~CWX;
2991
 
 
2992
 
    if (xwc->y == priv->serverGeometry.y ())
2993
 
        xwcm &= ~CWY;
2994
 
 
2995
 
    if (xwc->width == (int) priv->serverGeometry.width ())
2996
 
        xwcm &= ~CWWidth;
2997
 
 
2998
 
    if (xwc->height == (int) priv->serverGeometry.height ())
2999
 
        xwcm &= ~CWHeight;
3000
 
 
3001
 
    if (xwc->border_width == (int) priv->serverGeometry.border ())
3002
 
        xwcm &= ~CWBorderWidth;
3003
 
 
3004
 
    /* update saved window coordinates - if CWX or CWY is set for fullscreen
3005
 
       or maximized windows after addWindowSizeChanges, it should be pretty
3006
 
       safe to assume that the saved coordinates should be updated too, e.g.
3007
 
       because the window was moved to another viewport by some client */
3008
 
    if ((xwcm & CWX) && (priv->saveMask & CWX))
3009
 
        priv->saveWc.x += (xwc->x - priv->serverGeometry.x ());
3010
 
 
3011
 
    if ((xwcm & CWY) && (priv->saveMask & CWY))
3012
 
        priv->saveWc.y += (xwc->y - priv->serverGeometry.y ());
3013
 
 
3014
 
    if (priv->mapNum && (xwcm & (CWWidth | CWHeight)))
3015
 
        sendSyncRequest ();
3016
 
 
3017
 
    if (xwcm)
3018
 
        configureXWindow (xwcm, xwc);
3019
 
    else
3020
 
    {
3021
 
        /* we have to send a configure notify on ConfigureRequest events if
3022
 
           we decide not to do anything according to ICCCM 4.1.5 */
3023
 
        sendConfigureNotify ();
3024
 
    }
3025
 
 
3026
 
    if (placed)
3027
 
        priv->placed = true;
3028
 
}
3029
 
 
3030
 
void
3031
 
PrivateWindow::updateSize ()
3032
 
{
3033
 
    XWindowChanges xwc;
3034
 
    int            mask;
3035
 
 
3036
 
    if (window->overrideRedirect () || !managed)
3037
 
        return;
3038
 
 
3039
 
    mask = priv->addWindowSizeChanges (&xwc, priv->serverGeometry);
3040
 
    if (mask)
3041
 
    {
3042
 
        if (priv->mapNum && (mask & (CWWidth | CWHeight)))
3043
 
            window->sendSyncRequest ();
3044
 
 
3045
 
        window->configureXWindow (mask, &xwc);
3046
 
    }
3047
 
}
3048
 
 
3049
 
int
3050
 
PrivateWindow::addWindowStackChanges (XWindowChanges *xwc,
3051
 
                                      CompWindow     *sibling)
3052
 
{
3053
 
    int mask = 0;
3054
 
 
3055
 
    if (!sibling || sibling->priv->id != id)
3056
 
    {
3057
 
        if (window->prev)
3058
 
        {
3059
 
            if (!sibling)
3060
 
            {
3061
 
                XLowerWindow (screen->dpy (), id);
3062
 
                if (frame)
3063
 
                    XLowerWindow (screen->dpy (), frame);
3064
 
 
3065
 
                /* Restacking of compiz's window list happens
3066
 
                   immediately and since this path doesn't call
3067
 
                   reconfigureXWindow, restack must be called here. */
3068
 
                restack (0);
3069
 
            }
3070
 
            else if (sibling->priv->id != window->prev->priv->id)
3071
 
            {
3072
 
                mask |= CWSibling | CWStackMode;
3073
 
 
3074
 
                xwc->stack_mode = Above;
3075
 
                xwc->sibling    = ROOTPARENT (sibling);
3076
 
            }
3077
 
        }
3078
 
        else if (sibling)
3079
 
        {
3080
 
            mask |= CWSibling | CWStackMode;
3081
 
 
3082
 
            xwc->stack_mode = Above;
3083
 
            xwc->sibling    = ROOTPARENT (sibling);
3084
 
        }
3085
 
    }
3086
 
 
3087
 
    if (sibling && mask)
3088
 
    {
3089
 
        /* a normal window can be stacked above fullscreen windows but we
3090
 
           don't want normal windows to be stacked above dock window so if
3091
 
           the sibling we're stacking above is a fullscreen window we also
3092
 
           update all dock windows. */
3093
 
        if ((sibling->priv->type & CompWindowTypeFullscreenMask) &&
3094
 
            (!(type & (CompWindowTypeFullscreenMask |
3095
 
                          CompWindowTypeDockMask))) &&
3096
 
            !isAncestorTo (window, sibling))
3097
 
        {
3098
 
            CompWindow *dw;
3099
 
 
3100
 
            for (dw = screen->windows ().back (); dw; dw = dw->prev)
3101
 
                if (dw == sibling)
3102
 
                    break;
3103
 
 
3104
 
            /* Collect all dock windows first */
3105
 
            CompWindowList dockWindows;
3106
 
            for (; dw; dw = dw->prev)
3107
 
                if (dw->priv->type & CompWindowTypeDockMask)
3108
 
                    dockWindows.push_back (dw);
3109
 
 
3110
 
            /* Then update the dock windows */
3111
 
            foreach (CompWindow *dw, dockWindows)
3112
 
                dw->configureXWindow (mask, xwc);
3113
 
        }
3114
 
    }
3115
 
 
3116
 
    return mask;
3117
 
}
3118
 
 
3119
 
void
3120
 
CompWindow::raise ()
3121
 
{
3122
 
    XWindowChanges xwc;
3123
 
    int            mask;
3124
 
    bool           aboveFs = false;
3125
 
 
3126
 
    /* an active fullscreen window should be raised over all other
3127
 
       windows in its layer */
3128
 
    if (priv->type & CompWindowTypeFullscreenMask)
3129
 
        if (priv->id == screen->activeWindow ())
3130
 
            aboveFs = true;
3131
 
 
3132
 
    mask = priv->addWindowStackChanges (&xwc,
3133
 
        PrivateWindow::findSiblingBelow (this, aboveFs));
3134
 
 
3135
 
    if (mask)
3136
 
        configureXWindow (mask, &xwc);
3137
 
}
3138
 
 
3139
 
CompWindow *
3140
 
PrivateScreen::focusTopMostWindow ()
3141
 
{
3142
 
    CompWindow  *focus = NULL;
3143
 
    CompWindowList::reverse_iterator it = windows.rbegin ();
3144
 
 
3145
 
    for (; it != windows.rend (); it++)
3146
 
    {
3147
 
        CompWindow *w = *it;
3148
 
 
3149
 
        if (w->type () & CompWindowTypeDockMask)
3150
 
            continue;
3151
 
 
3152
 
        if (w->focus ())
3153
 
        {
3154
 
            focus = w;
3155
 
            break;
3156
 
        }
3157
 
    }
3158
 
 
3159
 
    if (focus)
3160
 
    {
3161
 
        if (focus->id () != activeWindow)
3162
 
            focus->moveInputFocusTo ();
3163
 
    }
3164
 
    else
3165
 
        XSetInputFocus (dpy, root, RevertToPointerRoot,
3166
 
                        CurrentTime);
3167
 
    return focus;
3168
 
}
3169
 
 
3170
 
 
3171
 
void
3172
 
CompWindow::lower ()
3173
 
{
3174
 
    XWindowChanges xwc;
3175
 
    int            mask;
3176
 
 
3177
 
    mask = priv->addWindowStackChanges (&xwc,
3178
 
        PrivateWindow::findLowestSiblingBelow (this));
3179
 
    if (mask)
3180
 
        configureXWindow (mask, &xwc);
3181
 
 
3182
 
    /* when lowering a window, focus the topmost window if
3183
 
       the click-to-focus option is on */
3184
 
    if ((screen->getOption ("click_to_focus")->value ().b ()))
3185
 
    {
3186
 
        Window aboveWindowId = prev ? prev->id () : None;
3187
 
        screen->unhookWindow (this);
3188
 
        CompWindow *focusedWindow = screen->priv->focusTopMostWindow ();
3189
 
        screen->insertWindow (this , aboveWindowId);
3190
 
 
3191
 
        /* if the newly focused window is a desktop window,
3192
 
           give the focus back to w */
3193
 
        if (focusedWindow &&
3194
 
            focusedWindow->type () & CompWindowTypeDesktopMask)
3195
 
        {
3196
 
            moveInputFocusTo ();
3197
 
        }
3198
 
    }
3199
 
}
3200
 
 
3201
 
void
3202
 
CompWindow::restackAbove (CompWindow *sibling)
3203
 
{
3204
 
    for (; sibling; sibling = sibling->next)
3205
 
        if (PrivateWindow::validSiblingBelow (this, sibling))
3206
 
            break;
3207
 
 
3208
 
    if (sibling)
3209
 
    {
3210
 
        XWindowChanges xwc;
3211
 
        int            mask;
3212
 
 
3213
 
        mask = priv->addWindowStackChanges (&xwc, sibling);
3214
 
        if (mask)
3215
 
            configureXWindow (mask, &xwc);
3216
 
    }
3217
 
}
3218
 
 
3219
 
/* finds the highest window under sibling we can stack above */
3220
 
CompWindow *
3221
 
PrivateWindow::findValidStackSiblingBelow (CompWindow *w,
3222
 
                                           CompWindow *sibling)
3223
 
{
3224
 
    CompWindow *lowest, *last, *p;
3225
 
 
3226
 
    /* check whether we're allowed to stack under a sibling by finding
3227
 
     * the above 'sibling' and checking whether or not we're allowed
3228
 
     * to stack under that - if not, then there is no valid sibling
3229
 
     * underneath it */
3230
 
 
3231
 
    for (p = sibling; p; p = p->next)
3232
 
    {
3233
 
        if (!avoidStackingRelativeTo (p))
3234
 
        {
3235
 
            if (!validSiblingBelow (p, w))
3236
 
                return NULL;
3237
 
            break;
3238
 
        }
3239
 
    }
3240
 
 
3241
 
    /* get lowest sibling we're allowed to stack above */
3242
 
    lowest = last = findLowestSiblingBelow (w);
3243
 
 
3244
 
    /* walk from bottom up */
3245
 
    for (p = screen->windows ().front (); p; p = p->next)
3246
 
    {
3247
 
        /* stop walking when we reach the sibling we should try to stack
3248
 
           below */
3249
 
        if (p == sibling)
3250
 
            return lowest;
3251
 
 
3252
 
        /* skip windows that we should avoid */
3253
 
        if (w == p || avoidStackingRelativeTo (p))
3254
 
            continue;
3255
 
 
3256
 
        if (validSiblingBelow (w, p))
3257
 
        {
3258
 
            /* update lowest as we find windows below sibling that we're
3259
 
               allowed to stack above. last window must be equal to the
3260
 
               lowest as we shouldn't update lowest if we passed an
3261
 
               invalid window */
3262
 
            if (last == lowest)
3263
 
                lowest = p;
3264
 
        }
3265
 
 
3266
 
        /* update last pointer */
3267
 
        last = p;
3268
 
    }
3269
 
 
3270
 
    return lowest;
3271
 
}
3272
 
 
3273
 
void
3274
 
CompWindow::restackBelow (CompWindow *sibling)
3275
 
{
3276
 
    XWindowChanges xwc;
3277
 
    unsigned int   mask;
3278
 
 
3279
 
    mask = priv->addWindowStackChanges (&xwc,
3280
 
        PrivateWindow::findValidStackSiblingBelow (this, sibling));
3281
 
 
3282
 
    if (mask)
3283
 
        configureXWindow (mask, &xwc);
3284
 
}
3285
 
 
3286
 
void
3287
 
CompWindow::updateAttributes (CompStackingUpdateMode stackingMode)
3288
 
{
3289
 
    XWindowChanges xwc;
3290
 
    int            mask = 0;
3291
 
 
3292
 
    if (overrideRedirect () || !priv->managed)
3293
 
        return;
3294
 
 
3295
 
    if (priv->state & CompWindowStateShadedMask)
3296
 
    {
3297
 
        windowNotify (CompWindowNotifyShade);
3298
 
 
3299
 
        priv->hide ();
3300
 
    }
3301
 
    else if (priv->shaded)
3302
 
    {
3303
 
        windowNotify (CompWindowNotifyUnshade);
3304
 
 
3305
 
        priv->show ();
3306
 
    }
3307
 
 
3308
 
    if (stackingMode != CompStackingUpdateModeNone)
3309
 
    {
3310
 
        bool       aboveFs;
3311
 
        CompWindow *sibling;
3312
 
 
3313
 
        aboveFs = (stackingMode == CompStackingUpdateModeAboveFullscreen);
3314
 
        if (priv->type & CompWindowTypeFullscreenMask)
3315
 
        {
3316
 
            /* put active or soon-to-be-active fullscreen windows over
3317
 
               all others in their layer */
3318
 
            if (priv->id == screen->activeWindow ())
3319
 
            {
3320
 
                aboveFs = true;
3321
 
            }
3322
 
        }
3323
 
 
3324
 
        /* put windows that are just mapped, over fullscreen windows */
3325
 
        if (stackingMode == CompStackingUpdateModeInitialMap)
3326
 
            aboveFs = true;
3327
 
 
3328
 
        sibling = PrivateWindow::findSiblingBelow (this, aboveFs);
3329
 
 
3330
 
        if (sibling &&
3331
 
            (stackingMode == CompStackingUpdateModeInitialMapDeniedFocus))
3332
 
        {
3333
 
            CompWindow *p;
3334
 
 
3335
 
            for (p = sibling; p; p = p->prev)
3336
 
                if (p->priv->id == screen->activeWindow ())
3337
 
                    break;
3338
 
 
3339
 
            /* window is above active window so we should lower it,
3340
 
             * assuing that is allowed (if, for example, our window has
3341
 
             * the "above" state, then lowering beneath the active
3342
 
             * window may not be allowed). */
3343
 
            if (p && PrivateWindow::validSiblingBelow (p, this))
3344
 
            {
3345
 
                p = PrivateWindow::findValidStackSiblingBelow (sibling, p);
3346
 
 
3347
 
                /* if we found a valid sibling under the active window, it's
3348
 
                   our new sibling we want to stack above */
3349
 
                if (p)
3350
 
                    sibling = p;
3351
 
            }
3352
 
        }
3353
 
 
3354
 
        mask |= priv->addWindowStackChanges (&xwc, sibling);
3355
 
    }
3356
 
 
3357
 
    if ((stackingMode == CompStackingUpdateModeInitialMap) ||
3358
 
        (stackingMode == CompStackingUpdateModeInitialMapDeniedFocus))
3359
 
    {
3360
 
        /* If we are called from the MapRequest handler, we have to
3361
 
           immediately update the internal stack. If we don't do that,
3362
 
           the internal stacking order is invalid until the ConfigureNotify
3363
 
           arrives because we put the window at the top of the stack when
3364
 
           it was created */
3365
 
        if (mask & CWStackMode)
3366
 
        {
3367
 
            Window above = (mask & CWSibling) ? xwc.sibling : 0;
3368
 
            priv->restack (above);
3369
 
        }
3370
 
    }
3371
 
 
3372
 
    mask |= priv->addWindowSizeChanges (&xwc, priv->serverGeometry);
3373
 
 
3374
 
    if (priv->mapNum && (mask & (CWWidth | CWHeight)))
3375
 
        sendSyncRequest ();
3376
 
 
3377
 
    if (mask)
3378
 
        configureXWindow (mask, &xwc);
3379
 
}
3380
 
 
3381
 
void
3382
 
PrivateWindow::ensureWindowVisibility ()
3383
 
{
3384
 
    int x1, y1, x2, y2;
3385
 
    int width = serverGeometry.width () + serverGeometry.border () * 2;
3386
 
    int height = serverGeometry.height () + serverGeometry.border () * 2;
3387
 
    int dx = 0;
3388
 
    int dy = 0;
3389
 
 
3390
 
    if (struts || attrib.override_redirect)
3391
 
        return;
3392
 
 
3393
 
    if (type & (CompWindowTypeDockMask       |
3394
 
                CompWindowTypeFullscreenMask |
3395
 
                CompWindowTypeUnknownMask))
3396
 
        return;
3397
 
 
3398
 
    x1 = screen->workArea ().x () - screen->width () * screen->vp ().x ();
3399
 
    y1 = screen->workArea ().y () - screen->height () * screen->vp ().y ();
3400
 
    x2 = x1 + screen->workArea ().width () + screen->vpSize ().width () *
3401
 
         screen->width ();
3402
 
    y2 = y1 + screen->workArea ().height () + screen->vpSize ().height () *
3403
 
         screen->height ();
3404
 
 
3405
 
    if (serverGeometry.x () - input.left >= x2)
3406
 
        dx = (x2 - 25) - serverGeometry.x ();
3407
 
    else if (serverGeometry.x () + width + input.right <= x1)
3408
 
        dx = (x1 + 25) - (serverGeometry.x () + width);
3409
 
 
3410
 
    if (serverGeometry.y () - input.top >= y2)
3411
 
        dy = (y2 - 25) - serverGeometry.y ();
3412
 
    else if (serverGeometry.y () + height + input.bottom <= y1)
3413
 
        dy = (y1 + 25) - (serverGeometry.y () + height);
3414
 
 
3415
 
    if (dx || dy)
3416
 
    {
3417
 
        XWindowChanges xwc;
3418
 
 
3419
 
        xwc.x = serverGeometry.x () + dx;
3420
 
        xwc.y = serverGeometry.y () + dy;
3421
 
 
3422
 
        window->configureXWindow (CWX | CWY, &xwc);
3423
 
    }
3424
 
}
3425
 
 
3426
 
void
3427
 
PrivateWindow::reveal ()
3428
 
{
3429
 
    if (window->minimized ())
3430
 
        window->unminimize ();
3431
 
 
3432
 
    screen->leaveShowDesktopMode (window);
3433
 
}
3434
 
 
3435
 
void
3436
 
PrivateWindow::revealAncestors (CompWindow *w,
3437
 
                                CompWindow *transient)
3438
 
{
3439
 
    if (isAncestorTo (transient, w))
3440
 
    {
3441
 
        screen->forEachWindow (boost::bind (revealAncestors, _1, w));
3442
 
        w->priv->reveal ();
3443
 
    }
3444
 
}
3445
 
 
3446
 
void
3447
 
CompWindow::activate ()
3448
 
{
3449
 
    WRAPABLE_HND_FUNC (3, activate)
3450
 
 
3451
 
    screen->priv->setCurrentDesktop (priv->desktop);
3452
 
 
3453
 
    screen->forEachWindow (
3454
 
        boost::bind (PrivateWindow::revealAncestors, _1, this));
3455
 
    priv->reveal ();
3456
 
 
3457
 
    if (priv->state & CompWindowStateHiddenMask)
3458
 
    {
3459
 
        priv->state &= ~CompWindowStateShadedMask;
3460
 
        if (priv->shaded)
3461
 
            priv->show ();
3462
 
    }
3463
 
 
3464
 
    if (priv->state & CompWindowStateHiddenMask)
3465
 
        return;
3466
 
 
3467
 
    if (!onCurrentDesktop ())
3468
 
        return;
3469
 
 
3470
 
    priv->ensureWindowVisibility ();
3471
 
    updateAttributes (CompStackingUpdateModeAboveFullscreen);
3472
 
    moveInputFocusTo ();
3473
 
}
3474
 
 
3475
 
 
3476
 
#define PVertResizeInc (1 << 0)
3477
 
#define PHorzResizeInc (1 << 1)
3478
 
 
3479
 
bool
3480
 
CompWindow::constrainNewWindowSize (int        width,
3481
 
                                    int        height,
3482
 
                                    int        *newWidth,
3483
 
                                    int        *newHeight)
3484
 
{
3485
 
    const XSizeHints *hints = &priv->sizeHints;
3486
 
    int              oldWidth = width;
3487
 
    int              oldHeight = height;
3488
 
    int              min_width = 0;
3489
 
    int              min_height = 0;
3490
 
    int              base_width = 0;
3491
 
    int              base_height = 0;
3492
 
    int              xinc = 1;
3493
 
    int              yinc = 1;
3494
 
    int              max_width = MAXSHORT;
3495
 
    int              max_height = MAXSHORT;
3496
 
    long             flags = hints->flags;
3497
 
    long             resizeIncFlags = (flags & PResizeInc) ? ~0 : 0;
3498
 
 
3499
 
    if (screen->getOption ("ignore_hints_when_maximized")->value ().b ())
3500
 
    {
3501
 
        if (priv->state & MAXIMIZE_STATE)
3502
 
        {
3503
 
            flags &= ~PAspect;
3504
 
 
3505
 
            if (priv->state & CompWindowStateMaximizedHorzMask)
3506
 
                resizeIncFlags &= ~PHorzResizeInc;
3507
 
 
3508
 
            if (priv->state & CompWindowStateMaximizedVertMask)
3509
 
                resizeIncFlags &= ~PVertResizeInc;
3510
 
        }
3511
 
    }
3512
 
 
3513
 
    /* Ater gdk_window_constrain_size(), which is partially borrowed from fvwm.
3514
 
     *
3515
 
     * Copyright 1993, Robert Nation
3516
 
     *     You may use this code for any purpose, as long as the original
3517
 
     *     copyright remains in the source code and all documentation
3518
 
     *
3519
 
     * which in turn borrows parts of the algorithm from uwm
3520
 
     */
3521
 
 
3522
 
#define FLOOR(value, base) (((int) ((value) / (base))) * (base))
3523
 
#define FLOOR64(value, base) (((uint64_t) ((value) / (base))) * (base))
3524
 
#define CLAMPW(v, min, max) ((v) <= (min) ? (min) : (v) >= (max) ? (max) : (v))
3525
 
 
3526
 
    if ((flags & PBaseSize) && (flags & PMinSize))
3527
 
    {
3528
 
        base_width = hints->base_width;
3529
 
        base_height = hints->base_height;
3530
 
        min_width = hints->min_width;
3531
 
        min_height = hints->min_height;
3532
 
    }
3533
 
    else if (flags & PBaseSize)
3534
 
    {
3535
 
        base_width = hints->base_width;
3536
 
        base_height = hints->base_height;
3537
 
        min_width = hints->base_width;
3538
 
        min_height = hints->base_height;
3539
 
    }
3540
 
    else if (flags & PMinSize)
3541
 
    {
3542
 
        base_width = hints->min_width;
3543
 
        base_height = hints->min_height;
3544
 
        min_width = hints->min_width;
3545
 
        min_height = hints->min_height;
3546
 
    }
3547
 
 
3548
 
    if (flags & PMaxSize)
3549
 
    {
3550
 
        max_width = hints->max_width;
3551
 
        max_height = hints->max_height;
3552
 
    }
3553
 
 
3554
 
    if (resizeIncFlags & PHorzResizeInc)
3555
 
        xinc = MAX (xinc, hints->width_inc);
3556
 
 
3557
 
    if (resizeIncFlags & PVertResizeInc)
3558
 
        yinc = MAX (yinc, hints->height_inc);
3559
 
 
3560
 
    /* clamp width and height to min and max values */
3561
 
    width  = CLAMPW (width, min_width, max_width);
3562
 
    height = CLAMPW (height, min_height, max_height);
3563
 
 
3564
 
    /* shrink to base + N * inc */
3565
 
    width  = base_width + FLOOR (width - base_width, xinc);
3566
 
    height = base_height + FLOOR (height - base_height, yinc);
3567
 
 
3568
 
    /* constrain aspect ratio, according to:
3569
 
     *
3570
 
     * min_aspect.x       width      max_aspect.x
3571
 
     * ------------  <= -------- <=  -----------
3572
 
     * min_aspect.y       height     max_aspect.y
3573
 
     */
3574
 
    if ((flags & PAspect) && hints->min_aspect.y > 0 && hints->max_aspect.x > 0)
3575
 
    {
3576
 
        /* Use 64 bit arithmetic to prevent overflow */
3577
 
 
3578
 
        uint64_t min_aspect_x = hints->min_aspect.x;
3579
 
        uint64_t min_aspect_y = hints->min_aspect.y;
3580
 
        uint64_t max_aspect_x = hints->max_aspect.x;
3581
 
        uint64_t max_aspect_y = hints->max_aspect.y;
3582
 
        uint64_t delta;
3583
 
 
3584
 
        if (min_aspect_x * height > width * min_aspect_y)
3585
 
        {
3586
 
            delta = FLOOR64 (height - width * min_aspect_y / min_aspect_x,
3587
 
                             yinc);
3588
 
            if (height - (int) delta >= min_height)
3589
 
                height -= delta;
3590
 
            else
3591
 
            {
3592
 
                delta = FLOOR64 (height * min_aspect_x / min_aspect_y - width,
3593
 
                                 xinc);
3594
 
                if (width + (int) delta <= max_width)
3595
 
                    width += delta;
3596
 
            }
3597
 
        }
3598
 
 
3599
 
        if (width * max_aspect_y > max_aspect_x * height)
3600
 
        {
3601
 
            delta = FLOOR64 (width - height * max_aspect_x / max_aspect_y,
3602
 
                             xinc);
3603
 
            if (width - (int) delta >= min_width)
3604
 
                width -= delta;
3605
 
            else
3606
 
            {
3607
 
                delta = FLOOR64 (width * min_aspect_y / min_aspect_x - height,
3608
 
                                 yinc);
3609
 
                if (height + (int) delta <= max_height)
3610
 
                    height += delta;
3611
 
            }
3612
 
        }
3613
 
    }
3614
 
 
3615
 
#undef CLAMPW
3616
 
#undef FLOOR64
3617
 
#undef FLOOR
3618
 
 
3619
 
    if (width != oldWidth || height != oldHeight)
3620
 
    {
3621
 
        *newWidth  = width;
3622
 
        *newHeight = height;
3623
 
 
3624
 
        return true;
3625
 
    }
3626
 
 
3627
 
    return false;
3628
 
}
3629
 
 
3630
 
void
3631
 
CompWindow::hide ()
3632
 
{
3633
 
    priv->hidden = true;
3634
 
    priv->hide ();
3635
 
}
3636
 
 
3637
 
void
3638
 
CompWindow::show ()
3639
 
{
3640
 
    priv->hidden = false;
3641
 
    priv->show ();
3642
 
}
3643
 
 
3644
 
void
3645
 
PrivateWindow::hide ()
3646
 
{
3647
 
    bool onDesktop = window->onCurrentDesktop ();
3648
 
 
3649
 
    if (!managed)
3650
 
        return;
3651
 
 
3652
 
    if (!window->minimized () && !inShowDesktopMode &&
3653
 
        !hidden && onDesktop)
3654
 
    {
3655
 
        if (state & CompWindowStateShadedMask)
3656
 
        {
3657
 
            shaded = true;
3658
 
        }
3659
 
        else
3660
 
        {
3661
 
            return;
3662
 
        }
3663
 
    }
3664
 
    else
3665
 
    {
3666
 
        shaded = false;
3667
 
 
3668
 
        if ((state & CompWindowStateShadedMask) && frame)
3669
 
            XUnmapWindow (screen->dpy (), frame);
3670
 
    }
3671
 
 
3672
 
    if (!pendingMaps && !window->isViewable ())
3673
 
        return;
3674
 
 
3675
 
    window->windowNotify (CompWindowNotifyHide);
3676
 
 
3677
 
    pendingUnmaps++;
3678
 
 
3679
 
    if (frame && !shaded)
3680
 
        XUnmapWindow (screen->dpy (), frame);
3681
 
 
3682
 
    XUnmapWindow (screen->dpy (), id);
3683
 
 
3684
 
    if (window->minimized () || inShowDesktopMode || hidden || shaded)
3685
 
        window->changeState (state | CompWindowStateHiddenMask);
3686
 
 
3687
 
    if (shaded && id == screen->activeWindow ())
3688
 
        window->moveInputFocusTo ();
3689
 
}
3690
 
 
3691
 
void
3692
 
PrivateWindow::show ()
3693
 
{
3694
 
    bool onDesktop = window->onCurrentDesktop ();
3695
 
 
3696
 
    if (!managed)
3697
 
        return;
3698
 
 
3699
 
    if (minimized || inShowDesktopMode ||
3700
 
        hidden    || !onDesktop)
3701
 
    {
3702
 
        /* no longer hidden but not on current desktop */
3703
 
        if (!minimized && !inShowDesktopMode && !hidden)
3704
 
            window->changeState (state & ~CompWindowStateHiddenMask);
3705
 
 
3706
 
        return;
3707
 
    }
3708
 
 
3709
 
    /* transition from minimized to shaded */
3710
 
    if (state & CompWindowStateShadedMask)
3711
 
    {
3712
 
        shaded = true;
3713
 
 
3714
 
        if (frame)
3715
 
            XMapWindow (screen->dpy (), frame);
3716
 
 
3717
 
        if (height)
3718
 
            window->resize (attrib.x, attrib.y,
3719
 
                            attrib.width, ++attrib.height - 1,
3720
 
                            attrib.border_width);
3721
 
 
3722
 
        return;
3723
 
    }
3724
 
    else
3725
 
    {
3726
 
        shaded = false;
3727
 
    }
3728
 
 
3729
 
    window->windowNotify (CompWindowNotifyShow);
3730
 
 
3731
 
    pendingMaps++;
3732
 
 
3733
 
    if (frame)
3734
 
    {
3735
 
        XMapWindow (screen->dpy (), frame);
3736
 
        XMapWindow (screen->dpy (), wrapper);
3737
 
    }
3738
 
 
3739
 
    XMapWindow (screen->dpy (), id);
3740
 
 
3741
 
    window->changeState (state & ~CompWindowStateHiddenMask);
3742
 
    screen->priv->setWindowState (state, id);
3743
 
}
3744
 
 
3745
 
void
3746
 
PrivateWindow::minimizeTransients (CompWindow *w,
3747
 
                                   CompWindow *ancestor)
3748
 
{
3749
 
    if (w->priv->transientFor == ancestor->priv->id ||
3750
 
        w->priv->isGroupTransient (ancestor->priv->clientLeader))
3751
 
    {
3752
 
        w->minimize ();
3753
 
    }
3754
 
}
3755
 
 
3756
 
void
3757
 
CompWindow::minimize ()
3758
 
{
3759
 
    WRAPABLE_HND_FUNC (13, minimize);
3760
 
 
3761
 
    if (!priv->managed)
3762
 
        return;
3763
 
 
3764
 
    if (!priv->minimized)
3765
 
    {
3766
 
        windowNotify (CompWindowNotifyMinimize);
3767
 
 
3768
 
        priv->minimized = true;
3769
 
 
3770
 
        screen->forEachWindow (
3771
 
            boost::bind (PrivateWindow::minimizeTransients, _1, this));
3772
 
 
3773
 
        priv->hide ();
3774
 
    }
3775
 
}
3776
 
 
3777
 
void
3778
 
PrivateWindow::unminimizeTransients (CompWindow *w,
3779
 
                                     CompWindow *ancestor)
3780
 
{
3781
 
    if (w->priv->transientFor == ancestor->priv->id ||
3782
 
        w->priv->isGroupTransient (ancestor->priv->clientLeader))
3783
 
        w->unminimize ();
3784
 
}
3785
 
 
3786
 
void
3787
 
CompWindow::unminimize ()
3788
 
{
3789
 
    WRAPABLE_HND_FUNC (14, unminimize);
3790
 
    if (priv->minimized)
3791
 
    {
3792
 
        windowNotify (CompWindowNotifyUnminimize);
3793
 
 
3794
 
        priv->minimized = false;
3795
 
 
3796
 
        priv->show ();
3797
 
 
3798
 
        screen->forEachWindow (
3799
 
            boost::bind (PrivateWindow::unminimizeTransients, _1, this));
3800
 
    }
3801
 
}
3802
 
 
3803
 
void
3804
 
CompWindow::maximize (unsigned int state)
3805
 
{
3806
 
    if (overrideRedirect ())
3807
 
        return;
3808
 
 
3809
 
    state = constrainWindowState (state, priv->actions);
3810
 
 
3811
 
    state &= MAXIMIZE_STATE;
3812
 
 
3813
 
    if (state == (priv->state & MAXIMIZE_STATE))
3814
 
        return;
3815
 
 
3816
 
    state |= (priv->state & ~MAXIMIZE_STATE);
3817
 
 
3818
 
    changeState (state);
3819
 
    updateAttributes (CompStackingUpdateModeNone);
3820
 
}
3821
 
 
3822
 
bool
3823
 
PrivateWindow::getUserTime (Time& time)
3824
 
{
3825
 
    Atom          actual;
3826
 
    int           result, format;
3827
 
    unsigned long n, left;
3828
 
    unsigned char *data;
3829
 
    bool          retval = false;
3830
 
 
3831
 
    result = XGetWindowProperty (screen->dpy (), priv->id,
3832
 
                                 Atoms::wmUserTime,
3833
 
                                 0L, 1L, False, XA_CARDINAL, &actual, &format,
3834
 
                                 &n, &left, &data);
3835
 
 
3836
 
    if (result == Success && data)
3837
 
    {
3838
 
        if (n)
3839
 
        {
3840
 
            CARD32 value;
3841
 
 
3842
 
            memcpy (&value, data, sizeof (CARD32));
3843
 
            retval = true;
3844
 
            time   = (Time) value;
3845
 
        }
3846
 
 
3847
 
        XFree ((void *) data);
3848
 
    }
3849
 
 
3850
 
    return retval;
3851
 
}
3852
 
 
3853
 
void
3854
 
PrivateWindow::setUserTime (Time time)
3855
 
{
3856
 
    CARD32 value = (CARD32) time;
3857
 
 
3858
 
    XChangeProperty (screen->dpy (), priv->id,
3859
 
                     Atoms::wmUserTime,
3860
 
                     XA_CARDINAL, 32, PropModeReplace,
3861
 
                     (unsigned char *) &value, 1);
3862
 
}
3863
 
 
3864
 
/*
3865
 
 * Macros from metacity
3866
 
 *
3867
 
 * Xserver time can wraparound, thus comparing two timestamps needs to
3868
 
 * take this into account.  Here's a little macro to help out.  If no
3869
 
 * wraparound has occurred, this is equivalent to
3870
 
 *   time1 < time2
3871
 
 * Of course, the rest of the ugliness of this macro comes from
3872
 
 * accounting for the fact that wraparound can occur and the fact that
3873
 
 * a timestamp of 0 must be special-cased since it means older than
3874
 
 * anything else.
3875
 
 *
3876
 
 * Note that this is NOT an equivalent for time1 <= time2; if that's
3877
 
 * what you need then you'll need to swap the order of the arguments
3878
 
 * and negate the result.
3879
 
 */
3880
 
#define XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) \
3881
 
    ( (( (time1) < (time2) ) &&                                       \
3882
 
       ( (time2) - (time1) < ((unsigned long) -1) / 2 )) ||           \
3883
 
      (( (time1) > (time2) ) &&                                       \
3884
 
       ( (time1) - (time2) > ((unsigned long) -1) / 2 ))              \
3885
 
        )
3886
 
#define XSERVER_TIME_IS_BEFORE(time1, time2)                             \
3887
 
    ( (time1) == 0 ||                                                    \
3888
 
      (XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS (time1, time2) && \
3889
 
       (time2) != 0)                                                     \
3890
 
        )
3891
 
 
3892
 
bool
3893
 
PrivateWindow::getUsageTimestamp (Time& timestamp)
3894
 
{
3895
 
    if (getUserTime (timestamp))
3896
 
        return true;
3897
 
 
3898
 
    if (initialTimestampSet)
3899
 
    {
3900
 
        timestamp = initialTimestamp;
3901
 
        return true;
3902
 
    }
3903
 
 
3904
 
    return false;
3905
 
}
3906
 
 
3907
 
bool
3908
 
PrivateWindow::isWindowFocusAllowed (Time timestamp)
3909
 
{
3910
 
    CompScreen   *s = screen;
3911
 
    CompWindow   *active;
3912
 
    Time         wUserTime, aUserTime;
3913
 
    bool         gotTimestamp = false;
3914
 
    int          level;
3915
 
    CompPoint    dvp;
3916
 
 
3917
 
    level = s->getOption ("focus_prevention_level")->value ().i ();
3918
 
 
3919
 
    if (level == CoreOptions::FocusPreventionLevelOff)
3920
 
        return true;
3921
 
 
3922
 
    if (timestamp)
3923
 
    {
3924
 
        /* the caller passed a timestamp, so use that
3925
 
           instead of the window's user time */
3926
 
        wUserTime = timestamp;
3927
 
        gotTimestamp = true;
3928
 
    }
3929
 
    else
3930
 
    {
3931
 
        gotTimestamp = getUsageTimestamp (wUserTime);
3932
 
    }
3933
 
 
3934
 
    /* if we got no timestamp for the window, try to get at least a timestamp
3935
 
       for its transient parent, if any */
3936
 
    if (!gotTimestamp && transientFor)
3937
 
    {
3938
 
        CompWindow *parent;
3939
 
 
3940
 
        parent = screen->findWindow (transientFor);
3941
 
        if (parent)
3942
 
            gotTimestamp = parent->priv->getUsageTimestamp (wUserTime);
3943
 
    }
3944
 
 
3945
 
    if (gotTimestamp && !wUserTime)
3946
 
    {
3947
 
        /* window explicitly requested no focus */
3948
 
        return false;
3949
 
    }
3950
 
 
3951
 
    /* allow focus for excluded windows */
3952
 
    CompMatch &match =
3953
 
        s->getOption ("focus_prevention_match")->value ().match ();
3954
 
    if (!match.evaluate (window))
3955
 
        return true;
3956
 
 
3957
 
    if (level == CoreOptions::FocusPreventionLevelVeryHigh)
3958
 
        return false;
3959
 
 
3960
 
    active = s->findWindow (s->activeWindow ());
3961
 
 
3962
 
    /* no active window */
3963
 
    if (!active || (active->type () & CompWindowTypeDesktopMask))
3964
 
        return true;
3965
 
 
3966
 
    /* active window belongs to same application */
3967
 
    if (window->clientLeader () == active->clientLeader ())
3968
 
       return true;
3969
 
 
3970
 
    if (level == CoreOptions::FocusPreventionLevelHigh)
3971
 
       return false;
3972
 
 
3973
 
    /* not in current viewport or desktop */
3974
 
    if (!window->onCurrentDesktop ())
3975
 
        return false;
3976
 
 
3977
 
    dvp = window->defaultViewport ();
3978
 
    if (dvp.x () != s->vp ().x () || dvp.y () != s->vp ().y ())
3979
 
        return false;
3980
 
 
3981
 
    if (!gotTimestamp)
3982
 
    {
3983
 
        /* unsure as we have nothing to compare - allow focus in low level,
3984
 
           don't allow in normal level */
3985
 
        if (level == CoreOptions::FocusPreventionLevelNormal)
3986
 
            return false;
3987
 
 
3988
 
        return true;
3989
 
    }
3990
 
 
3991
 
    /* can't get user time for active window */
3992
 
    if (!active->priv->getUserTime (aUserTime))
3993
 
        return true;
3994
 
 
3995
 
    if (XSERVER_TIME_IS_BEFORE (wUserTime, aUserTime))
3996
 
        return false;
3997
 
 
3998
 
    return true;
3999
 
}
4000
 
 
4001
 
bool
4002
 
PrivateWindow::allowWindowFocus (unsigned int noFocusMask,
4003
 
                                 Time         timestamp)
4004
 
{
4005
 
    bool retval;
4006
 
 
4007
 
    if (priv->id == screen->activeWindow ())
4008
 
        return true;
4009
 
 
4010
 
    /* do not focus windows of these types */
4011
 
    if (priv->type & noFocusMask)
4012
 
        return false;
4013
 
 
4014
 
    /* window doesn't take focus */
4015
 
    if (!priv->inputHint &&
4016
 
        !(priv->protocols & CompWindowProtocolTakeFocusMask))
4017
 
    {
4018
 
        return false;
4019
 
    }
4020
 
 
4021
 
    retval = priv->isWindowFocusAllowed (timestamp);
4022
 
    if (!retval)
4023
 
    {
4024
 
        /* add demands attention state if focus was prevented */
4025
 
        window->changeState (priv->state | CompWindowStateDemandsAttentionMask);
4026
 
    }
4027
 
 
4028
 
    return retval;
4029
 
}
4030
 
 
4031
 
CompPoint
4032
 
CompWindow::defaultViewport ()
4033
 
{
4034
 
    CompPoint viewport;
4035
 
 
4036
 
    if (priv->serverGeometry.x () < (int) screen->width ()            &&
4037
 
        priv->serverGeometry.x () + priv->serverGeometry.width () > 0 &&
4038
 
        priv->serverGeometry.y () < (int) screen->height ()           &&
4039
 
        priv->serverGeometry.y ()+ priv->serverGeometry.height () > 0)
4040
 
    {
4041
 
        return screen->vp ();
4042
 
    }
4043
 
 
4044
 
    screen->viewportForGeometry (priv->serverGeometry, viewport);
4045
 
 
4046
 
    return viewport;
4047
 
}
4048
 
 
4049
 
CompPoint &
4050
 
CompWindow::initialViewport () const
4051
 
{
4052
 
    return priv->initialViewport;
4053
 
}
4054
 
 
4055
 
void
4056
 
PrivateWindow::readIconHint ()
4057
 
{
4058
 
    XImage       *image, *maskImage = NULL;
4059
 
    Display      *dpy = screen->dpy ();
4060
 
    unsigned int width, height, dummy;
4061
 
    unsigned int i, j, k;
4062
 
    int          iDummy;
4063
 
    Window       wDummy;
4064
 
    CompIcon     *icon;
4065
 
    XColor       *colors;
4066
 
    CARD32       *p;
4067
 
 
4068
 
    if (!XGetGeometry (dpy, hints->icon_pixmap, &wDummy, &iDummy,
4069
 
                       &iDummy, &width, &height, &dummy, &dummy))
4070
 
        return;
4071
 
 
4072
 
    image = XGetImage (dpy, hints->icon_pixmap, 0, 0, width, height,
4073
 
                       AllPlanes, ZPixmap);
4074
 
    if (!image)
4075
 
        return;
4076
 
 
4077
 
    colors = new XColor[width * height];
4078
 
    if (!colors)
4079
 
    {
4080
 
        XDestroyImage (image);
4081
 
        return;
4082
 
    }
4083
 
 
4084
 
    k = 0;
4085
 
    for (j = 0; j < height; j++)
4086
 
        for (i = 0; i < width; i++)
4087
 
            colors[k++].pixel = XGetPixel (image, i, j);
4088
 
 
4089
 
    for (i = 0; i < k; i += 256)
4090
 
        XQueryColors (dpy, screen->priv->colormap,
4091
 
                      &colors[i], MIN (k - i, 256));
4092
 
 
4093
 
    XDestroyImage (image);
4094
 
 
4095
 
    icon = new CompIcon (screen, width, height);
4096
 
    if (!icon)
4097
 
    {
4098
 
        delete [] colors;
4099
 
        return;
4100
 
    }
4101
 
 
4102
 
    if (hints->flags & IconMaskHint)
4103
 
        maskImage = XGetImage (dpy, hints->icon_mask, 0, 0,
4104
 
                               width, height, AllPlanes, ZPixmap);
4105
 
 
4106
 
    k = 0;
4107
 
    p = (CARD32 *) icon->data ();
4108
 
 
4109
 
    for (j = 0; j < height; j++)
4110
 
    {
4111
 
        for (i = 0; i < width; i++)
4112
 
        {
4113
 
            if (maskImage && !XGetPixel (maskImage, i, j))
4114
 
                *p++ = 0;
4115
 
            else if (image->depth == 1)  /* white   : black */
4116
 
                *p++ = colors[k].pixel ? 0xffffffff : 0xff000000;
4117
 
            else
4118
 
                *p++ = 0xff000000                             | /* alpha */
4119
 
                       (((colors[k].red >> 8) & 0xff) << 16)  | /* red */
4120
 
                       (((colors[k].green >> 8) & 0xff) << 8) | /* green */
4121
 
                       ((colors[k].blue >> 8) & 0xff);          /* blue */
4122
 
 
4123
 
            k++;
4124
 
        }
4125
 
    }
4126
 
 
4127
 
    delete [] colors;
4128
 
    if (maskImage)
4129
 
        XDestroyImage (maskImage);
4130
 
 
4131
 
    icons.push_back (icon);
4132
 
}
4133
 
 
4134
 
/* returns icon with dimensions as close as possible to width and height
4135
 
   but never greater. */
4136
 
CompIcon *
4137
 
CompWindow::getIcon (int width,
4138
 
                     int height)
4139
 
{
4140
 
    CompIcon     *icon;
4141
 
    int          wh, diff, oldDiff;
4142
 
    unsigned int i;
4143
 
 
4144
 
    /* need to fetch icon property */
4145
 
    if (priv->icons.size () == 0 && !priv->noIcons)
4146
 
    {
4147
 
        Atom          actual;
4148
 
        int           result, format;
4149
 
        unsigned long n, left;
4150
 
        unsigned char *data;
4151
 
 
4152
 
        result = XGetWindowProperty (screen->dpy (), priv->id, Atoms::wmIcon,
4153
 
                                     0L, 65536L, false, XA_CARDINAL,
4154
 
                                     &actual, &format, &n, &left, &data);
4155
 
 
4156
 
        if (result == Success && data)
4157
 
        {
4158
 
            CARD32        *p;
4159
 
            CARD32        alpha, red, green, blue;
4160
 
            unsigned long iw, ih;
4161
 
 
4162
 
            for (i = 0; i + 2 < n; i += iw * ih + 2)
4163
 
            {
4164
 
                unsigned long *idata = (unsigned long *) data;
4165
 
 
4166
 
                iw = idata[i];
4167
 
                ih = idata[i + 1];
4168
 
 
4169
 
                /* iw * ih may be larger than the value range of unsigned
4170
 
                * long, so better do some checking for extremely weird
4171
 
                * icon sizes first */
4172
 
                if (iw > 2048 || ih > 2048 || iw * ih + 2 > n - i)
4173
 
                    break;
4174
 
 
4175
 
                if (iw && ih)
4176
 
                {
4177
 
                    unsigned long j;
4178
 
                    icon = new CompIcon (screen, iw, ih);
4179
 
                    if (!icon)
4180
 
                        continue;
4181
 
 
4182
 
                    priv->icons.push_back (icon);
4183
 
 
4184
 
                    p = (CARD32 *) (icon->data ());
4185
 
 
4186
 
                    /* EWMH doesn't say if icon data is premultiplied or
4187
 
                       not but most applications seem to assume data should
4188
 
                       be unpremultiplied. */
4189
 
                    for (j = 0; j < iw * ih; j++)
4190
 
                    {
4191
 
                        alpha = (idata[i + j + 2] >> 24) & 0xff;
4192
 
                        red   = (idata[i + j + 2] >> 16) & 0xff;
4193
 
                        green = (idata[i + j + 2] >>  8) & 0xff;
4194
 
                        blue  = (idata[i + j + 2] >>  0) & 0xff;
4195
 
 
4196
 
                        red   = (red   * alpha) >> 8;
4197
 
                        green = (green * alpha) >> 8;
4198
 
                        blue  = (blue  * alpha) >> 8;
4199
 
 
4200
 
                        p[j] =
4201
 
                            (alpha << 24) |
4202
 
                            (red   << 16) |
4203
 
                            (green <<  8) |
4204
 
                            (blue  <<  0);
4205
 
                    }
4206
 
                }
4207
 
            }
4208
 
 
4209
 
            XFree (data);
4210
 
        }
4211
 
        else if (priv->hints && (priv->hints->flags & IconPixmapHint))
4212
 
        {
4213
 
            priv->readIconHint ();
4214
 
        }
4215
 
 
4216
 
        /* don't fetch property again */
4217
 
        if (priv->icons.size () == 0)
4218
 
            priv->noIcons = true;
4219
 
    }
4220
 
 
4221
 
    /* no icons available for this window */
4222
 
    if (priv->noIcons)
4223
 
        return NULL;
4224
 
 
4225
 
    icon = NULL;
4226
 
    wh   = width + height;
4227
 
 
4228
 
    for (i = 0; i < priv->icons.size (); i++)
4229
 
    {
4230
 
        const CompSize iconSize = *priv->icons[i];
4231
 
 
4232
 
        if ((int) iconSize.width () > width ||
4233
 
            (int) iconSize.height () > height)
4234
 
            continue;
4235
 
 
4236
 
        if (icon)
4237
 
        {
4238
 
            diff    = wh - (iconSize.width () + iconSize.height ());
4239
 
            oldDiff = wh - (icon->width () + icon->height ());
4240
 
 
4241
 
            if (diff < oldDiff)
4242
 
                icon = priv->icons[i];
4243
 
        }
4244
 
        else
4245
 
            icon = priv->icons[i];
4246
 
    }
4247
 
 
4248
 
    return icon;
4249
 
}
4250
 
 
4251
 
const CompRect&
4252
 
CompWindow::iconGeometry () const
4253
 
{
4254
 
    return priv->iconGeometry;
4255
 
}
4256
 
 
4257
 
void
4258
 
PrivateWindow::freeIcons ()
4259
 
{
4260
 
    for (unsigned int i = 0; i < priv->icons.size (); i++)
4261
 
        delete priv->icons[i];
4262
 
 
4263
 
    priv->icons.resize (0);
4264
 
    priv->noIcons = false;
4265
 
}
4266
 
 
4267
 
int
4268
 
CompWindow::outputDevice ()
4269
 
{
4270
 
    return screen->outputDeviceForGeometry (priv->serverGeometry);
4271
 
}
4272
 
 
4273
 
bool
4274
 
CompWindow::onCurrentDesktop ()
4275
 
{
4276
 
    if (priv->desktop == 0xffffffff ||
4277
 
        priv->desktop == screen->currentDesktop ())
4278
 
    {
4279
 
        return true;
4280
 
    }
4281
 
 
4282
 
    return false;
4283
 
}
4284
 
 
4285
 
void
4286
 
CompWindow::setDesktop (unsigned int desktop)
4287
 
{
4288
 
    if (desktop != 0xffffffff)
4289
 
    {
4290
 
        if (priv->type & (CompWindowTypeDesktopMask | CompWindowTypeDockMask))
4291
 
            return;
4292
 
 
4293
 
        if (desktop >= screen->nDesktop ())
4294
 
            return;
4295
 
    }
4296
 
 
4297
 
    if (desktop == priv->desktop)
4298
 
        return;
4299
 
 
4300
 
    priv->desktop = desktop;
4301
 
 
4302
 
    if (desktop == 0xffffffff || desktop == screen->currentDesktop ())
4303
 
        priv->show ();
4304
 
    else
4305
 
        priv->hide ();
4306
 
 
4307
 
    screen->setWindowProp (priv->id, Atoms::winDesktop, priv->desktop);
4308
 
}
4309
 
 
4310
 
/* The compareWindowActiveness function compares the two windows 'w1'
4311
 
   and 'w2'. It returns an integer less than, equal to, or greater
4312
 
   than zero if 'w1' is found, respectively, to activated longer time
4313
 
   ago than, to be activated at the same time, or be activated more
4314
 
   recently than 'w2'. */
4315
 
int
4316
 
PrivateWindow::compareWindowActiveness (CompWindow *w1,
4317
 
                                        CompWindow *w2)
4318
 
{
4319
 
    CompActiveWindowHistory *history = screen->currentHistory ();
4320
 
    int                     i;
4321
 
 
4322
 
    /* check current window history first */
4323
 
    for (i = 0; i < ACTIVE_WINDOW_HISTORY_SIZE; i++)
4324
 
    {
4325
 
        if (history->id[i] == w1->priv->id)
4326
 
            return 1;
4327
 
 
4328
 
        if (history->id[i] == w2->priv->id)
4329
 
            return -1;
4330
 
 
4331
 
        if (!history->id[i])
4332
 
            break;
4333
 
    }
4334
 
 
4335
 
    return w1->priv->activeNum - w2->priv->activeNum;
4336
 
}
4337
 
 
4338
 
bool
4339
 
CompWindow::onAllViewports ()
4340
 
{
4341
 
    if (overrideRedirect ())
4342
 
        return true;
4343
 
 
4344
 
    if (!priv->managed && !isViewable ())
4345
 
        return true;
4346
 
 
4347
 
    if (priv->type & (CompWindowTypeDesktopMask | CompWindowTypeDockMask))
4348
 
        return true;
4349
 
 
4350
 
    if (priv->state & CompWindowStateStickyMask)
4351
 
        return true;
4352
 
 
4353
 
    return false;
4354
 
}
4355
 
 
4356
 
CompPoint
4357
 
CompWindow::getMovementForOffset (CompPoint offset)
4358
 
{
4359
 
    CompScreen *s = screen;
4360
 
    int         m, vWidth, vHeight;
4361
 
    int         offX = offset.x (), offY = offset.y ();
4362
 
    CompPoint   rv;
4363
 
 
4364
 
    vWidth = s->width () * s->vpSize ().width ();
4365
 
    vHeight = s->height () * s->vpSize ().height ();
4366
 
 
4367
 
    offX %= vWidth;
4368
 
    offY %= vHeight;
4369
 
 
4370
 
    /* x */
4371
 
    if (s->vpSize ().width () == 1)
4372
 
    {
4373
 
        rv.setX (offX);
4374
 
    }
4375
 
    else
4376
 
    {
4377
 
        m = priv->attrib.x + offX;
4378
 
        if (m - priv->input.left < (int) s->width () - vWidth)
4379
 
            rv.setX (offX + vWidth);
4380
 
        else if (m + priv->width + priv->input.right > vWidth)
4381
 
            rv.setX (offX - vWidth);
4382
 
        else
4383
 
            rv.setX (offX);
4384
 
    }
4385
 
 
4386
 
    if (s->vpSize ().height () == 1)
4387
 
    {
4388
 
        rv.setY (offY);
4389
 
    }
4390
 
    else
4391
 
    {
4392
 
        m = priv->attrib.y + offY;
4393
 
        if (m - priv->input.top < (int) s->height () - vHeight)
4394
 
            rv.setY (offY + vHeight);
4395
 
        else if (m + priv->height + priv->input.bottom > vHeight)
4396
 
            rv.setY (offY - vHeight);
4397
 
        else
4398
 
            rv.setY (offY);
4399
 
    }
4400
 
 
4401
 
    return rv;
4402
 
}
4403
 
 
4404
 
void
4405
 
WindowInterface::getOutputExtents (CompWindowExtents& output)
4406
 
    WRAPABLE_DEF (getOutputExtents, output)
4407
 
 
4408
 
void
4409
 
WindowInterface::getAllowedActions (unsigned int &setActions,
4410
 
                                    unsigned int &clearActions)
4411
 
    WRAPABLE_DEF (getAllowedActions, setActions, clearActions)
4412
 
 
4413
 
bool
4414
 
WindowInterface::focus ()
4415
 
    WRAPABLE_DEF (focus)
4416
 
 
4417
 
void
4418
 
WindowInterface::activate ()
4419
 
    WRAPABLE_DEF (activate)
4420
 
 
4421
 
bool
4422
 
WindowInterface::place (CompPoint &pos)
4423
 
    WRAPABLE_DEF (place, pos)
4424
 
 
4425
 
void
4426
 
WindowInterface::validateResizeRequest (unsigned int   &mask,
4427
 
                                        XWindowChanges *xwc,
4428
 
                                        unsigned int   source)
4429
 
    WRAPABLE_DEF (validateResizeRequest, mask, xwc, source)
4430
 
 
4431
 
void
4432
 
WindowInterface::resizeNotify (int dx,
4433
 
                               int dy,
4434
 
                               int dwidth,
4435
 
                               int dheight)
4436
 
    WRAPABLE_DEF (resizeNotify, dx, dy, dwidth, dheight)
4437
 
 
4438
 
void
4439
 
WindowInterface::moveNotify (int  dx,
4440
 
                             int  dy,
4441
 
                             bool immediate)
4442
 
    WRAPABLE_DEF (moveNotify, dx, dy, immediate)
4443
 
 
4444
 
void
4445
 
WindowInterface::windowNotify (CompWindowNotify n)
4446
 
    WRAPABLE_DEF (windowNotify, n)
4447
 
 
4448
 
void
4449
 
WindowInterface::grabNotify (int          x,
4450
 
                             int          y,
4451
 
                             unsigned int state,
4452
 
                             unsigned int mask)
4453
 
    WRAPABLE_DEF (grabNotify, x, y, state, mask)
4454
 
 
4455
 
void
4456
 
WindowInterface::ungrabNotify ()
4457
 
    WRAPABLE_DEF (ungrabNotify)
4458
 
 
4459
 
void
4460
 
WindowInterface::stateChangeNotify (unsigned int lastState)
4461
 
    WRAPABLE_DEF (stateChangeNotify, lastState)
4462
 
 
4463
 
void
4464
 
WindowInterface::updateFrameRegion (CompRegion &region)
4465
 
    WRAPABLE_DEF (updateFrameRegion, region)
4466
 
 
4467
 
void
4468
 
WindowInterface::minimize ()
4469
 
    WRAPABLE_DEF (minimize);
4470
 
 
4471
 
void
4472
 
WindowInterface::unminimize ()
4473
 
    WRAPABLE_DEF (unminimize);
4474
 
 
4475
 
bool
4476
 
WindowInterface::minimized ()
4477
 
    WRAPABLE_DEF (minimized);
4478
 
 
4479
 
bool
4480
 
WindowInterface::alpha ()
4481
 
    WRAPABLE_DEF (alpha);
4482
 
 
4483
 
bool
4484
 
WindowInterface::isFocussable ()
4485
 
    WRAPABLE_DEF (isFocussable);
4486
 
 
4487
 
bool
4488
 
WindowInterface::managed ()
4489
 
    WRAPABLE_DEF (managed);
4490
 
 
4491
 
Window
4492
 
CompWindow::id ()
4493
 
{
4494
 
    return priv->id;
4495
 
}
4496
 
 
4497
 
unsigned int
4498
 
CompWindow::type ()
4499
 
{
4500
 
    return priv->type;
4501
 
}
4502
 
 
4503
 
unsigned int &
4504
 
CompWindow::state ()
4505
 
{
4506
 
    return priv->state;
4507
 
}
4508
 
 
4509
 
unsigned int
4510
 
CompWindow::actions ()
4511
 
{
4512
 
    return priv->actions;
4513
 
}
4514
 
 
4515
 
unsigned int &
4516
 
CompWindow::protocols ()
4517
 
{
4518
 
    return priv->protocols;
4519
 
}
4520
 
 
4521
 
void
4522
 
CompWindow::close (Time serverTime)
4523
 
{
4524
 
    if (serverTime == 0)
4525
 
        serverTime = screen->getCurrentTime ();
4526
 
 
4527
 
    if (priv->alive)
4528
 
    {
4529
 
        if (priv->protocols & CompWindowProtocolDeleteMask)
4530
 
        {
4531
 
            XEvent ev;
4532
 
 
4533
 
            ev.type                 = ClientMessage;
4534
 
            ev.xclient.window       = priv->id;
4535
 
            ev.xclient.message_type = Atoms::wmProtocols;
4536
 
            ev.xclient.format       = 32;
4537
 
            ev.xclient.data.l[0]    = Atoms::wmDeleteWindow;
4538
 
            ev.xclient.data.l[1]    = serverTime;
4539
 
            ev.xclient.data.l[2]    = 0;
4540
 
            ev.xclient.data.l[3]    = 0;
4541
 
            ev.xclient.data.l[4]    = 0;
4542
 
 
4543
 
            XSendEvent (screen->dpy (), priv->id, false, NoEventMask, &ev);
4544
 
        }
4545
 
        else
4546
 
        {
4547
 
            XKillClient (screen->dpy (), priv->id);
4548
 
        }
4549
 
 
4550
 
        priv->closeRequests++;
4551
 
    }
4552
 
    else
4553
 
    {
4554
 
        screen->toolkitAction (Atoms::toolkitActionForceQuitDialog,
4555
 
                                     serverTime, priv->id, true, 0, 0);
4556
 
    }
4557
 
 
4558
 
    priv->lastCloseRequestTime = serverTime;
4559
 
}
4560
 
 
4561
 
bool
4562
 
PrivateWindow::handlePingTimeout (unsigned int lastPing)
4563
 
{
4564
 
    if (!window->isViewable ())
4565
 
        return false;
4566
 
 
4567
 
    if (!(priv->type & CompWindowTypeNormalMask))
4568
 
        return false;
4569
 
 
4570
 
    if (priv->protocols & CompWindowProtocolPingMask)
4571
 
    {
4572
 
        if (priv->transientFor)
4573
 
            return false;
4574
 
 
4575
 
        if (priv->lastPong < lastPing)
4576
 
        {
4577
 
            if (priv->alive)
4578
 
            {
4579
 
                priv->alive = false;
4580
 
 
4581
 
                window->windowNotify (CompWindowNotifyAliveChanged);
4582
 
 
4583
 
                if (priv->closeRequests)
4584
 
                {
4585
 
                    screen->toolkitAction (Atoms::toolkitActionForceQuitDialog,
4586
 
                                           priv->lastCloseRequestTime,
4587
 
                                           priv->id, true, 0, 0);
4588
 
 
4589
 
                    priv->closeRequests = 0;
4590
 
                }
4591
 
            }
4592
 
        }
4593
 
 
4594
 
        return true;
4595
 
    }
4596
 
    return false;
4597
 
}
4598
 
 
4599
 
void
4600
 
PrivateWindow::handlePing (int lastPing)
4601
 
{
4602
 
    if (!priv->alive)
4603
 
    {
4604
 
        priv->alive = true;
4605
 
 
4606
 
        window->windowNotify (CompWindowNotifyAliveChanged);
4607
 
 
4608
 
        if (priv->lastCloseRequestTime)
4609
 
        {
4610
 
            screen->toolkitAction (Atoms::toolkitActionForceQuitDialog,
4611
 
                                   priv->lastCloseRequestTime,
4612
 
                                   priv->id, false, 0, 0);
4613
 
 
4614
 
            priv->lastCloseRequestTime = 0;
4615
 
        }
4616
 
    }
4617
 
    priv->lastPong = lastPing;
4618
 
}
4619
 
 
4620
 
void
4621
 
PrivateWindow::processMap ()
4622
 
{
4623
 
    bool                   allowFocus;
4624
 
    CompStackingUpdateMode stackingMode;
4625
 
 
4626
 
    priv->initialViewport = screen->vp ();
4627
 
 
4628
 
    priv->initialTimestampSet = false;
4629
 
 
4630
 
    screen->priv->applyStartupProperties (window);
4631
 
 
4632
 
    if (!frame)
4633
 
        reparent ();
4634
 
    priv->managed = true;
4635
 
 
4636
 
    if (!priv->placed)
4637
 
    {
4638
 
        int            gravity = priv->sizeHints.win_gravity;
4639
 
        XWindowChanges xwc;
4640
 
        unsigned int   xwcm;
4641
 
 
4642
 
        /* adjust for gravity, but only for frame size */
4643
 
        xwc.x      = priv->serverGeometry.x ();
4644
 
        xwc.y      = priv->serverGeometry.y ();
4645
 
        xwc.width  = 0;
4646
 
        xwc.height = 0;
4647
 
 
4648
 
        xwcm = adjustConfigureRequestForGravity (&xwc, CWX | CWY, gravity, 1);
4649
 
 
4650
 
        window->validateResizeRequest (xwcm, &xwc, ClientTypeApplication);
4651
 
 
4652
 
        CompPoint pos (xwc.x, xwc.y);
4653
 
        if (window->place (pos))
4654
 
        {
4655
 
            xwc.x = pos.x ();
4656
 
            xwc.y = pos.y ();
4657
 
            xwcm |= CWX | CWY;
4658
 
        }
4659
 
 
4660
 
        if (xwcm)
4661
 
            window->configureXWindow (xwcm, &xwc);
4662
 
 
4663
 
        priv->placed = true;
4664
 
    }
4665
 
 
4666
 
    allowFocus = allowWindowFocus (NO_FOCUS_MASK, 0);
4667
 
 
4668
 
    if (!allowFocus && (priv->type & ~NO_FOCUS_MASK))
4669
 
        stackingMode = CompStackingUpdateModeInitialMapDeniedFocus;
4670
 
    else
4671
 
        stackingMode = CompStackingUpdateModeInitialMap;
4672
 
 
4673
 
    window->updateAttributes (stackingMode);
4674
 
 
4675
 
    if (window->minimized ())
4676
 
        window->unminimize ();
4677
 
 
4678
 
    screen->leaveShowDesktopMode (window);
4679
 
 
4680
 
    if (allowFocus && !window->onCurrentDesktop ())
4681
 
        screen->priv->setCurrentDesktop (priv->desktop);
4682
 
 
4683
 
    if (!(priv->state & CompWindowStateHiddenMask))
4684
 
        show ();
4685
 
 
4686
 
    if (allowFocus)
4687
 
        window->moveInputFocusTo ();
4688
 
}
4689
 
 
4690
 
/*
4691
 
 * PrivateWindow::updatePassiveButtonGrabs
4692
 
 *
4693
 
 * Updates the passive button grabs for a window. When
4694
 
 * one of the specified button + modifier combinations
4695
 
 * for this window is activated, compiz will be given
4696
 
 * an active grab for the window (which we can turn off
4697
 
 * by calling XAllowEvents later in ::handleEvent)
4698
 
 *
4699
 
 * NOTE: ICCCM says that we are only allowed to grab
4700
 
 * windows that we actually own as a client, so only
4701
 
 * grab the frame window. Additionally, although there
4702
 
 * isn't anything in the ICCCM that says we cannot
4703
 
 * grab every button, some clients do not interpret
4704
 
 * EnterNotify and LeaveNotify events caused by the
4705
 
 * activation of the grab correctly, so ungrab button
4706
 
 * and modifier combinations that we do not need on
4707
 
 * active windows (but in reality we shouldn't be grabbing
4708
 
 * for buttons that we don't actually need at that point
4709
 
 * anyways)
4710
 
 */
4711
 
 
4712
 
void
4713
 
PrivateWindow::updatePassiveButtonGrabs ()
4714
 
{
4715
 
    bool onlyActions = (priv->id == screen->priv->activeWindow ||
4716
 
                        !screen->priv->optionGetClickToFocus ());
4717
 
 
4718
 
    if (!priv->frame)
4719
 
        return;
4720
 
 
4721
 
    /* Ungrab everything */
4722
 
    XUngrabButton (screen->priv->dpy, AnyButton, AnyModifier, frame);
4723
 
 
4724
 
    /* We don't need the full grab in the following cases:
4725
 
     * - This window has the focus and either
4726
 
     *   - it is raised or
4727
 
     *   - we don't want click raise
4728
 
     */
4729
 
 
4730
 
    if (onlyActions)
4731
 
    {
4732
 
        if (screen->priv->optionGetRaiseOnClick ())
4733
 
        {
4734
 
            for (CompWindow *above = window->next;
4735
 
                above != NULL; above = above->next)
4736
 
            {
4737
 
                if (above->priv->attrib.map_state != IsViewable)
4738
 
                    continue;
4739
 
 
4740
 
                if (above->type () & CompWindowTypeDockMask)
4741
 
                    continue;
4742
 
 
4743
 
                if (above->region ().intersects (region))
4744
 
                {
4745
 
                    onlyActions = false;
4746
 
                    break;
4747
 
                }
4748
 
            }
4749
 
        }
4750
 
    }
4751
 
 
4752
 
    if (onlyActions)
4753
 
    {
4754
 
        /* Grab only we have bindings on */
4755
 
        foreach (PrivateScreen::ButtonGrab &bind, screen->priv->buttonGrabs)
4756
 
        {
4757
 
            for (unsigned int ignore = 0;
4758
 
                     ignore <= modHandler->ignoredModMask (); ignore++)
4759
 
            {
4760
 
                if (ignore & ~modHandler->ignoredModMask ())
4761
 
                {
4762
 
                    XGrabButton (screen->priv->dpy,
4763
 
                                bind.button,
4764
 
                                bind.modifiers | ignore,
4765
 
                                frame,
4766
 
                                false,
4767
 
                                ButtonPressMask | ButtonReleaseMask |
4768
 
                                    ButtonMotionMask,
4769
 
                                GrabModeSync,
4770
 
                                GrabModeAsync,
4771
 
                                None,
4772
 
                                None);
4773
 
                }
4774
 
            }
4775
 
        }
4776
 
    }
4777
 
    else
4778
 
    {
4779
 
        /* Grab everything */
4780
 
        XGrabButton (screen->priv->dpy,
4781
 
                     AnyButton,
4782
 
                     AnyModifier,
4783
 
                     frame, false,
4784
 
                     ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
4785
 
                     GrabModeSync,
4786
 
                     GrabModeAsync,
4787
 
                     None,
4788
 
                     None);
4789
 
    }
4790
 
}
4791
 
 
4792
 
 
4793
 
const CompRegion &
4794
 
CompWindow::region () const
4795
 
{
4796
 
    return priv->region;
4797
 
}
4798
 
 
4799
 
const CompRegion &
4800
 
CompWindow::frameRegion () const
4801
 
{
4802
 
    return priv->frameRegion;
4803
 
}
4804
 
 
4805
 
bool
4806
 
CompWindow::inShowDesktopMode ()
4807
 
{
4808
 
    return priv->inShowDesktopMode;
4809
 
}
4810
 
 
4811
 
void
4812
 
CompWindow::setShowDesktopMode (bool value)
4813
 
{
4814
 
    priv->inShowDesktopMode = value;
4815
 
}
4816
 
 
4817
 
bool
4818
 
CompWindow::managed ()
4819
 
{
4820
 
    WRAPABLE_HND_FUNC_RETURN (18, bool, managed);
4821
 
    return priv->managed;
4822
 
}
4823
 
 
4824
 
bool
4825
 
CompWindow::grabbed ()
4826
 
{
4827
 
    return priv->grabbed;
4828
 
}
4829
 
 
4830
 
int
4831
 
CompWindow::pendingMaps ()
4832
 
{
4833
 
    return priv->pendingMaps;
4834
 
}
4835
 
 
4836
 
unsigned int &
4837
 
CompWindow::wmType ()
4838
 
{
4839
 
    return priv->wmType;
4840
 
}
4841
 
 
4842
 
unsigned int
4843
 
CompWindow::activeNum ()
4844
 
{
4845
 
    return priv->activeNum;
4846
 
}
4847
 
 
4848
 
Window
4849
 
CompWindow::frame ()
4850
 
{
4851
 
    return priv->frame;
4852
 
}
4853
 
 
4854
 
CompString
4855
 
CompWindow::resName ()
4856
 
{
4857
 
    if (priv->resName)
4858
 
        return priv->resName;
4859
 
 
4860
 
    return CompString ();
4861
 
}
4862
 
 
4863
 
int
4864
 
CompWindow::mapNum () const
4865
 
{
4866
 
    return priv->mapNum;
4867
 
}
4868
 
 
4869
 
CompStruts *
4870
 
CompWindow::struts ()
4871
 
{
4872
 
    return priv->struts;
4873
 
}
4874
 
 
4875
 
int &
4876
 
CompWindow::saveMask ()
4877
 
{
4878
 
    return priv->saveMask;
4879
 
}
4880
 
 
4881
 
XWindowChanges &
4882
 
CompWindow::saveWc ()
4883
 
{
4884
 
    return priv->saveWc;
4885
 
}
4886
 
 
4887
 
void
4888
 
CompWindow::moveToViewportPosition (int  x,
4889
 
                                    int  y,
4890
 
                                    bool sync)
4891
 
{
4892
 
    int tx, ty;
4893
 
    int vWidth  = screen->width () * screen->vpSize ().width ();
4894
 
    int vHeight = screen->height () * screen->vpSize ().height ();
4895
 
 
4896
 
    if (screen->vpSize ().width () != 1)
4897
 
    {
4898
 
        x += screen->vp ().x () * screen->width ();
4899
 
        x = MOD (x, vWidth);
4900
 
        x -= screen->vp ().x () * screen->width ();
4901
 
    }
4902
 
 
4903
 
    if (screen->vpSize ().height () != 1)
4904
 
    {
4905
 
        y += screen->vp ().y () * screen->height ();
4906
 
        y = MOD (y, vHeight);
4907
 
        y -= screen->vp ().y () * screen->height ();
4908
 
    }
4909
 
 
4910
 
    tx = x - priv->attrib.x;
4911
 
    ty = y - priv->attrib.y;
4912
 
 
4913
 
    if (tx || ty)
4914
 
    {
4915
 
        int m, wx, wy;
4916
 
 
4917
 
        if (!priv->managed)
4918
 
            return;
4919
 
 
4920
 
        if (priv->type & (CompWindowTypeDesktopMask | CompWindowTypeDockMask))
4921
 
            return;
4922
 
 
4923
 
        if (priv->state & CompWindowStateStickyMask)
4924
 
            return;
4925
 
 
4926
 
        wx = tx;
4927
 
        wy = ty;
4928
 
 
4929
 
        if (screen->vpSize ().width ()!= 1)
4930
 
        {
4931
 
            m = priv->attrib.x + tx;
4932
 
 
4933
 
            if (m - priv->output.left < (int) screen->width () - vWidth)
4934
 
                wx = tx + vWidth;
4935
 
            else if (m + priv->width + priv->output.right > vWidth)
4936
 
                wx = tx - vWidth;
4937
 
        }
4938
 
 
4939
 
        if (screen->vpSize ().height () != 1)
4940
 
        {
4941
 
            m = priv->attrib.y + ty;
4942
 
 
4943
 
            if (m - priv->output.top < (int) screen->height () - vHeight)
4944
 
                wy = ty + vHeight;
4945
 
            else if (m + priv->height + priv->output.bottom > vHeight)
4946
 
                wy = ty - vHeight;
4947
 
        }
4948
 
 
4949
 
        if (priv->saveMask & CWX)
4950
 
            priv->saveWc.x += wx;
4951
 
 
4952
 
        if (priv->saveMask & CWY)
4953
 
            priv->saveWc.y += wy;
4954
 
 
4955
 
        move (wx, wy);
4956
 
 
4957
 
        if (sync)
4958
 
            syncPosition ();
4959
 
    }
4960
 
}
4961
 
 
4962
 
char *
4963
 
CompWindow::startupId ()
4964
 
{
4965
 
     return priv->startupId;
4966
 
}
4967
 
 
4968
 
void
4969
 
PrivateWindow::applyStartupProperties (CompStartupSequence *s)
4970
 
{
4971
 
    int workspace;
4972
 
 
4973
 
    priv->initialViewport.setX (s->viewportX);
4974
 
    priv->initialViewport.setY (s->viewportY);
4975
 
 
4976
 
    workspace = sn_startup_sequence_get_workspace (s->sequence);
4977
 
    if (workspace >= 0)
4978
 
        window->setDesktop (workspace);
4979
 
 
4980
 
    priv->initialTimestamp    =
4981
 
        sn_startup_sequence_get_timestamp (s->sequence);
4982
 
    priv->initialTimestampSet = true;
4983
 
}
4984
 
 
4985
 
unsigned int
4986
 
CompWindow::desktop ()
4987
 
{
4988
 
    return priv->desktop;
4989
 
}
4990
 
 
4991
 
Window
4992
 
CompWindow::clientLeader (bool checkAncestor)
4993
 
{
4994
 
    if (priv->clientLeader)
4995
 
        return priv->clientLeader;
4996
 
 
4997
 
    if (checkAncestor)
4998
 
        return priv->getClientLeaderOfAncestor ();
4999
 
 
5000
 
    return None;
5001
 
}
5002
 
 
5003
 
Window
5004
 
CompWindow::transientFor ()
5005
 
{
5006
 
    return priv->transientFor;
5007
 
}
5008
 
 
5009
 
int
5010
 
CompWindow::pendingUnmaps ()
5011
 
{
5012
 
    return priv->pendingUnmaps;
5013
 
}
5014
 
 
5015
 
bool
5016
 
CompWindow::minimized ()
5017
 
{
5018
 
    WRAPABLE_HND_FUNC_RETURN (15, bool, minimized);
5019
 
    return priv->minimized;
5020
 
}
5021
 
 
5022
 
bool
5023
 
CompWindow::placed ()
5024
 
{
5025
 
    return priv->placed;
5026
 
}
5027
 
 
5028
 
bool
5029
 
CompWindow::shaded ()
5030
 
{
5031
 
    return priv->shaded;
5032
 
}
5033
 
 
5034
 
CompWindowExtents &
5035
 
CompWindow::input () const
5036
 
{
5037
 
    return priv->input;
5038
 
}
5039
 
 
5040
 
CompWindowExtents &
5041
 
CompWindow::output () const
5042
 
{
5043
 
    return priv->output;
5044
 
}
5045
 
 
5046
 
XSizeHints &
5047
 
CompWindow::sizeHints () const
5048
 
{
5049
 
    return priv->sizeHints;
5050
 
}
5051
 
 
5052
 
void
5053
 
PrivateWindow::updateMwmHints ()
5054
 
{
5055
 
    screen->priv->getMwmHints (priv->id, &priv->mwmFunc, &priv->mwmDecor);
5056
 
    window->recalcActions ();
5057
 
}
5058
 
 
5059
 
void
5060
 
PrivateWindow::updateStartupId ()
5061
 
{
5062
 
    char *oldId = startupId;
5063
 
    bool newId = true;
5064
 
 
5065
 
    startupId = getStartupId ();
5066
 
 
5067
 
    if (oldId)
5068
 
    {
5069
 
        if (strcmp (startupId, oldId) == 0)
5070
 
            newId = false;
5071
 
 
5072
 
        free (oldId);
5073
 
    }
5074
 
 
5075
 
    if (managed && startupId && newId)
5076
 
    {
5077
 
        Time       timestamp = 0;
5078
 
        CompPoint  vp, svp;
5079
 
        CompSize   size;
5080
 
        int        x, y;
5081
 
 
5082
 
        initialTimestampSet = false;
5083
 
        screen->priv->applyStartupProperties (window);
5084
 
 
5085
 
        if (initialTimestampSet)
5086
 
            timestamp = initialTimestamp;
5087
 
 
5088
 
        /* as the viewport can't be transmitted via startup
5089
 
           notification, assume the client changing the ID
5090
 
           wanted to activate the window on the current viewport */
5091
 
 
5092
 
        vp   = window->defaultViewport ();
5093
 
        svp  = screen->vp ();
5094
 
        size = *screen;
5095
 
 
5096
 
        x = window->geometry ().x () + (svp.x () - vp.x ()) * size.width ();
5097
 
        y = window->geometry ().y () + (svp.y () - vp.y ()) * size.height ();
5098
 
        window->moveToViewportPosition (x, y, true);
5099
 
 
5100
 
        if (allowWindowFocus (0, timestamp))
5101
 
            window->activate ();
5102
 
    }
5103
 
}
5104
 
 
5105
 
bool
5106
 
CompWindow::destroyed ()
5107
 
{
5108
 
    return priv->destroyed;
5109
 
}
5110
 
 
5111
 
bool
5112
 
CompWindow::invisible ()
5113
 
{
5114
 
    return priv->invisible;
5115
 
}
5116
 
 
5117
 
XSyncAlarm
5118
 
CompWindow::syncAlarm ()
5119
 
{
5120
 
    return priv->syncAlarm;
5121
 
}
5122
 
 
5123
 
 
5124
 
CompWindow::CompWindow (Window id,
5125
 
                        Window aboveId) :
5126
 
   PluginClassStorage (windowPluginClassIndices)
5127
 
{
5128
 
    priv = new PrivateWindow (this);
5129
 
    assert (priv);
5130
 
 
5131
 
    /* Failure means that window has been destroyed. We still have to add the
5132
 
       window to the window list as we might get configure requests which
5133
 
       require us to stack other windows relative to it. Setting some default
5134
 
       values if this is the case. */
5135
 
    if (!XGetWindowAttributes (screen->dpy (), id, &priv->attrib))
5136
 
        setDefaultWindowAttributes (&priv->attrib);
5137
 
 
5138
 
    priv->serverGeometry.set (priv->attrib.x, priv->attrib.y,
5139
 
                              priv->attrib.width, priv->attrib.height,
5140
 
                              priv->attrib.border_width);
5141
 
    priv->syncGeometry.set (priv->attrib.x, priv->attrib.y,
5142
 
                            priv->attrib.width, priv->attrib.height,
5143
 
                            priv->attrib.border_width);
5144
 
    priv->geometry.set (priv->attrib.x, priv->attrib.y,
5145
 
                        priv->attrib.width, priv->attrib.height,
5146
 
                        priv->attrib.border_width);
5147
 
 
5148
 
    priv->width  = priv->attrib.width  + priv->attrib.border_width * 2;
5149
 
    priv->height = priv->attrib.height + priv->attrib.border_width * 2;
5150
 
 
5151
 
    priv->sizeHints.flags = 0;
5152
 
 
5153
 
    priv->recalcNormalHints ();
5154
 
 
5155
 
    priv->transientFor = None;
5156
 
    priv->clientLeader = None;
5157
 
 
5158
 
    XSelectInput (screen->dpy (), id,
5159
 
                      EnterWindowMask   |
5160
 
                      PropertyChangeMask |
5161
 
                      FocusChangeMask);
5162
 
 
5163
 
    priv->id = id;
5164
 
 
5165
 
    priv->alpha     = (depth () == 32);
5166
 
    priv->lastPong  = screen->priv->lastPing;
5167
 
 
5168
 
    if (screen->XShape ())
5169
 
        XShapeSelectInput (screen->dpy (), id, ShapeNotifyMask);
5170
 
 
5171
 
    screen->insertWindow (this, aboveId);
5172
 
 
5173
 
    if (windowClass () != InputOnly)
5174
 
    {
5175
 
        priv->region = CompRegion (priv->attrib.x, priv->attrib.y,
5176
 
                                   priv->width, priv->height);
5177
 
        priv->inputRegion = priv->region;
5178
 
 
5179
 
        /* need to check for DisplayModal state on all windows */
5180
 
        priv->state = screen->priv->getWindowState (priv->id);
5181
 
 
5182
 
        priv->updateClassHints ();
5183
 
    }
5184
 
    else
5185
 
    {
5186
 
        priv->attrib.map_state = IsUnmapped;
5187
 
    }
5188
 
 
5189
 
    priv->wmType    = screen->priv->getWindowType (priv->id);
5190
 
    priv->protocols = screen->priv->getProtocols (priv->id);
5191
 
 
5192
 
    if (!overrideRedirect ())
5193
 
    {
5194
 
        priv->updateNormalHints ();
5195
 
        updateStruts ();
5196
 
        priv->updateWmHints ();
5197
 
        priv->updateTransientHint ();
5198
 
 
5199
 
        priv->clientLeader = priv->getClientLeader ();
5200
 
        priv->startupId = priv->getStartupId ();
5201
 
 
5202
 
        recalcType ();
5203
 
 
5204
 
        screen->priv->getMwmHints (priv->id, &priv->mwmFunc, &priv->mwmDecor);
5205
 
 
5206
 
        if (!(priv->type & (CompWindowTypeDesktopMask | CompWindowTypeDockMask)))
5207
 
        {
5208
 
            priv->desktop = screen->getWindowProp (priv->id, Atoms::winDesktop,
5209
 
                                                   priv->desktop);
5210
 
            if (priv->desktop != 0xffffffff)
5211
 
            {
5212
 
                if (priv->desktop >= screen->nDesktop ())
5213
 
                    priv->desktop = screen->currentDesktop ();
5214
 
            }
5215
 
        }
5216
 
    }
5217
 
    else
5218
 
    {
5219
 
        recalcType ();
5220
 
    }
5221
 
 
5222
 
    if (priv->attrib.map_state == IsViewable)
5223
 
    {
5224
 
        priv->placed = true;
5225
 
 
5226
 
        if (!overrideRedirect ())
5227
 
        {
5228
 
            if (!priv->frame)
5229
 
                priv->reparent ();
5230
 
            priv->managed = true;
5231
 
 
5232
 
            if (screen->priv->getWmState (priv->id) == IconicState)
5233
 
            {
5234
 
                if (priv->state & CompWindowStateShadedMask)
5235
 
                    priv->shaded = true;
5236
 
                else
5237
 
                    priv->minimized = true;
5238
 
            }
5239
 
            else
5240
 
            {
5241
 
                if (priv->wmType & (CompWindowTypeDockMask |
5242
 
                                 CompWindowTypeDesktopMask))
5243
 
                {
5244
 
                    setDesktop (0xffffffff);
5245
 
                }
5246
 
                else
5247
 
                {
5248
 
                    if (priv->desktop != 0xffffffff)
5249
 
                        priv->desktop = screen->currentDesktop ();
5250
 
 
5251
 
                    screen->setWindowProp (priv->id, Atoms::winDesktop,
5252
 
                                           priv->desktop);
5253
 
                }
5254
 
            }
5255
 
        }
5256
 
 
5257
 
        priv->attrib.map_state = IsUnmapped;
5258
 
        priv->pendingMaps++;
5259
 
 
5260
 
        map ();
5261
 
 
5262
 
        updateAttributes (CompStackingUpdateModeNormal);
5263
 
 
5264
 
        if (priv->minimized || priv->inShowDesktopMode ||
5265
 
            priv->hidden || priv->shaded)
5266
 
        {
5267
 
            priv->state |= CompWindowStateHiddenMask;
5268
 
 
5269
 
            priv->pendingUnmaps++;
5270
 
 
5271
 
            if (priv->frame && !priv->shaded)
5272
 
                XUnmapWindow (screen->dpy (), priv->frame);
5273
 
 
5274
 
            XUnmapWindow (screen->dpy (), priv->id);
5275
 
 
5276
 
            screen->priv->setWindowState (priv->state, priv->id);
5277
 
        }
5278
 
    }
5279
 
    else if (!overrideRedirect ())
5280
 
    {
5281
 
        if (screen->priv->getWmState (priv->id) == IconicState)
5282
 
        {
5283
 
            if (!priv->frame)
5284
 
                priv->reparent ();
5285
 
            priv->managed = true;
5286
 
            priv->placed  = true;
5287
 
 
5288
 
            if (priv->state & CompWindowStateHiddenMask)
5289
 
            {
5290
 
                if (priv->state & CompWindowStateShadedMask)
5291
 
                    priv->shaded = true;
5292
 
                else
5293
 
                    priv->minimized = true;
5294
 
            }
5295
 
        }
5296
 
    }
5297
 
 
5298
 
    /* TODO: bailout properly when objectInitPlugins fails */
5299
 
    assert (CompPlugin::windowInitPlugins (this));
5300
 
 
5301
 
    recalcActions ();
5302
 
    priv->updateIconGeometry ();
5303
 
 
5304
 
    if (priv->shaded)
5305
 
        resize (priv->attrib.x, priv->attrib.y,
5306
 
                priv->attrib.width, ++priv->attrib.height - 1,
5307
 
                priv->attrib.border_width);
5308
 
 
5309
 
    if (priv->attrib.map_state == IsViewable)
5310
 
    {
5311
 
        priv->invisible = WINDOW_INVISIBLE (priv);
5312
 
    }
5313
 
}
5314
 
 
5315
 
CompWindow::~CompWindow ()
5316
 
{
5317
 
    screen->unhookWindow (this);
5318
 
 
5319
 
    if (!priv->destroyed)
5320
 
    {
5321
 
        if (priv->frame)
5322
 
        {
5323
 
            priv->unreparent ();
5324
 
        }
5325
 
 
5326
 
        /* restore saved geometry and map if hidden */
5327
 
        if (!priv->attrib.override_redirect)
5328
 
        {
5329
 
            if (priv->saveMask)
5330
 
                XConfigureWindow (screen->dpy (), priv->id,
5331
 
                                  priv->saveMask, &priv->saveWc);
5332
 
 
5333
 
            if (!priv->hidden)
5334
 
            {
5335
 
                if (priv->state & CompWindowStateHiddenMask)
5336
 
                    XMapWindow (screen->dpy (), priv->id);
5337
 
            }
5338
 
        }
5339
 
 
5340
 
        if (screen->XShape ())
5341
 
            XShapeSelectInput (screen->dpy (), priv->id, NoEventMask);
5342
 
 
5343
 
        if (priv->id != screen->priv->grabWindow)
5344
 
            XSelectInput (screen->dpy (), priv->id, NoEventMask);
5345
 
 
5346
 
        XUngrabButton (screen->dpy (), AnyButton, AnyModifier, priv->id);
5347
 
    }
5348
 
 
5349
 
    if (priv->attrib.map_state == IsViewable)
5350
 
    {
5351
 
        if (priv->type == CompWindowTypeDesktopMask)
5352
 
            screen->priv->desktopWindowCount--;
5353
 
 
5354
 
        if (priv->destroyed && priv->struts)
5355
 
            screen->updateWorkarea ();
5356
 
    }
5357
 
 
5358
 
    if (priv->destroyed)
5359
 
        screen->priv->updateClientList ();
5360
 
 
5361
 
    CompPlugin::windowFiniPlugins (this);
5362
 
 
5363
 
    delete priv;
5364
 
}
5365
 
 
5366
 
PrivateWindow::PrivateWindow (CompWindow *window) :
5367
 
    priv (this),
5368
 
    window (window),
5369
 
    refcnt (1),
5370
 
    id (None),
5371
 
    frame (None),
5372
 
    wrapper (None),
5373
 
    mapNum (0),
5374
 
    activeNum (0),
5375
 
    transientFor (None),
5376
 
    clientLeader (None),
5377
 
    hints (NULL),
5378
 
    inputHint (true),
5379
 
    alpha (false),
5380
 
    width (0),
5381
 
    height (0),
5382
 
    region (),
5383
 
    wmType (0),
5384
 
    type (CompWindowTypeUnknownMask),
5385
 
    state (0),
5386
 
    actions (0),
5387
 
    protocols (0),
5388
 
    mwmDecor (MwmDecorAll),
5389
 
    mwmFunc (MwmFuncAll),
5390
 
    invisible (true),
5391
 
    destroyed (false),
5392
 
    managed (false),
5393
 
    unmanaging (false),
5394
 
    destroyRefCnt (1),
5395
 
    unmapRefCnt (1),
5396
 
 
5397
 
    initialViewport (0, 0),
5398
 
 
5399
 
    initialTimestamp (0),
5400
 
    initialTimestampSet (false),
5401
 
 
5402
 
    fullscreenMonitorsSet (false),
5403
 
 
5404
 
    placed (false),
5405
 
    minimized (false),
5406
 
    inShowDesktopMode (false),
5407
 
    shaded (false),
5408
 
    hidden (false),
5409
 
    grabbed (false),
5410
 
 
5411
 
    desktop (0),
5412
 
 
5413
 
    pendingUnmaps (0),
5414
 
    pendingMaps (0),
5415
 
 
5416
 
    startupId (0),
5417
 
    resName (0),
5418
 
    resClass (0),
5419
 
 
5420
 
    group (0),
5421
 
 
5422
 
    lastPong (0),
5423
 
    alive (true),
5424
 
 
5425
 
    struts (0),
5426
 
 
5427
 
    icons (0),
5428
 
    noIcons (false),
5429
 
 
5430
 
    saveMask (0),
5431
 
    syncCounter (0),
5432
 
    syncAlarm (None),
5433
 
    syncWaitTimer (),
5434
 
 
5435
 
    syncWait (false),
5436
 
    closeRequests (false),
5437
 
    lastCloseRequestTime (0)
5438
 
{
5439
 
    input.left   = 0;
5440
 
    input.right  = 0;
5441
 
    input.top    = 0;
5442
 
    input.bottom = 0;
5443
 
 
5444
 
    output.left   = 0;
5445
 
    output.right  = 0;
5446
 
    output.top    = 0;
5447
 
    output.bottom = 0;
5448
 
 
5449
 
    syncWaitTimer.setTimes (1000, 1200);
5450
 
    syncWaitTimer.setCallback (boost::bind (&PrivateWindow::handleSyncAlarm,
5451
 
                                            this));
5452
 
}
5453
 
 
5454
 
PrivateWindow::~PrivateWindow ()
5455
 
{
5456
 
     if (syncAlarm)
5457
 
        XSyncDestroyAlarm (screen->dpy (), syncAlarm);
5458
 
 
5459
 
    syncWaitTimer.stop ();
5460
 
 
5461
 
    if (frame)
5462
 
        XDestroyWindow (screen->dpy (), frame);
5463
 
 
5464
 
    if (struts)
5465
 
        free (struts);
5466
 
 
5467
 
    if (hints)
5468
 
        XFree (hints);
5469
 
 
5470
 
    if (icons.size ())
5471
 
        freeIcons ();
5472
 
 
5473
 
    if (startupId)
5474
 
        free (startupId);
5475
 
 
5476
 
    if (resName)
5477
 
        free (resName);
5478
 
 
5479
 
    if (resClass)
5480
 
        free (resClass);
5481
 
}
5482
 
 
5483
 
bool
5484
 
CompWindow::syncWait ()
5485
 
{
5486
 
    return priv->syncWait;
5487
 
}
5488
 
 
5489
 
bool
5490
 
CompWindow::alpha ()
5491
 
{
5492
 
    WRAPABLE_HND_FUNC_RETURN (16, bool, alpha);
5493
 
 
5494
 
    return priv->alpha;
5495
 
}
5496
 
 
5497
 
bool
5498
 
CompWindow::overrideRedirect ()
5499
 
{
5500
 
    return priv->attrib.override_redirect;
5501
 
}
5502
 
 
5503
 
void
5504
 
PrivateWindow::setOverrideRedirect (bool overrideRedirect)
5505
 
{
5506
 
    if (overrideRedirect == window->overrideRedirect ())
5507
 
        return;
5508
 
 
5509
 
    priv->attrib.override_redirect = overrideRedirect ? 1 : 0;
5510
 
    window->recalcType ();
5511
 
    window->recalcActions ();
5512
 
 
5513
 
    screen->matchPropertyChanged (window);
5514
 
}
5515
 
 
5516
 
bool
5517
 
CompWindow::isMapped () const
5518
 
{
5519
 
    return priv->mapNum > 0;
5520
 
}
5521
 
 
5522
 
bool
5523
 
CompWindow::isViewable () const
5524
 
{
5525
 
    return (priv->attrib.map_state == IsViewable);
5526
 
}
5527
 
 
5528
 
bool
5529
 
CompWindow::isFocussable ()
5530
 
{
5531
 
    WRAPABLE_HND_FUNC_RETURN (17, bool, isFocussable);
5532
 
 
5533
 
    if (priv->inputHint)
5534
 
        return true;
5535
 
 
5536
 
    if (priv->protocols & CompWindowProtocolTakeFocusMask)
5537
 
        return true;
5538
 
 
5539
 
    return false;
5540
 
}
5541
 
 
5542
 
int
5543
 
CompWindow::windowClass ()
5544
 
{
5545
 
    return priv->attrib.c_class;
5546
 
}
5547
 
 
5548
 
unsigned int
5549
 
CompWindow::depth ()
5550
 
{
5551
 
    return priv->attrib.depth;
5552
 
}
5553
 
 
5554
 
bool
5555
 
CompWindow::alive ()
5556
 
{
5557
 
    return priv->alive;
5558
 
}
5559
 
 
5560
 
unsigned int
5561
 
CompWindow::mwmDecor ()
5562
 
{
5563
 
    return priv->mwmDecor;
5564
 
}
5565
 
 
5566
 
unsigned int
5567
 
CompWindow::mwmFunc ()
5568
 
{
5569
 
    return priv->mwmFunc;
5570
 
}
5571
 
 
5572
 
/* TODO: This function should be able to check the XShape event
5573
 
 * kind and only get/set shape rectangles for either ShapeInput
5574
 
 * or ShapeBounding, but not both at the same time
5575
 
 */
5576
 
 
5577
 
void
5578
 
CompWindow::updateFrameRegion ()
5579
 
{
5580
 
    if (priv->frame && priv->serverGeometry.width () == priv->geometry.width () &&
5581
 
         priv->serverGeometry.height () == priv->geometry.height ())
5582
 
    {
5583
 
        CompRect   r;
5584
 
        int        x, y;
5585
 
 
5586
 
        priv->frameRegion = CompRegion ();
5587
 
 
5588
 
        updateFrameRegion (priv->frameRegion);
5589
 
 
5590
 
        if (!shaded ())
5591
 
        {
5592
 
            r = priv->region.boundingRect ();
5593
 
            priv->frameRegion -= r;
5594
 
 
5595
 
            r.setGeometry (r.x1 () - priv->input.left,
5596
 
                        r.y1 () - priv->input.top,
5597
 
                        r.width  () + priv->input.right + priv->input.left,
5598
 
                        r.height () + priv->input.bottom + priv->input.top);
5599
 
 
5600
 
            priv->frameRegion &= CompRegion (r);
5601
 
        }
5602
 
 
5603
 
        x = priv->geometry.x () - priv->input.left;
5604
 
        y = priv->geometry.y () - priv->input.top;
5605
 
 
5606
 
        XShapeCombineRegion (screen->dpy (), priv->frame,
5607
 
                             ShapeBounding, -x, -y,
5608
 
                             priv->frameRegion.united (priv->region).handle (),
5609
 
                             ShapeSet);
5610
 
 
5611
 
        XShapeCombineRegion (screen->dpy (), priv->frame,
5612
 
                             ShapeInput, -x, -y,
5613
 
                             priv->frameRegion.united (priv->inputRegion).handle (),
5614
 
                             ShapeSet);
5615
 
    }
5616
 
}
5617
 
 
5618
 
void
5619
 
CompWindow::setWindowFrameExtents (CompWindowExtents *i)
5620
 
{
5621
 
    if (priv->input.left   != i->left  ||
5622
 
        priv->input.right  != i->right ||
5623
 
        priv->input.top    != i->top   ||
5624
 
        priv->input.bottom != i->bottom)
5625
 
    {
5626
 
        unsigned long data[4];
5627
 
 
5628
 
        priv->input = *i;
5629
 
 
5630
 
        priv->updateFrameWindow ();
5631
 
        priv->updateSize ();
5632
 
        recalcActions ();
5633
 
 
5634
 
        data[0] = i->left;
5635
 
        data[1] = i->right;
5636
 
        data[2] = i->top;
5637
 
        data[3] = i->bottom;
5638
 
 
5639
 
        XChangeProperty (screen->dpy (), priv->id,
5640
 
                         Atoms::frameExtents,
5641
 
                         XA_CARDINAL, 32, PropModeReplace,
5642
 
                         (unsigned char *) data, 4);
5643
 
    }
5644
 
}
5645
 
 
5646
 
bool
5647
 
CompWindow::hasUnmapReference ()
5648
 
{
5649
 
    return (priv && priv->unmapRefCnt > 1);
5650
 
}
5651
 
 
5652
 
void
5653
 
CompWindow::updateFrameRegion (CompRegion& region)
5654
 
    WRAPABLE_HND_FUNC (12, updateFrameRegion, region)
5655
 
 
5656
 
bool
5657
 
PrivateWindow::reparent ()
5658
 
{
5659
 
    XSetWindowAttributes attr;
5660
 
    XWindowAttributes    wa;
5661
 
    XWindowChanges       xwc;
5662
 
    int                  mask;
5663
 
    CompWindow::Geometry sg = serverGeometry;
5664
 
    Display              *dpy = screen->dpy ();
5665
 
    CompWindow           *sibling = window->next ? window->next : window->prev;
5666
 
    bool                 above = window->next ? false : true;
5667
 
    Window               root_ret;
5668
 
    unsigned int         uidummy;
5669
 
    int                  idummy;
5670
 
    Visual               *visual = DefaultVisual (screen->dpy (),
5671
 
                                                  screen->screenNum ());
5672
 
    Colormap             cmap = DefaultColormap (screen->dpy (),
5673
 
                                                 screen->screenNum ());
5674
 
 
5675
 
    if (frame || attrib.override_redirect)
5676
 
        return false;
5677
 
 
5678
 
    XSync (dpy, false);
5679
 
    XGrabServer (dpy);
5680
 
 
5681
 
    if (!XGetGeometry (screen->dpy (), id, &root_ret, &idummy, &idummy, &uidummy, &uidummy, &uidummy, &uidummy) ||
5682
 
        !XGetWindowAttributes (dpy, id, &wa))
5683
 
    {
5684
 
        XUngrabServer (dpy);
5685
 
        XSync (dpy, false);
5686
 
        return false;
5687
 
    }
5688
 
 
5689
 
    XChangeSaveSet (dpy, id, SetModeInsert);
5690
 
    XSelectInput (dpy, id, NoEventMask);
5691
 
    XSelectInput (dpy, screen->root (), NoEventMask);
5692
 
 
5693
 
    xwc.border_width = 0;
5694
 
    XConfigureWindow (dpy, id, CWBorderWidth, &xwc);
5695
 
 
5696
 
    mask = CWBorderPixel | CWColormap | CWBackPixmap;
5697
 
 
5698
 
    if (attrib.depth == 32)
5699
 
    {
5700
 
        cmap = attrib.colormap;
5701
 
        visual = attrib.visual;
5702
 
    }
5703
 
 
5704
 
    attr.background_pixmap = None;
5705
 
    attr.border_pixel      = 0;
5706
 
    attr.colormap          = cmap;
5707
 
 
5708
 
    frame = XCreateWindow (dpy, screen->root (), 0, 0,
5709
 
                           sg.width (), sg.height (), 0, attrib.depth,
5710
 
                           InputOutput, visual, mask, &attr);
5711
 
 
5712
 
    wrapper = XCreateWindow (dpy, frame, 0, 0,
5713
 
                            sg.width (), sg.height (), 0, attrib.depth,
5714
 
                            InputOutput, visual, mask, &attr);
5715
 
 
5716
 
    XMapWindow (dpy, wrapper);
5717
 
    XReparentWindow (dpy, id, wrapper, 0, 0);
5718
 
 
5719
 
    attr.event_mask = PropertyChangeMask | FocusChangeMask |
5720
 
                      EnterWindowMask | LeaveWindowMask;
5721
 
 
5722
 
    /* We don't care about client events on the frame, and listening for them
5723
 
     * will probably end up fighting the client anyways, so disable them */
5724
 
    attr.do_not_propagate_mask = KeyPressMask | KeyReleaseMask |
5725
 
                                 ButtonPressMask | ButtonReleaseMask |
5726
 
                                 EnterWindowMask | LeaveWindowMask |
5727
 
                                 PointerMotionMask | PointerMotionHintMask |
5728
 
                                 Button1MotionMask | Button2MotionMask |
5729
 
                                 Button3MotionMask | Button4MotionMask |
5730
 
                                 Button5MotionMask | ButtonMotionMask |
5731
 
                                 KeymapStateMask | ExposureMask |
5732
 
                                 VisibilityChangeMask | StructureNotifyMask |
5733
 
                                 ResizeRedirectMask | SubstructureNotifyMask |
5734
 
                                 SubstructureRedirectMask | FocusChangeMask |
5735
 
                                 PropertyChangeMask | ColormapChangeMask |
5736
 
                                 OwnerGrabButtonMask;
5737
 
 
5738
 
    XChangeWindowAttributes (dpy, id, CWEventMask | CWDontPropagate, &attr);
5739
 
 
5740
 
    if (wa.map_state == IsViewable || shaded)
5741
 
        XMapWindow (dpy, frame);
5742
 
 
5743
 
    attr.event_mask = SubstructureRedirectMask | StructureNotifyMask |
5744
 
                      SubstructureNotifyMask | EnterWindowMask |
5745
 
                      LeaveWindowMask;
5746
 
 
5747
 
    XChangeWindowAttributes (dpy, frame, CWEventMask, &attr);
5748
 
    XChangeWindowAttributes (dpy, wrapper, CWEventMask, &attr);
5749
 
 
5750
 
    XSelectInput (dpy, screen->root (),
5751
 
                  SubstructureRedirectMask |
5752
 
                  SubstructureNotifyMask   |
5753
 
                  StructureNotifyMask      |
5754
 
                  PropertyChangeMask       |
5755
 
                  LeaveWindowMask          |
5756
 
                  EnterWindowMask          |
5757
 
                  KeyPressMask             |
5758
 
                  KeyReleaseMask           |
5759
 
                  ButtonPressMask          |
5760
 
                  ButtonReleaseMask        |
5761
 
                  FocusChangeMask          |
5762
 
                  ExposureMask);
5763
 
 
5764
 
    XUngrabServer (dpy);
5765
 
 
5766
 
    XMoveResizeWindow (dpy, frame, sg.x (), sg.y (), sg.width (), sg.height ());
5767
 
 
5768
 
    /* Try to use a relative window as a stacking anchor point */
5769
 
    if (sibling)
5770
 
    {
5771
 
        if (above)
5772
 
            window->restackAbove (sibling);
5773
 
        else
5774
 
            priv->restack (sibling->id ());
5775
 
    }
5776
 
 
5777
 
    window->windowNotify (CompWindowNotifyReparent);
5778
 
 
5779
 
    return true;
5780
 
}
5781
 
 
5782
 
void
5783
 
PrivateWindow::unreparent ()
5784
 
{
5785
 
    Display        *dpy = screen->dpy ();
5786
 
    XEvent         e;
5787
 
    bool           alive = true;
5788
 
    XWindowChanges xwc;
5789
 
 
5790
 
    if (!frame)
5791
 
        return;
5792
 
 
5793
 
    XSync (dpy, false);
5794
 
 
5795
 
    if (XCheckTypedWindowEvent (dpy, id, DestroyNotify, &e))
5796
 
    {
5797
 
        XPutBackEvent (dpy, &e);
5798
 
        alive = false;
5799
 
    }
5800
 
 
5801
 
    if ((!destroyed) && alive)
5802
 
    {
5803
 
        XGrabServer (dpy);
5804
 
 
5805
 
        XChangeSaveSet (dpy, id, SetModeDelete);
5806
 
        XSelectInput (dpy, frame, NoEventMask);
5807
 
        XSelectInput (dpy, id, NoEventMask);
5808
 
        XSelectInput (dpy, screen->root (), NoEventMask);
5809
 
        XReparentWindow (dpy, id, screen->root (), 0, 0);
5810
 
 
5811
 
        xwc.stack_mode = Below;
5812
 
        xwc.sibling    = frame;
5813
 
        XConfigureWindow (dpy, id, CWSibling | CWStackMode, &xwc);
5814
 
 
5815
 
        XUnmapWindow (dpy, frame);
5816
 
 
5817
 
        XSelectInput (dpy, id, PropertyChangeMask | EnterWindowMask |
5818
 
                      FocusChangeMask);
5819
 
 
5820
 
        XSelectInput (dpy, screen->root (),
5821
 
                  SubstructureRedirectMask |
5822
 
                  SubstructureNotifyMask   |
5823
 
                  StructureNotifyMask      |
5824
 
                  PropertyChangeMask       |
5825
 
                  LeaveWindowMask          |
5826
 
                  EnterWindowMask          |
5827
 
                  KeyPressMask             |
5828
 
                  KeyReleaseMask           |
5829
 
                  ButtonPressMask          |
5830
 
                  ButtonReleaseMask        |
5831
 
                  FocusChangeMask          |
5832
 
                  ExposureMask);
5833
 
 
5834
 
        XUngrabServer (dpy);
5835
 
 
5836
 
        XMoveWindow (dpy, id, serverGeometry.x (), serverGeometry.y ());
5837
 
    }
5838
 
 
5839
 
    XDestroyWindow (dpy, wrapper);
5840
 
    XDestroyWindow (dpy, frame);
5841
 
    wrapper = None;
5842
 
    frame = None;
5843
 
 
5844
 
    window->windowNotify (CompWindowNotifyUnreparent);
5845
 
}