~mc-return/compiz/compiz.merge-src-screen.cpp-improvements

« back to all changes in this revision

Viewing changes to plugins/composite/window.cpp

  • Committer: Dennis kasprzyk
  • Author(s): Dennis Kasprzyk
  • Date: 2009-03-15 05:09:18 UTC
  • Revision ID: git-v1:163f6b6f3c3b7764987cbdf8e03cc355edeaa499
New generalized build system.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © 2008 Dennis Kasprzyk
3
 
 * Copyright © 2007 Novell, Inc.
4
 
 *
5
 
 * Permission to use, copy, modify, distribute, and sell this software
6
 
 * and its documentation for any purpose is hereby granted without
7
 
 * fee, provided that the above copyright notice appear in all copies
8
 
 * and that both that copyright notice and this permission notice
9
 
 * appear in supporting documentation, and that the name of
10
 
 * Dennis Kasprzyk not be used in advertising or publicity pertaining to
11
 
 * distribution of the software without specific, written prior permission.
12
 
 * Dennis Kasprzyk makes no representations about the suitability of this
13
 
 * software for any purpose. It is provided "as is" without express or
14
 
 * implied warranty.
15
 
 *
16
 
 * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17
 
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
18
 
 * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19
 
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
20
 
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
21
 
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
22
 
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
 
 *
24
 
 * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
25
 
 *          David Reveman <davidr@novell.com>
26
 
 */
27
 
 
28
 
#include "privates.h"
29
 
 
30
 
CompositeWindow::CompositeWindow (CompWindow *w) :
31
 
    PrivateHandler<CompositeWindow, CompWindow, COMPIZ_COMPOSITE_ABI> (w),
32
 
    priv (new PrivateCompositeWindow (w, this))
33
 
{
34
 
    CompScreen *s = screen;
35
 
 
36
 
    if (w->windowClass () != InputOnly)
37
 
    {
38
 
        priv->damage = XDamageCreate (s->dpy (), w->id (),
39
 
                                      XDamageReportRawRectangles);
40
 
    }
41
 
    else
42
 
    {
43
 
        priv->damage = None;
44
 
    }
45
 
 
46
 
    priv->opacity = OPAQUE;
47
 
    if (!(w->type () & CompWindowTypeDesktopMask))
48
 
        priv->opacity = s->getWindowProp32 (w->id (),
49
 
                                            Atoms::winOpacity, OPAQUE);
50
 
 
51
 
    priv->brightness = s->getWindowProp32 (w->id (),
52
 
                                           Atoms::winBrightness, BRIGHT);
53
 
 
54
 
    priv->saturation = s->getWindowProp32 (w->id (),
55
 
                                           Atoms::winSaturation, COLOR);
56
 
        
57
 
    if (w->isViewable ())
58
 
        priv->damaged = true;
59
 
}
60
 
 
61
 
CompositeWindow::~CompositeWindow ()
62
 
{
63
 
 
64
 
    if (priv->damage)
65
 
        XDamageDestroy (screen->dpy (), priv->damage);
66
 
 
67
 
     if (!priv->redirected)
68
 
    {
69
 
        priv->cScreen->overlayWindowCount ()--;
70
 
 
71
 
        if (priv->cScreen->overlayWindowCount () < 1)
72
 
            priv->cScreen->showOutputWindow ();
73
 
    }
74
 
 
75
 
    release ();
76
 
 
77
 
    addDamage ();
78
 
 
79
 
    if (lastDamagedWindow == priv->window)
80
 
        lastDamagedWindow = NULL;
81
 
 
82
 
    delete priv;
83
 
}
84
 
 
85
 
PrivateCompositeWindow::PrivateCompositeWindow (CompWindow      *w,
86
 
                                                CompositeWindow *cw) :
87
 
    window (w),
88
 
    cWindow (cw),
89
 
    cScreen (CompositeScreen::get (screen)),
90
 
    pixmap (None),
91
 
    damage (None),
92
 
    damaged (false),
93
 
    redirected (cScreen->compositingActive ()),
94
 
    overlayWindow (false),
95
 
    bindFailed (false),
96
 
    opacity (OPAQUE),
97
 
    brightness (BRIGHT),
98
 
    saturation (COLOR),
99
 
    damageRects (0),
100
 
    sizeDamage (0),
101
 
    nDamage (0)
102
 
{
103
 
    WindowInterface::setHandler (w);
104
 
}
105
 
 
106
 
PrivateCompositeWindow::~PrivateCompositeWindow ()
107
 
{
108
 
 
109
 
    if (sizeDamage)
110
 
        free (damageRects);
111
 
}
112
 
 
113
 
bool
114
 
CompositeWindow::bind ()
115
 
{
116
 
    if (!priv->cScreen->compositingActive ())
117
 
        return false;
118
 
 
119
 
    redirect ();
120
 
    if (!priv->pixmap)
121
 
    {
122
 
        XWindowAttributes attr;
123
 
 
124
 
        /* don't try to bind window again if it failed previously */
125
 
        if (priv->bindFailed)
126
 
            return false;
127
 
 
128
 
        /* We have to grab the server here to make sure that window
129
 
           is mapped when getting the window pixmap */
130
 
        XGrabServer (screen->dpy ());
131
 
        XGetWindowAttributes (screen->dpy (),
132
 
                              ROOTPARENT (priv->window), &attr);
133
 
        if (attr.map_state != IsViewable)
134
 
        {
135
 
            XUngrabServer (screen->dpy ());
136
 
            priv->bindFailed = true;
137
 
            return false;
138
 
        }
139
 
 
140
 
        priv->pixmap = XCompositeNameWindowPixmap
141
 
            (screen->dpy (), ROOTPARENT (priv->window));
142
 
 
143
 
        XUngrabServer (screen->dpy ());
144
 
    }
145
 
    return true;
146
 
}
147
 
 
148
 
void
149
 
CompositeWindow::release ()
150
 
{
151
 
    if (priv->pixmap)
152
 
    {
153
 
        XFreePixmap (screen->dpy (), priv->pixmap);
154
 
        priv->pixmap = None;
155
 
    }
156
 
}
157
 
 
158
 
Pixmap
159
 
CompositeWindow::pixmap ()
160
 
{
161
 
    return priv->pixmap;
162
 
}
163
 
 
164
 
void
165
 
CompositeWindow::redirect ()
166
 
{
167
 
    if (priv->redirected || !priv->cScreen->compositingActive ())
168
 
        return;
169
 
 
170
 
    XCompositeRedirectWindow (screen->dpy (),
171
 
                              ROOTPARENT (priv->window),
172
 
                              CompositeRedirectManual);
173
 
 
174
 
    priv->redirected = true;
175
 
 
176
 
    if (priv->overlayWindow)
177
 
    {
178
 
        priv->cScreen->overlayWindowCount ()--;
179
 
        priv->overlayWindow = false;
180
 
    }
181
 
 
182
 
    if (priv->cScreen->overlayWindowCount () < 1)
183
 
        priv->cScreen->showOutputWindow ();
184
 
    else
185
 
        priv->cScreen->updateOutputWindow ();
186
 
}
187
 
 
188
 
void
189
 
CompositeWindow::unredirect ()
190
 
{
191
 
    if (!priv->redirected || !priv->cScreen->compositingActive ())
192
 
        return;
193
 
 
194
 
    release ();
195
 
 
196
 
    XCompositeUnredirectWindow (screen->dpy (),
197
 
                                ROOTPARENT (priv->window),
198
 
                                CompositeRedirectManual);
199
 
 
200
 
    priv->redirected   = false;
201
 
    priv->overlayWindow = true;
202
 
    priv->cScreen->overlayWindowCount ()++;
203
 
 
204
 
    if (priv->cScreen->overlayWindowCount () > 0)
205
 
        priv->cScreen->updateOutputWindow ();
206
 
}
207
 
 
208
 
bool
209
 
CompositeWindow::redirected ()
210
 
{
211
 
    return priv->redirected;
212
 
}
213
 
 
214
 
bool
215
 
CompositeWindow::overlayWindow ()
216
 
{
217
 
    return priv->overlayWindow;
218
 
}
219
 
 
220
 
void
221
 
CompositeWindow::damageTransformedRect (float          xScale,
222
 
                                        float          yScale,
223
 
                                        float          xTranslate,
224
 
                                        float          yTranslate,
225
 
                                        const CompRect &rect)
226
 
{
227
 
    int x1, x2, y1, y2;
228
 
 
229
 
    x1 = (short) (rect.x1 () * xScale) - 1;
230
 
    y1 = (short) (rect.y1 () * yScale) - 1;
231
 
    x2 = (short) (rect.x2 () * xScale + 0.5f) + 1;
232
 
    y2 = (short) (rect.y2 () * yScale + 0.5f) + 1;
233
 
 
234
 
    x1 += (short) xTranslate;
235
 
    y1 += (short) yTranslate;
236
 
    x2 += (short) (xTranslate + 0.5f);
237
 
    y2 += (short) (yTranslate + 0.5f);
238
 
 
239
 
    if (x2 > x1 && y2 > y1)
240
 
    {
241
 
        CompWindow::Geometry geom = priv->window->geometry ();
242
 
 
243
 
        x1 += geom.x () + geom.border ();
244
 
        y1 += geom.y () + geom.border ();
245
 
        x2 += geom.x () + geom.border ();
246
 
        y2 += geom.y () + geom.border ();
247
 
 
248
 
        priv->cScreen->damageRegion (CompRegion (CompRect (x1, y1, x2 - x1, y2 - y1)));
249
 
    }
250
 
}
251
 
 
252
 
void
253
 
CompositeWindow::damageOutputExtents ()
254
 
{
255
 
    if (priv->cScreen->damageMask () & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
256
 
        return;
257
 
 
258
 
    if (priv->window->shaded () ||
259
 
        (priv->window->isViewable () && priv->damaged))
260
 
    {
261
 
        int x1, x2, y1, y2;
262
 
 
263
 
        CompWindow::Geometry geom = priv->window->geometry ();
264
 
        CompWindowExtents output  = priv->window->output ();
265
 
 
266
 
        /* top */
267
 
        x1 = -output.left - geom.border ();
268
 
        y1 = -output.top - geom.border ();
269
 
        x2 = priv->window->size ().width () + output.right - geom.border ();
270
 
        y2 = -geom.border ();
271
 
 
272
 
        if (x1 < x2 && y1 < y2)
273
 
            addDamageRect (CompRect (x1, y1, x2 - x1, y2 - y1));
274
 
 
275
 
        /* bottom */
276
 
        y1 = priv->window->size ().height () - geom.border ();
277
 
        y2 = y1 + output.bottom - geom.border ();
278
 
 
279
 
        if (x1 < x2 && y1 < y2)
280
 
            addDamageRect (CompRect (x1, y1, x2 - x1, y2 - y1));
281
 
 
282
 
        /* left */
283
 
        x1 = -output.left - geom.border ();
284
 
        y1 = -geom.border ();
285
 
        x2 = -geom.border ();
286
 
        y2 = priv->window->size ().height () - geom.border ();
287
 
 
288
 
        if (x1 < x2 && y1 < y2)
289
 
            addDamageRect (CompRect (x1, y1, x2 - x1, y2 - y1));
290
 
 
291
 
        /* right */
292
 
        x1 = priv->window->size ().width () - geom.border ();
293
 
        x2 = x1 + output.right - geom.border ();
294
 
 
295
 
        if (x1 < x2 && y1 < y2)
296
 
            addDamageRect (CompRect (x1, y1, x2 - x1, y2 - y1));
297
 
    }
298
 
}
299
 
 
300
 
void
301
 
CompositeWindow::addDamageRect (const CompRect &rect)
302
 
{
303
 
    int x, y;
304
 
 
305
 
    if (priv->cScreen->damageMask () & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
306
 
        return;
307
 
 
308
 
    if (!damageRect (false, rect))
309
 
    {
310
 
        x = rect.x ();
311
 
        y = rect.y ();
312
 
 
313
 
        CompWindow::Geometry geom = priv->window->geometry ();
314
 
        x += geom.x () + geom.border ();
315
 
        y += geom.y () + geom.border ();
316
 
 
317
 
        priv->cScreen->damageRegion (CompRegion (CompRect (x, y,
318
 
                                                           rect.width (),
319
 
                                                           rect.height ())));
320
 
    }
321
 
}
322
 
 
323
 
void
324
 
CompositeWindow::addDamage (bool force)
325
 
{
326
 
    if (priv->cScreen->damageMask () & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
327
 
        return;
328
 
 
329
 
    if (priv->window->shaded () || force ||
330
 
        (priv->window->isViewable () && priv->damaged))
331
 
    {
332
 
        int    border = priv->window->geometry ().border ();
333
 
 
334
 
        int x1 = -MAX (priv->window->output ().left,
335
 
                       priv->window->input ().left) - border;
336
 
        int y1 = -MAX (priv->window->output ().top,
337
 
                       priv->window->input ().top) - border;
338
 
        int x2 = priv->window->size ().width () +
339
 
                 MAX (priv->window->output ().right,
340
 
                      priv->window->input ().right) ;
341
 
        int y2 = priv->window->size ().height () +
342
 
                 MAX (priv->window->output ().bottom,
343
 
                      priv->window->input ().bottom) ;
344
 
        CompRect r (x1, y1, x2 - x1, y2 - y1);
345
 
 
346
 
        addDamageRect (r);
347
 
    }
348
 
}
349
 
 
350
 
bool
351
 
CompositeWindow::damaged ()
352
 
{
353
 
    return priv->damaged;
354
 
}
355
 
 
356
 
void
357
 
CompositeWindow::processDamage (XDamageNotifyEvent *de)
358
 
{
359
 
    if (priv->window->syncWait ())
360
 
    {
361
 
        if (priv->nDamage == priv->sizeDamage)
362
 
        {
363
 
            priv->damageRects = (XRectangle *) realloc (priv->damageRects,
364
 
                                 (priv->sizeDamage + 1) *
365
 
                                 sizeof (XRectangle));
366
 
            priv->sizeDamage += 1;
367
 
        }
368
 
 
369
 
        priv->damageRects[priv->nDamage].x      = de->area.x;
370
 
        priv->damageRects[priv->nDamage].y      = de->area.y;
371
 
        priv->damageRects[priv->nDamage].width  = de->area.width;
372
 
        priv->damageRects[priv->nDamage].height = de->area.height;
373
 
        priv->nDamage++;
374
 
    }
375
 
    else
376
 
    {
377
 
        priv->handleDamageRect (this, de->area.x, de->area.y,
378
 
                                de->area.width, de->area.height);
379
 
    }
380
 
}
381
 
 
382
 
void
383
 
PrivateCompositeWindow::handleDamageRect (CompositeWindow *w,
384
 
                                          int             x,
385
 
                                          int             y,
386
 
                                          int             width,
387
 
                                          int             height)
388
 
{
389
 
    bool   initial = false;
390
 
 
391
 
    if (!w->priv->redirected)
392
 
        return;
393
 
 
394
 
    if (!w->priv->damaged)
395
 
    {
396
 
        w->priv->damaged = initial = true;
397
 
    }
398
 
 
399
 
    if (!w->damageRect (initial, CompRect (x, y, width, height)))
400
 
    {
401
 
        CompWindow::Geometry geom = w->priv->window->geometry ();
402
 
 
403
 
        x += geom.x () + geom.border ();
404
 
        y += geom.y () + geom.border ();
405
 
 
406
 
        w->priv->cScreen->damageRegion (CompRegion (CompRect (x, y, width, height)));
407
 
    }
408
 
 
409
 
    if (initial)
410
 
        w->damageOutputExtents ();
411
 
}
412
 
 
413
 
void
414
 
CompositeWindow::updateOpacity ()
415
 
{
416
 
    unsigned short opacity;
417
 
 
418
 
    if (priv->window->type () & CompWindowTypeDesktopMask)
419
 
        return;
420
 
 
421
 
    opacity = screen->getWindowProp32 (priv->window->id (),
422
 
                                             Atoms::winOpacity, OPAQUE);
423
 
 
424
 
    if (opacity != priv->opacity)
425
 
    {
426
 
        priv->opacity = opacity;
427
 
        addDamage ();
428
 
    }
429
 
}
430
 
 
431
 
void
432
 
CompositeWindow::updateBrightness ()
433
 
{
434
 
    unsigned short brightness;
435
 
 
436
 
    brightness = screen->getWindowProp32 (priv->window->id (),
437
 
                                                Atoms::winBrightness, BRIGHT);
438
 
 
439
 
    if (brightness != priv->brightness)
440
 
    {
441
 
        priv->brightness = brightness;
442
 
        addDamage ();
443
 
    }
444
 
}
445
 
 
446
 
void
447
 
CompositeWindow::updateSaturation ()
448
 
{
449
 
    unsigned short saturation;
450
 
 
451
 
    saturation = screen->getWindowProp32 (priv->window->id (),
452
 
                                                Atoms::winSaturation, COLOR);
453
 
 
454
 
    if (saturation != priv->saturation)
455
 
    {
456
 
        priv->saturation = saturation;
457
 
        addDamage ();
458
 
    }
459
 
}
460
 
 
461
 
unsigned short
462
 
CompositeWindow::opacity ()
463
 
{
464
 
    return priv->opacity;
465
 
}
466
 
 
467
 
unsigned short
468
 
CompositeWindow::brightness ()
469
 
{
470
 
    return priv->brightness;
471
 
}
472
 
 
473
 
unsigned short
474
 
CompositeWindow::saturation ()
475
 
{
476
 
    return priv->saturation;
477
 
}
478
 
 
479
 
bool
480
 
CompositeWindow::damageRect (bool           initial,
481
 
                             const CompRect &rect)
482
 
{
483
 
    WRAPABLE_HND_FUNC_RETURN(0, bool, damageRect, initial, rect)
484
 
    return false;
485
 
}
486
 
 
487
 
void
488
 
PrivateCompositeWindow::windowNotify (CompWindowNotify n)
489
 
{
490
 
    switch (n)
491
 
    {
492
 
        case CompWindowNotifyMap:
493
 
            bindFailed = false;
494
 
            damaged = false;
495
 
            break;
496
 
        case CompWindowNotifyUnmap:
497
 
            cWindow->addDamage (true);
498
 
            cWindow->release ();
499
 
 
500
 
            if (!redirected && cScreen->compositingActive ())
501
 
                cWindow->redirect ();
502
 
            break;
503
 
        case CompWindowNotifyRestack:
504
 
        case CompWindowNotifyHide:
505
 
        case CompWindowNotifyShow:
506
 
        case CompWindowNotifyAliveChanged:
507
 
            cWindow->addDamage (true);
508
 
            break;
509
 
        case CompWindowNotifyReparent:
510
 
        case CompWindowNotifyUnreparent:
511
 
            if (redirected)
512
 
            {
513
 
                cWindow->release ();
514
 
            }
515
 
            cScreen->damageScreen ();
516
 
            cWindow->addDamage (true);
517
 
            break;
518
 
        case CompWindowNotifyFrameUpdate:
519
 
            cWindow->release ();
520
 
            break;
521
 
        case CompWindowNotifySyncAlarm:
522
 
        {
523
 
            XRectangle *rects;
524
 
 
525
 
            rects   = damageRects;
526
 
            while (nDamage--)
527
 
            {
528
 
                PrivateCompositeWindow::handleDamageRect (cWindow,
529
 
                                                          rects[nDamage].x,
530
 
                                                          rects[nDamage].y,
531
 
                                                          rects[nDamage].width,
532
 
                                                          rects[nDamage].height);
533
 
            }
534
 
            break;
535
 
        }
536
 
        default:
537
 
            break;
538
 
        
539
 
    }
540
 
 
541
 
    window->windowNotify (n);
542
 
}
543
 
 
544
 
void
545
 
PrivateCompositeWindow::resizeNotify (int dx, int dy, int dwidth, int dheight)
546
 
{
547
 
    window->resizeNotify (dx, dy, dwidth, dheight);
548
 
 
549
 
    Pixmap pixmap = None;
550
 
 
551
 
    if (window->shaded () || (window->isViewable () && damaged))
552
 
    {
553
 
        int x, y, x1, x2, y1, y2;
554
 
 
555
 
        x = window->geometry ().x ();
556
 
        y = window->geometry ().y ();
557
 
 
558
 
        x1 = x - window->output ().left - dx;
559
 
        y1 = y - window->output ().top - dy;
560
 
        x2 = x + window->size ().width () +
561
 
             window->output ().right - dx - dwidth;
562
 
        y2 = y + window->size ().height () +
563
 
             window->output ().bottom - dy - dheight;
564
 
 
565
 
        cScreen->damageRegion (CompRegion (CompRect (x1, y1, x2 - x1, y2 - y1)));
566
 
    }
567
 
 
568
 
    if (window->mapNum () && redirected)
569
 
    {
570
 
        unsigned int actualWidth, actualHeight, ui;
571
 
        Window       root;
572
 
        Status       result;
573
 
        int          i;
574
 
 
575
 
        pixmap = XCompositeNameWindowPixmap (screen->dpy (), window->id ());
576
 
        result = XGetGeometry (screen->dpy (), pixmap, &root, &i, &i,
577
 
                               &actualWidth, &actualHeight, &ui, &ui);
578
 
 
579
 
        if (!result || actualWidth != window->size ().width () ||
580
 
            actualHeight != window->size ().height ())
581
 
        {
582
 
            XFreePixmap (screen->dpy (), pixmap);
583
 
            return;
584
 
        }
585
 
    }
586
 
 
587
 
    cWindow->addDamage ();
588
 
 
589
 
    cWindow->release ();
590
 
    this->pixmap = pixmap;
591
 
}
592
 
 
593
 
void
594
 
PrivateCompositeWindow::moveNotify (int dx, int dy, bool now)
595
 
{
596
 
    if (window->shaded () || (window->isViewable () && damaged))
597
 
    {
598
 
        int x, y, x1, x2, y1, y2;
599
 
 
600
 
        x = window->geometry ().x ();
601
 
        y = window->geometry ().y ();
602
 
 
603
 
        x1 = x - window->output ().left - dx;
604
 
        y1 = y - window->output ().top - dy;
605
 
        x2 = x + window->size ().width () +
606
 
             window->output ().right - dx;
607
 
        y2 = y + window->size ().height () +
608
 
             window->output ().bottom - dy;
609
 
 
610
 
        cScreen->damageRegion (CompRegion (CompRect (x1, y1, x2 - x1, y2 - y1)));
611
 
    }
612
 
    cWindow->addDamage ();
613
 
 
614
 
    window->moveNotify (dx, dy, now);
615
 
}
616
 
 
617
 
bool
618
 
CompositeWindowInterface::damageRect (bool initial, const CompRect &rect)
619
 
    WRAPABLE_DEF (damageRect, initial, rect)