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

« back to all changes in this revision

Viewing changes to plugins/composite/screen.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
 
#ifdef HAVE_CONFIG_H
29
 
#  include <config.h>
30
 
#endif
31
 
 
32
 
#include <sys/time.h>
33
 
 
34
 
#include <X11/Xlib.h>
35
 
#include <X11/Xatom.h>
36
 
#include <X11/Xproto.h>
37
 
#include <X11/extensions/Xcomposite.h>
38
 
#include <X11/extensions/Xrandr.h>
39
 
#include <X11/extensions/shape.h>
40
 
 
41
 
#include "privates.h"
42
 
 
43
 
#include <X11/extensions/shape.h>
44
 
#include <X11/extensions/Xrandr.h>
45
 
 
46
 
CompWindow *lastDamagedWindow = 0;
47
 
 
48
 
 
49
 
void
50
 
PrivateCompositeScreen::handleEvent (XEvent *event)
51
 
{
52
 
    CompWindow      *w;
53
 
 
54
 
    switch (event->type) {
55
 
 
56
 
        case CreateNotify:
57
 
            if (screen->root () == event->xcreatewindow.parent)
58
 
            {
59
 
                /* The first time some client asks for the composite
60
 
                 * overlay window, the X server creates it, which causes
61
 
                 * an errorneous CreateNotify event.  We catch it and
62
 
                 * ignore it. */
63
 
                if (overlay == event->xcreatewindow.window)
64
 
                    return;
65
 
            }
66
 
            break;
67
 
        case PropertyNotify:
68
 
            if (event->xproperty.atom == Atoms::winOpacity)
69
 
            {
70
 
                w = screen->findWindow (event->xproperty.window);
71
 
                if (w)
72
 
                    CompositeWindow::get (w)->updateOpacity ();
73
 
            }
74
 
            else if (event->xproperty.atom == Atoms::winBrightness)
75
 
            {
76
 
                w = screen->findWindow (event->xproperty.window);
77
 
                if (w)
78
 
                    CompositeWindow::get (w)->updateBrightness ();
79
 
            }
80
 
            else if (event->xproperty.atom == Atoms::winSaturation)
81
 
            {
82
 
                w = screen->findWindow (event->xproperty.window);
83
 
                if (w)
84
 
                    CompositeWindow::get (w)->updateSaturation ();
85
 
            }
86
 
            break;
87
 
        default:
88
 
            if (shapeExtension &&
89
 
                event->type == shapeEvent + ShapeNotify)
90
 
            {
91
 
                w = screen->findWindow (((XShapeEvent *) event)->window);
92
 
                if (w)
93
 
                {
94
 
                    if (w->mapNum ())
95
 
                    {
96
 
                        CompositeWindow::get (w)->addDamage ();
97
 
                    }
98
 
                }
99
 
            }
100
 
            break;
101
 
    }
102
 
        
103
 
    screen->handleEvent (event);
104
 
 
105
 
    switch (event->type) {
106
 
        case Expose:
107
 
            handleExposeEvent (&event->xexpose);
108
 
        break;
109
 
        case ClientMessage:
110
 
            if (event->xclient.message_type == Atoms::winOpacity)
111
 
            {
112
 
                w = screen->findWindow (event->xclient.window);
113
 
                if (w && (w->type () & CompWindowTypeDesktopMask) == 0)
114
 
                {
115
 
                    unsigned short opacity = event->xclient.data.l[0] >> 16;
116
 
 
117
 
                    screen->setWindowProp32 (w->id (),
118
 
                        Atoms::winOpacity, opacity);
119
 
                }
120
 
            }
121
 
            else if (event->xclient.message_type ==
122
 
                     Atoms::winBrightness)
123
 
            {
124
 
                w = screen->findWindow (event->xclient.window);
125
 
                if (w)
126
 
                {
127
 
                    unsigned short brightness = event->xclient.data.l[0] >> 16;
128
 
 
129
 
                    screen->setWindowProp32 (w->id (),
130
 
                        Atoms::winBrightness, brightness);
131
 
                }
132
 
            }
133
 
            else if (event->xclient.message_type ==
134
 
                     Atoms::winSaturation)
135
 
            {
136
 
                w = screen->findWindow (event->xclient.window);
137
 
                if (w)
138
 
                {
139
 
                    unsigned short saturation = event->xclient.data.l[0] >> 16;
140
 
 
141
 
                    screen->setWindowProp32 (w->id (),
142
 
                        Atoms::winSaturation, saturation);
143
 
                }
144
 
            }
145
 
            break;
146
 
        default:
147
 
            if (event->type == damageEvent + XDamageNotify)
148
 
            {
149
 
                XDamageNotifyEvent *de = (XDamageNotifyEvent *) event;
150
 
 
151
 
                if (lastDamagedWindow && de->drawable == lastDamagedWindow->id ())
152
 
                {
153
 
                    w = lastDamagedWindow;
154
 
                }
155
 
                else
156
 
                {
157
 
                    w = screen->findWindow (de->drawable);
158
 
                    if (w)
159
 
                        lastDamagedWindow = w;
160
 
                }
161
 
 
162
 
                if (w)
163
 
                    CompositeWindow::get (w)->processDamage (de);
164
 
            }
165
 
            else if (shapeExtension &&
166
 
                     event->type == shapeEvent + ShapeNotify)
167
 
            {
168
 
                w = screen->findWindow (((XShapeEvent *) event)->window);
169
 
                if (w)
170
 
                {
171
 
                    if (w->mapNum ())
172
 
                    {
173
 
                        CompositeWindow::get (w)->addDamage ();
174
 
                    }
175
 
                }
176
 
            }
177
 
            else if (randrExtension &&
178
 
                     event->type == randrEvent + RRScreenChangeNotify)
179
 
            {
180
 
                XRRScreenChangeNotifyEvent *rre;
181
 
 
182
 
                rre = (XRRScreenChangeNotifyEvent *) event;
183
 
 
184
 
                if (screen->root () == rre->root)
185
 
                    cScreen->detectRefreshRate ();
186
 
            }
187
 
            break;
188
 
    }
189
 
}
190
 
 
191
 
int
192
 
CompositeScreen::damageEvent ()
193
 
{
194
 
    return priv->damageEvent;
195
 
}
196
 
 
197
 
 
198
 
CompositeScreen::CompositeScreen (CompScreen *s) :
199
 
    PrivateHandler<CompositeScreen, CompScreen, COMPIZ_COMPOSITE_ABI> (s),
200
 
    priv (new PrivateCompositeScreen (this))
201
 
{
202
 
    int compositeMajor, compositeMinor;
203
 
 
204
 
    if (!compositeVTable->getMetadata ()->initOptions (compositeOptionInfo,
205
 
                                                       COMPOSITE_OPTION_NUM,
206
 
                                                       priv->opt))
207
 
    {
208
 
        setFailed ();
209
 
        return;
210
 
    }
211
 
 
212
 
    if (!XQueryExtension (s->dpy (), COMPOSITE_NAME,
213
 
                          &priv->compositeOpcode,
214
 
                          &priv->compositeEvent,
215
 
                          &priv->compositeError))
216
 
    {
217
 
        compLogMessage ("core", CompLogLevelFatal,
218
 
                        "No composite extension");
219
 
        setFailed ();
220
 
        return;
221
 
    }
222
 
 
223
 
    XCompositeQueryVersion (s->dpy (), &compositeMajor, &compositeMinor);
224
 
    if (compositeMajor == 0 && compositeMinor < 2)
225
 
    {
226
 
        compLogMessage ("core", CompLogLevelFatal,
227
 
                        "Old composite extension");
228
 
        setFailed ();
229
 
        return;
230
 
    }
231
 
 
232
 
    if (!XDamageQueryExtension (s->dpy (), &priv->damageEvent,
233
 
                                &priv->damageError))
234
 
    {
235
 
        compLogMessage ("core", CompLogLevelFatal,
236
 
                        "No damage extension");
237
 
        setFailed ();
238
 
        return;
239
 
    }
240
 
 
241
 
    if (!XFixesQueryExtension (s->dpy (), &priv->fixesEvent, &priv->fixesError))
242
 
    {
243
 
        compLogMessage ("core", CompLogLevelFatal,
244
 
                        "No fixes extension");
245
 
        setFailed ();
246
 
        return;
247
 
    }
248
 
 
249
 
    priv->shapeExtension = XShapeQueryExtension (s->dpy (), &priv->shapeEvent,
250
 
                                                 &priv->shapeError);
251
 
    priv->randrExtension = XRRQueryExtension (s->dpy (), &priv->randrEvent,
252
 
                                              &priv->randrError);
253
 
 
254
 
    priv->makeOutputWindow ();
255
 
 
256
 
    detectRefreshRate ();
257
 
 
258
 
    priv->slowAnimations = false;
259
 
 
260
 
    if (!priv->init ())
261
 
    {
262
 
        setFailed ();
263
 
    }
264
 
 
265
 
}
266
 
 
267
 
CompositeScreen::~CompositeScreen ()
268
 
{
269
 
    priv->paintTimer.stop ();
270
 
 
271
 
#ifdef USE_COW
272
 
    if (useCow)
273
 
        XCompositeReleaseOverlayWindow (screen->dpy (),
274
 
                                        screen->root ());
275
 
#endif
276
 
 
277
 
    delete priv;
278
 
}
279
 
 
280
 
 
281
 
PrivateCompositeScreen::PrivateCompositeScreen (CompositeScreen *cs) :
282
 
    cScreen (cs),
283
 
    damageMask (COMPOSITE_SCREEN_DAMAGE_ALL_MASK),
284
 
    overlay (None),
285
 
    output (None),
286
 
    exposeRects (),
287
 
    windowPaintOffset (0, 0),
288
 
    overlayWindowCount (0),
289
 
    nextRedraw (0),
290
 
    redrawTime (1000 / 50),
291
 
    optimalRedrawTime (1000 / 50),
292
 
    frameStatus (0),
293
 
    timeMult (1),
294
 
    idle (true),
295
 
    timeLeft (0),
296
 
    slowAnimations (false),
297
 
    active (false),
298
 
    pHnd (NULL),
299
 
    opt (COMPOSITE_OPTION_NUM)
300
 
{
301
 
    gettimeofday (&lastRedraw, 0);
302
 
    // wrap outputChangeNotify
303
 
    ScreenInterface::setHandler (screen);
304
 
}
305
 
 
306
 
PrivateCompositeScreen::~PrivateCompositeScreen ()
307
 
{
308
 
}
309
 
 
310
 
bool
311
 
PrivateCompositeScreen::init ()
312
 
{
313
 
    Display              *dpy = screen->dpy ();
314
 
    Window               newCmSnOwner = None;
315
 
    Atom                 cmSnAtom = 0;
316
 
    Time                 cmSnTimestamp = 0;
317
 
    XEvent               event;
318
 
    XSetWindowAttributes attr;
319
 
    Window               currentCmSnOwner;
320
 
    char                 buf[128];
321
 
 
322
 
    sprintf (buf, "_NET_WM_CM_S%d", screen->screenNum ());
323
 
    cmSnAtom = XInternAtom (dpy, buf, 0);
324
 
 
325
 
    currentCmSnOwner = XGetSelectionOwner (dpy, cmSnAtom);
326
 
 
327
 
    if (currentCmSnOwner != None)
328
 
    {
329
 
        if (!replaceCurrentWm)
330
 
        {
331
 
            compLogMessage ("composite", CompLogLevelError,
332
 
                            "Screen %d on display \"%s\" already "
333
 
                            "has a compositing manager; try using the "
334
 
                            "--replace option to replace the current "
335
 
                            "compositing manager.",
336
 
                            screen->screenNum (), DisplayString (dpy));
337
 
 
338
 
            return false;
339
 
        }
340
 
    }
341
 
 
342
 
    attr.override_redirect = TRUE;
343
 
    attr.event_mask        = PropertyChangeMask;
344
 
 
345
 
    newCmSnOwner =
346
 
        XCreateWindow (dpy, XRootWindow (dpy, screen->screenNum ()),
347
 
                       -100, -100, 1, 1, 0,
348
 
                       CopyFromParent, CopyFromParent,
349
 
                       CopyFromParent,
350
 
                       CWOverrideRedirect | CWEventMask,
351
 
                       &attr);
352
 
 
353
 
    XChangeProperty (dpy, newCmSnOwner, Atoms::wmName, Atoms::utf8String, 8,
354
 
                     PropModeReplace, (unsigned char *) PACKAGE,
355
 
                     strlen (PACKAGE));
356
 
 
357
 
    XWindowEvent (dpy, newCmSnOwner, PropertyChangeMask, &event);
358
 
 
359
 
    cmSnTimestamp = event.xproperty.time;
360
 
 
361
 
 
362
 
    XSetSelectionOwner (dpy, cmSnAtom, newCmSnOwner, cmSnTimestamp);
363
 
 
364
 
    if (XGetSelectionOwner (dpy, cmSnAtom) != newCmSnOwner)
365
 
    {
366
 
        compLogMessage ("composite", CompLogLevelError,
367
 
                        "Could not acquire compositing manager "
368
 
                        "selection on screen %d display \"%s\"",
369
 
                        screen->screenNum (), DisplayString (dpy));
370
 
 
371
 
        return false;
372
 
    }
373
 
 
374
 
    return true;
375
 
}
376
 
 
377
 
 
378
 
bool
379
 
CompositeScreen::registerPaintHandler (PaintHandler *pHnd)
380
 
{
381
 
    Display *dpy = screen->dpy ();
382
 
 
383
 
    if (priv->active)
384
 
        return false;
385
 
 
386
 
    CompScreen::checkForError (dpy);
387
 
 
388
 
    XCompositeRedirectSubwindows (dpy, screen->root (),
389
 
                                  CompositeRedirectManual);
390
 
 
391
 
    priv->overlayWindowCount = 0;
392
 
 
393
 
    if (CompScreen::checkForError (dpy))
394
 
    {
395
 
        compLogMessage ("composite", CompLogLevelError,
396
 
                        "Another composite manager is already "
397
 
                        "running on screen: %d", screen->screenNum ());
398
 
 
399
 
        return false;
400
 
    }
401
 
 
402
 
    foreach (CompWindow *w, screen->windows ())
403
 
    {
404
 
        CompositeWindow *cw = CompositeWindow::get (w);
405
 
        cw->priv->overlayWindow = false;
406
 
        cw->priv->redirected = true;
407
 
    }
408
 
 
409
 
    priv->pHnd = pHnd;
410
 
    priv->active = true;
411
 
 
412
 
    showOutputWindow ();
413
 
 
414
 
    priv->paintTimer.start
415
 
        (boost::bind(&CompositeScreen::handlePaintTimeout, this),
416
 
         priv->optimalRedrawTime, MAXSHORT);
417
 
    return true;
418
 
}
419
 
 
420
 
void
421
 
CompositeScreen::unregisterPaintHandler ()
422
 
{
423
 
    Display *dpy = screen->dpy ();
424
 
 
425
 
    foreach (CompWindow *w, screen->windows ())
426
 
    {
427
 
        CompositeWindow *cw = CompositeWindow::get (w);
428
 
        cw->priv->overlayWindow = false;
429
 
        cw->priv->redirected = false;
430
 
        cw->release ();
431
 
    }
432
 
 
433
 
    priv->overlayWindowCount = 0;
434
 
 
435
 
    XCompositeUnredirectSubwindows (dpy, screen->root (),
436
 
                                    CompositeRedirectManual);
437
 
 
438
 
    priv->pHnd = NULL;
439
 
    priv->active = false;
440
 
    priv->paintTimer.stop ();
441
 
 
442
 
    hideOutputWindow ();
443
 
}
444
 
 
445
 
bool
446
 
CompositeScreen::compositingActive ()
447
 
{
448
 
    return priv->active;
449
 
}
450
 
 
451
 
void
452
 
CompositeScreen::damageScreen ()
453
 
{
454
 
    if (priv->damageMask == 0)
455
 
        priv->paintTimer.setTimes (priv->paintTimer.minLeft ());
456
 
 
457
 
    priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_ALL_MASK;
458
 
    priv->damageMask &= ~COMPOSITE_SCREEN_DAMAGE_REGION_MASK;
459
 
}
460
 
 
461
 
void
462
 
CompositeScreen::damageRegion (const CompRegion &region)
463
 
{
464
 
    if (priv->damageMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
465
 
        return;
466
 
 
467
 
    if (priv->damageMask == 0)
468
 
        priv->paintTimer.setTimes (priv->paintTimer.minLeft ());
469
 
 
470
 
    priv->damage += region;
471
 
 
472
 
    priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_REGION_MASK;
473
 
 
474
 
    /* if the number of damage rectangles grows two much between repaints,
475
 
       we have a lot of overhead just for doing the damage tracking -
476
 
       in order to make sure we're not having too much overhead, damage
477
 
       the whole screen if we have a lot of damage rects */
478
 
 
479
 
    if (priv->damage.numRects () > 100)
480
 
       damageScreen ();
481
 
}
482
 
 
483
 
void
484
 
CompositeScreen::damagePending ()
485
 
{
486
 
    if (priv->damageMask == 0)
487
 
        priv->paintTimer.setTimes (priv->paintTimer.minLeft ());
488
 
 
489
 
    priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_PENDING_MASK;
490
 
}
491
 
 
492
 
unsigned int
493
 
CompositeScreen::damageMask ()
494
 
{
495
 
    return priv->damageMask;
496
 
}
497
 
 
498
 
void
499
 
CompositeScreen::showOutputWindow ()
500
 
{
501
 
#ifdef USE_COW
502
 
    if (useCow && priv->active)
503
 
    {
504
 
        Display       *dpy = screen->dpy ();
505
 
        XserverRegion region;
506
 
 
507
 
        region = XFixesCreateRegion (dpy, NULL, 0);
508
 
 
509
 
        XFixesSetWindowShapeRegion (dpy,
510
 
                                    priv->output,
511
 
                                    ShapeBounding,
512
 
                                    0, 0, 0);
513
 
        XFixesSetWindowShapeRegion (dpy,
514
 
                                    priv->output,
515
 
                                    ShapeInput,
516
 
                                    0, 0, region);
517
 
 
518
 
        XFixesDestroyRegion (dpy, region);
519
 
 
520
 
        damageScreen ();
521
 
    }
522
 
#endif
523
 
 
524
 
}
525
 
 
526
 
void
527
 
CompositeScreen::hideOutputWindow ()
528
 
{
529
 
#ifdef USE_COW
530
 
    if (useCow)
531
 
    {
532
 
        Display       *dpy = screen->dpy ();
533
 
        XserverRegion region;
534
 
 
535
 
        region = XFixesCreateRegion (dpy, NULL, 0);
536
 
 
537
 
        XFixesSetWindowShapeRegion (dpy,
538
 
                                    priv->output,
539
 
                                    ShapeBounding,
540
 
                                    0, 0, region);
541
 
 
542
 
        XFixesDestroyRegion (dpy, region);
543
 
    }
544
 
#endif
545
 
 
546
 
}
547
 
 
548
 
void
549
 
CompositeScreen::updateOutputWindow ()
550
 
{
551
 
#ifdef USE_COW
552
 
    if (useCow && priv->active)
553
 
    {
554
 
        Display       *dpy = screen->dpy ();
555
 
        XserverRegion region;
556
 
        CompRegion    tmpRegion (screen->region ());
557
 
        
558
 
        for (CompWindowList::reverse_iterator rit =
559
 
             screen->windows ().rbegin ();
560
 
             rit != screen->windows ().rend (); rit++)
561
 
            if (CompositeWindow::get (*rit)->overlayWindow ())
562
 
            {
563
 
                tmpRegion -= (*rit)->region ();
564
 
            }
565
 
        
566
 
        XShapeCombineRegion (dpy, priv->output, ShapeBounding,
567
 
                             0, 0, tmpRegion.handle (), ShapeSet);
568
 
 
569
 
 
570
 
        region = XFixesCreateRegion (dpy, NULL, 0);
571
 
 
572
 
        XFixesSetWindowShapeRegion (dpy,
573
 
                                    priv->output,
574
 
                                    ShapeInput,
575
 
                                    0, 0, region);
576
 
 
577
 
        XFixesDestroyRegion (dpy, region);
578
 
    }
579
 
#endif
580
 
 
581
 
}
582
 
 
583
 
void
584
 
PrivateCompositeScreen::makeOutputWindow ()
585
 
{
586
 
#ifdef USE_COW
587
 
    if (useCow)
588
 
    {
589
 
        overlay = XCompositeGetOverlayWindow (screen->dpy (), screen->root ());
590
 
        output  = overlay;
591
 
 
592
 
        XSelectInput (screen->dpy (), output, ExposureMask);
593
 
    }
594
 
    else
595
 
#endif
596
 
        output = overlay = screen->root ();
597
 
 
598
 
    cScreen->hideOutputWindow ();
599
 
}
600
 
 
601
 
Window
602
 
CompositeScreen::output ()
603
 
{
604
 
    return priv->output;
605
 
}
606
 
 
607
 
Window
608
 
CompositeScreen::overlay ()
609
 
{
610
 
    return priv->overlay;
611
 
}
612
 
 
613
 
int &
614
 
CompositeScreen::overlayWindowCount ()
615
 
{
616
 
    return priv->overlayWindowCount;
617
 
}
618
 
 
619
 
void
620
 
CompositeScreen::setWindowPaintOffset (int x, int y)
621
 
{
622
 
    priv->windowPaintOffset = CompPoint (x, y);
623
 
}
624
 
 
625
 
CompPoint
626
 
CompositeScreen::windowPaintOffset ()
627
 
{
628
 
    return priv->windowPaintOffset;
629
 
}
630
 
 
631
 
void
632
 
CompositeScreen::detectRefreshRate ()
633
 
{
634
 
    if (!noDetection &&
635
 
        priv->opt[COMPOSITE_OPTION_DETECT_REFRESH_RATE].value ().b ())
636
 
    {
637
 
        CompString        name;
638
 
        CompOption::Value value;
639
 
 
640
 
        value.set ((int) 0);
641
 
 
642
 
        if (screen->XRandr())
643
 
        {
644
 
            XRRScreenConfiguration *config;
645
 
 
646
 
            config  = XRRGetScreenInfo (screen->dpy (),
647
 
                                        screen->root ());
648
 
            value.set ((int) XRRConfigCurrentRate (config));
649
 
 
650
 
            XRRFreeScreenConfigInfo (config);
651
 
        }
652
 
 
653
 
        if (value.i () == 0)
654
 
            value.set ((int) 50);
655
 
 
656
 
        name = priv->opt[COMPOSITE_OPTION_REFRESH_RATE].name ();
657
 
 
658
 
        priv->opt[COMPOSITE_OPTION_DETECT_REFRESH_RATE].value ().set (false);
659
 
        screen->setOptionForPlugin ("composite", name.c_str (), value);
660
 
        priv->opt[COMPOSITE_OPTION_DETECT_REFRESH_RATE].value ().set (true);
661
 
    }
662
 
    else
663
 
    {
664
 
        priv->redrawTime = 1000 /
665
 
            priv->opt[COMPOSITE_OPTION_REFRESH_RATE].value ().i ();
666
 
        priv->optimalRedrawTime = priv->redrawTime;
667
 
    }
668
 
}
669
 
 
670
 
int
671
 
CompositeScreen::getTimeToNextRedraw (struct timeval *tv)
672
 
{
673
 
    int diff, next;
674
 
 
675
 
    diff = TIMEVALDIFF (tv, &priv->lastRedraw);
676
 
 
677
 
    /* handle clock rollback */
678
 
    if (diff < 0)
679
 
        diff = 0;
680
 
 
681
 
    if (priv->idle || (priv->pHnd && priv->pHnd->hasVSync ()))
682
 
    {
683
 
        if (priv->timeMult > 1)
684
 
        {
685
 
            priv->frameStatus = -1;
686
 
            priv->redrawTime = priv->optimalRedrawTime;
687
 
            priv->timeMult--;
688
 
        }
689
 
    }
690
 
    else
691
 
    {
692
 
        if (diff > priv->redrawTime)
693
 
        {
694
 
            if (priv->frameStatus > 0)
695
 
                priv->frameStatus = 0;
696
 
 
697
 
            next = priv->optimalRedrawTime * (priv->timeMult + 1);
698
 
            if (diff > next)
699
 
            {
700
 
                priv->frameStatus--;
701
 
                if (priv->frameStatus < -1)
702
 
                {
703
 
                    priv->timeMult++;
704
 
                    priv->redrawTime = diff = next;
705
 
                }
706
 
            }
707
 
        }
708
 
        else if (diff < priv->redrawTime)
709
 
        {
710
 
            if (priv->frameStatus < 0)
711
 
                priv->frameStatus = 0;
712
 
 
713
 
            if (priv->timeMult > 1)
714
 
            {
715
 
                next = priv->optimalRedrawTime * (priv->timeMult - 1);
716
 
                if (diff < next)
717
 
                {
718
 
                    priv->frameStatus++;
719
 
                    if (priv->frameStatus > 4)
720
 
                    {
721
 
                        priv->timeMult--;
722
 
                        priv->redrawTime = next;
723
 
                    }
724
 
                }
725
 
            }
726
 
        }
727
 
    }
728
 
    if (diff >= priv->redrawTime)
729
 
        return 1;
730
 
 
731
 
    return priv->redrawTime - diff;
732
 
}
733
 
 
734
 
int
735
 
CompositeScreen::redrawTime ()
736
 
{
737
 
    return priv->redrawTime;
738
 
}
739
 
 
740
 
bool
741
 
CompositeScreen::handlePaintTimeout ()
742
 
{
743
 
    int         timeDiff;
744
 
    struct      timeval tv;
745
 
 
746
 
    gettimeofday (&tv, 0);
747
 
 
748
 
    if (priv->damageMask)
749
 
    {
750
 
        if (priv->pHnd)
751
 
            priv->pHnd->prepareDrawing ();
752
 
 
753
 
        timeDiff = TIMEVALDIFF (&tv, &priv->lastRedraw);
754
 
 
755
 
        /* handle clock rollback */
756
 
        if (timeDiff < 0)
757
 
            timeDiff = 0;
758
 
 
759
 
        if (priv->slowAnimations)
760
 
        {
761
 
            preparePaint (priv->idle ? 2 : (timeDiff * 2) / priv->redrawTime);
762
 
        }
763
 
        else
764
 
            preparePaint (priv->idle ? priv->redrawTime : timeDiff);
765
 
 
766
 
        /* substract top most overlay window region */
767
 
        if (priv->overlayWindowCount)
768
 
        {
769
 
            for (CompWindowList::reverse_iterator rit =
770
 
                 screen->windows ().rbegin ();
771
 
                 rit != screen->windows ().rend (); rit++)
772
 
            {
773
 
                CompWindow *w = (*rit);
774
 
 
775
 
                if (w->destroyed () || w->invisible ())
776
 
                    continue;
777
 
 
778
 
                if (!CompositeWindow::get (w)->redirected ())
779
 
                    priv->damage -= w->region ();
780
 
 
781
 
                break;
782
 
            }
783
 
 
784
 
            if (priv->damageMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
785
 
            {
786
 
                priv->damageMask &= ~COMPOSITE_SCREEN_DAMAGE_ALL_MASK;
787
 
                priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_REGION_MASK;
788
 
            }
789
 
        }
790
 
 
791
 
        priv->tmpRegion = priv->damage & screen->region ();
792
 
        
793
 
        if (priv->damageMask & COMPOSITE_SCREEN_DAMAGE_REGION_MASK)
794
 
        {
795
 
            if (priv->tmpRegion == screen->region ())
796
 
                damageScreen ();
797
 
        }
798
 
 
799
 
        priv->damage = CompRegion ();
800
 
 
801
 
        int mask = priv->damageMask;
802
 
        priv->damageMask = 0;
803
 
 
804
 
        CompOutput::ptrList outputs (0);
805
 
        
806
 
        if (priv->opt[COMPOSITE_OPTION_FORCE_INDEPENDENT].value ().b ()
807
 
            || !screen->hasOverlappingOutputs ())
808
 
        {
809
 
            foreach (CompOutput &o, screen->outputDevs ())
810
 
                outputs.push_back (&o);
811
 
        }
812
 
        else
813
 
            outputs.push_back (&screen->fullscreenOutput ());
814
 
 
815
 
        paint (outputs, mask);
816
 
        
817
 
        priv->lastRedraw = tv;
818
 
 
819
 
        donePaint ();
820
 
 
821
 
        foreach (CompWindow *w, screen->windows ())
822
 
        {
823
 
            if (w->destroyed ())
824
 
            {
825
 
                CompositeWindow::get (w)->addDamage ();
826
 
                break;
827
 
            }
828
 
        }
829
 
 
830
 
        priv->idle = false;
831
 
    }
832
 
    else
833
 
    {
834
 
        priv->idle = true;
835
 
    }
836
 
 
837
 
    gettimeofday (&tv, 0);
838
 
 
839
 
    if (priv->idle)
840
 
        priv->paintTimer.setTimes (getTimeToNextRedraw (&tv), MAXSHORT);
841
 
    else
842
 
        priv->paintTimer.setTimes (getTimeToNextRedraw (&tv));
843
 
    return true;
844
 
}
845
 
 
846
 
void
847
 
CompositeScreen::preparePaint (int msSinceLastPaint)
848
 
    WRAPABLE_HND_FUNC(0, preparePaint, msSinceLastPaint)
849
 
 
850
 
void
851
 
CompositeScreen::donePaint ()
852
 
    WRAPABLE_HND_FUNC(1, donePaint)
853
 
 
854
 
void
855
 
CompositeScreen::paint (CompOutput::ptrList &outputs,
856
 
                        unsigned int        mask)
857
 
{
858
 
    WRAPABLE_HND_FUNC(2, paint, outputs, mask)
859
 
 
860
 
    if (priv->pHnd)
861
 
        priv->pHnd->paintOutputs (outputs, mask, priv->tmpRegion);
862
 
}
863
 
 
864
 
CompWindowList
865
 
CompositeScreen::getWindowPaintList ()
866
 
{
867
 
    WRAPABLE_HND_FUNC_RETURN (3, CompWindowList, getWindowPaintList)
868
 
 
869
 
    return screen->windows ();
870
 
}
871
 
 
872
 
void
873
 
PrivateCompositeScreen::handleExposeEvent (XExposeEvent *event)
874
 
{
875
 
    if (output == event->window)
876
 
        return;
877
 
 
878
 
    exposeRects.push_back (CompRect (event->x,
879
 
                                     event->y,
880
 
                                     event->width,
881
 
                                     event->height));
882
 
 
883
 
    if (event->count == 0)
884
 
    {
885
 
        CompRect rect;
886
 
        foreach (CompRect rect, exposeRects)
887
 
        {
888
 
            cScreen->damageRegion (CompRegion (rect));
889
 
        }
890
 
        exposeRects.clear ();
891
 
    }
892
 
}
893
 
 
894
 
void
895
 
PrivateCompositeScreen::outputChangeNotify ()
896
 
{
897
 
    screen->outputChangeNotify ();
898
 
#ifdef USE_COW
899
 
    if (useCow)
900
 
        XMoveResizeWindow (screen->dpy (), overlay, 0, 0,
901
 
                           screen->width (), screen->height ());
902
 
#endif
903
 
    cScreen->damageScreen ();
904
 
}
905
 
 
906
 
bool
907
 
CompositeScreen::toggleSlowAnimations (CompAction         *action,
908
 
                                       CompAction::State  state,
909
 
                                       CompOption::Vector &options)
910
 
{
911
 
    CompositeScreen *cs = CompositeScreen::get (screen);
912
 
    if (cs)
913
 
        cs->priv->slowAnimations = !cs->priv->slowAnimations;
914
 
 
915
 
    return true;
916
 
}
917
 
 
918
 
 
919
 
void
920
 
CompositeScreenInterface::preparePaint (int msSinceLastPaint)
921
 
    WRAPABLE_DEF (preparePaint, msSinceLastPaint)
922
 
 
923
 
void
924
 
CompositeScreenInterface::donePaint ()
925
 
    WRAPABLE_DEF (donePaint)
926
 
 
927
 
void
928
 
CompositeScreenInterface::paint (CompOutput::ptrList &outputs,
929
 
                                 unsigned int        mask)
930
 
    WRAPABLE_DEF (paint, outputs, mask)
931
 
 
932
 
CompWindowList
933
 
CompositeScreenInterface::getWindowPaintList ()
934
 
    WRAPABLE_DEF (getWindowPaintList)
935
 
 
936
 
const CompRegion &
937
 
CompositeScreen::currentDamage () const
938
 
{
939
 
    return priv->damage;
940
 
}