~vanvugt/compiz-plugins-main/fix-1084386

« back to all changes in this revision

Viewing changes to ring/src/ring.cpp

  • Committer: Sam Spilsbury
  • Date: 2011-08-12 06:36:10 UTC
  • Revision ID: sam.spilsbury@canonical.com-20110812063610-8mcxo2xohctyp2ak
Sync - Remove Plugins

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *
3
 
 * Compiz ring switcher plugin
4
 
 *
5
 
 * ring.cpp
6
 
 *
7
 
 * Copyright : (C) 2007 by Danny Baumann
8
 
 * E-mail    : maniac@opencompositing.org
9
 
 *
10
 
 * Based on scale.c and switcher.c:
11
 
 * Copyright : (C) 2007 David Reveman
12
 
 * E-mail    : davidr@novell.com
13
 
 *
14
 
 * Ported to Compiz 0.9 by:
15
 
 * Copyright : (C) 2009 Sam Spilsbury
16
 
 * E-mail    : smspillaz@gmail.com
17
 
 *
18
 
 * This program is free software; you can redistribute it and/or
19
 
 * modify it under the terms of the GNU General Public License
20
 
 * as published by the Free Software Foundation; either version 2
21
 
 * of the License, or (at your option) any later version.
22
 
 *
23
 
 * This program is distributed in the hope that it will be useful,
24
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
 
 * GNU General Public License for more details.
27
 
 *
28
 
 */
29
 
 
30
 
#include "ring.h"
31
 
 
32
 
COMPIZ_PLUGIN_20090315 (ring, RingPluginVTable);
33
 
 
34
 
bool textAvailable;
35
 
 
36
 
static void
37
 
toggleFunctions (bool enabled)
38
 
{
39
 
    RING_SCREEN (screen);
40
 
 
41
 
    rs->cScreen->preparePaintSetEnabled (rs, enabled);
42
 
    rs->cScreen->donePaintSetEnabled (rs, enabled);
43
 
    rs->gScreen->glPaintOutputSetEnabled (rs, enabled);
44
 
    screen->handleEventSetEnabled (rs, enabled);
45
 
 
46
 
    foreach (CompWindow *w, screen->windows ())
47
 
    {
48
 
        RING_WINDOW (w);
49
 
        rw->gWindow->glPaintSetEnabled (rw, enabled);
50
 
        rw->cWindow->damageRectSetEnabled (rw, enabled);
51
 
    }
52
 
}
53
 
 
54
 
void
55
 
RingScreen::switchActivateEvent (bool activating)
56
 
{
57
 
    CompOption::Vector o;
58
 
 
59
 
    CompOption o1 ("root", CompOption::TypeInt);
60
 
    o1.value ().set ((int) screen->root ());
61
 
 
62
 
    o.push_back (o1);
63
 
 
64
 
    CompOption o2 ("active", CompOption::TypeBool);
65
 
    o2.value ().set (activating);
66
 
 
67
 
    o.push_back (o2);
68
 
 
69
 
    screen->handleCompizEvent ("ring", "activate", o);
70
 
}
71
 
 
72
 
bool
73
 
RingWindow::is (bool removing)
74
 
{
75
 
    RING_SCREEN (screen);
76
 
 
77
 
    if (!removing && window->destroyed ())
78
 
        return false;
79
 
 
80
 
    if (window->overrideRedirect ())
81
 
        return false;
82
 
 
83
 
    if (window->wmType () & (CompWindowTypeDockMask | CompWindowTypeDesktopMask))
84
 
        return false;
85
 
 
86
 
    if (!removing && (!window->mapNum () || !window->isViewable ()))
87
 
    {
88
 
        if (rs->optionGetMinimized ())
89
 
        {
90
 
            if (!window->minimized () && !window->inShowDesktopMode () &&
91
 
                !window->shaded ())
92
 
                return false;
93
 
        }
94
 
        else
95
 
            return false;
96
 
    }
97
 
 
98
 
    if (!removing && rs->mType == RingScreen::RingTypeNormal)
99
 
    {
100
 
        if (!window->mapNum () || !window->isViewable ())
101
 
        {
102
 
            if (window->serverX () + window->width ()  <= 0    ||
103
 
                window->serverY () + window->height () <= 0    ||
104
 
                window->serverX () >= screen->width () ||
105
 
                window->serverY () >= screen->height ())
106
 
                return false;
107
 
        }
108
 
        else
109
 
        {
110
 
            if (!window->focus ())
111
 
                return false;
112
 
        }
113
 
    }
114
 
    else if (rs->mType == RingScreen::RingTypeGroup &&
115
 
             rs->mClientLeader != window->clientLeader () &&
116
 
             rs->mClientLeader != window->id ())
117
 
    {
118
 
        return false;
119
 
    }
120
 
 
121
 
    if (window->state () & CompWindowStateSkipTaskbarMask)
122
 
        return false;
123
 
 
124
 
    if (!rs->mCurrentMatch.evaluate (window))
125
 
        return false;
126
 
 
127
 
    return true;
128
 
}
129
 
 
130
 
void
131
 
RingScreen::freeWindowTitle ()
132
 
{
133
 
}
134
 
 
135
 
void
136
 
RingScreen::renderWindowTitle ()
137
 
{
138
 
    if (!textAvailable)
139
 
        return;
140
 
 
141
 
    CompText::Attrib attrib;
142
 
    CompRect         oe;
143
 
 
144
 
    freeWindowTitle ();
145
 
 
146
 
    if (!mSelectedWindow)
147
 
        return;
148
 
 
149
 
    if (!optionGetWindowTitle ())
150
 
        return;
151
 
 
152
 
    oe = screen->getCurrentOutputExtents ();
153
 
 
154
 
    /* 75% of the output device as maximum width */
155
 
    attrib.maxWidth = oe.width () * 3 / 4;
156
 
    attrib.maxHeight = 100;
157
 
 
158
 
    attrib.size = optionGetTitleFontSize ();
159
 
    attrib.color[0] = optionGetTitleFontColorRed ();
160
 
    attrib.color[1] = optionGetTitleFontColorGreen ();
161
 
    attrib.color[2] = optionGetTitleFontColorBlue ();
162
 
    attrib.color[3] = optionGetTitleFontColorAlpha ();
163
 
    attrib.flags = CompText::WithBackground | CompText::Ellipsized;
164
 
    if (optionGetTitleFontBold ())
165
 
        attrib.flags |= CompText::StyleBold;
166
 
    attrib.family = "Sans";
167
 
    attrib.bgHMargin = 15;
168
 
    attrib.bgVMargin = 15;
169
 
    attrib.bgColor[0] = optionGetTitleBackColorRed ();
170
 
    attrib.bgColor[1] = optionGetTitleBackColorGreen ();
171
 
    attrib.bgColor[2] = optionGetTitleBackColorBlue ();
172
 
    attrib.bgColor[3] = optionGetTitleBackColorAlpha ();
173
 
 
174
 
    mText.renderWindowTitle (mSelectedWindow->id (),
175
 
                            mType == RingScreen::RingTypeAll,
176
 
                            attrib);
177
 
}
178
 
 
179
 
void
180
 
RingScreen::drawWindowTitle ()
181
 
{
182
 
    if (!textAvailable)
183
 
        return;
184
 
    float      x, y;
185
 
    CompRect   oe;
186
 
 
187
 
    oe = screen->getCurrentOutputExtents ();
188
 
 
189
 
    x = oe.centerX () - mText.getWidth () / 2;
190
 
 
191
 
    /* assign y (for the lower corner!) according to the setting */
192
 
    switch (optionGetTitleTextPlacement ())
193
 
    {
194
 
        case RingOptions::TitleTextPlacementCenteredOnScreen:
195
 
            y = oe.centerY () + mText.getHeight () / 2;
196
 
            break;
197
 
        case RingOptions::TitleTextPlacementAboveRing:
198
 
        case RingOptions::TitleTextPlacementBelowRing:
199
 
            {
200
 
                CompRect workArea = screen->currentOutputDev ().workArea ();
201
 
 
202
 
                if (optionGetTitleTextPlacement () ==
203
 
                    RingOptions::TitleTextPlacementAboveRing)
204
 
                    y = oe.y1 () + workArea.y () + mText.getHeight ();
205
 
                else
206
 
                    y = oe.y1 () + workArea.y2 ();
207
 
            }
208
 
            break;
209
 
        default:
210
 
            return;
211
 
            break;
212
 
    }
213
 
 
214
 
    mText.draw (floor (x), floor (y), 1.0f);
215
 
}
216
 
 
217
 
bool
218
 
RingWindow::glPaint (const GLWindowPaintAttrib &attrib,
219
 
                     const GLMatrix            &transform,
220
 
                     const CompRegion          &region,
221
 
                     unsigned int              mask)
222
 
{
223
 
    bool       status;
224
 
    bool       pixmap = true;
225
 
 
226
 
    RING_SCREEN (screen);
227
 
 
228
 
    if (rs->mState != RingScreen::RingStateNone)
229
 
    {
230
 
        GLWindowPaintAttrib sAttrib = attrib;
231
 
        bool              scaled = false;
232
 
 
233
 
        if (window->mapNum ())
234
 
        {
235
 
            if (gWindow->textures ().empty ())
236
 
                gWindow->bind ();
237
 
        }
238
 
 
239
 
        if (mAdjust || mSlot)
240
 
        {
241
 
            scaled = mAdjust || (mSlot);
242
 
            mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
243
 
        }
244
 
        else if (rs->mState != RingScreen::RingStateIn)
245
 
        {
246
 
            if (rs->optionGetDarkenBack ())
247
 
            {
248
 
                /* modify brightness of the other windows */
249
 
                sAttrib.brightness = sAttrib.brightness / 2;
250
 
            }
251
 
        }
252
 
 
253
 
        status = gWindow->glPaint (sAttrib, transform, region, mask);
254
 
 
255
 
        pixmap = !gWindow->textures ().empty ();
256
 
 
257
 
        if (scaled && pixmap)
258
 
        {
259
 
            GLFragment::Attrib fragment (gWindow->lastPaintAttrib ());
260
 
            GLMatrix           wTransform = transform;
261
 
 
262
 
            if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
263
 
                return false;
264
 
 
265
 
            if (mSlot)
266
 
            {
267
 
                fragment.setBrightness((float) fragment.getBrightness () *
268
 
                                         mSlot->depthBrightness);
269
 
 
270
 
                if (window != rs->mSelectedWindow)
271
 
                    fragment.setOpacity ((float)fragment.getOpacity () *
272
 
                                         rs->optionGetInactiveOpacity () / 100);
273
 
            }
274
 
 
275
 
            if (window->alpha () || fragment.getOpacity () != OPAQUE)
276
 
                mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
277
 
 
278
 
            wTransform.translate (window->x (), window->y (), 0.0f);
279
 
            wTransform.scale (mScale, mScale, 1.0f);
280
 
            wTransform.translate (mTx / mScale - window->x (),
281
 
                                  mTy / mScale - window->y (),
282
 
                                  0.0f);
283
 
 
284
 
            glPushMatrix ();
285
 
            glLoadMatrixf (wTransform.getMatrix ());
286
 
 
287
 
            gWindow->glDraw (wTransform, fragment, region,
288
 
                             mask | PAINT_WINDOW_TRANSFORMED_MASK);
289
 
 
290
 
            glPopMatrix ();
291
 
        }
292
 
 
293
 
        if (scaled && (rs->mState != RingScreen::RingStateIn) &&
294
 
            ((rs->optionGetOverlayIcon () != RingOptions::OverlayIconNone) ||
295
 
             !pixmap))
296
 
        {
297
 
            GLTexture *icon;
298
 
 
299
 
            icon = gWindow->getIcon (256, 256);
300
 
            if (!icon)
301
 
                icon = rs->gScreen->defaultIcon ();
302
 
 
303
 
            if (icon)
304
 
            {
305
 
                GLTexture::Matrix        matrix;
306
 
                GLTexture::MatrixList    matricies;
307
 
                float                    scale;
308
 
                float                    x, y;
309
 
                int                      width, height;
310
 
                int                      scaledWinWidth, scaledWinHeight;
311
 
 
312
 
                enum RingOptions::OverlayIcon  iconOverlay;
313
 
 
314
 
                scaledWinWidth  = window->width () * mScale;
315
 
                scaledWinHeight = window->height () * mScale;
316
 
 
317
 
                if (!pixmap)
318
 
                    iconOverlay = RingOptions::OverlayIconBig;
319
 
                else
320
 
                    iconOverlay = (enum RingOptions::OverlayIcon)
321
 
                                                    rs->optionGetOverlayIcon ();
322
 
 
323
 
                switch (iconOverlay) {
324
 
                case RingOptions::OverlayIconNone:
325
 
                case RingOptions::OverlayIconEmblem:
326
 
                    scale = (mSlot) ? mSlot->depthScale : 1.0f;
327
 
                    if (icon->width () > ICON_SIZE ||
328
 
                         icon->height () > ICON_SIZE)
329
 
                        scale = MIN ((scale * ICON_SIZE / icon->width ()),
330
 
                                     (scale * ICON_SIZE / icon->height ()));
331
 
                    break;
332
 
                case RingOptions::OverlayIconBig:
333
 
                default:
334
 
                    /* only change opacity if not painting an
335
 
                       icon for a minimized window */
336
 
                    if (pixmap)
337
 
                        sAttrib.opacity /= 3;
338
 
                    scale = MIN (((float) scaledWinWidth / icon->width ()),
339
 
                                 ((float) scaledWinHeight / icon->height ()));
340
 
                    break;
341
 
                }
342
 
 
343
 
                width  = icon->width ()  * scale;
344
 
                height = icon->height () * scale;
345
 
 
346
 
                switch (iconOverlay) {
347
 
                case RingOptions::OverlayIconNone:
348
 
                case RingOptions::OverlayIconEmblem:
349
 
                    x = window->x () + scaledWinWidth - width;
350
 
                    y = window->y () + scaledWinHeight - height;
351
 
                    break;
352
 
                case RingOptions::OverlayIconBig:
353
 
                default:
354
 
                    x = window->x () + scaledWinWidth / 2 - width / 2;
355
 
                    y = window->y () + scaledWinHeight / 2 - height / 2;
356
 
                    break;
357
 
                }
358
 
 
359
 
                x += mTx;
360
 
                y += mTy;
361
 
 
362
 
                mask |= PAINT_WINDOW_BLEND_MASK;
363
 
 
364
 
                /* if we paint the icon for a minimized window, we need
365
 
                   to force the usage of a good texture filter */
366
 
                if (!pixmap)
367
 
                    mask |= PAINT_WINDOW_TRANSFORMED_MASK;
368
 
 
369
 
                CompRegion iconReg (window->x (), window->y (),
370
 
                                    icon->width (), icon->height ());
371
 
 
372
 
                matrix = icon->matrix ();
373
 
                matrix.x0 -= (window->x () * matrix.xx);
374
 
                matrix.y0 -= (window->y () * matrix.yy);
375
 
 
376
 
                matricies.push_back (matrix);
377
 
 
378
 
                gWindow->geometry ().reset ();
379
 
 
380
 
                gWindow->glAddGeometry (matricies, iconReg, iconReg);
381
 
 
382
 
                if (gWindow->geometry ().vCount)
383
 
                {
384
 
                    GLFragment::Attrib fragment (sAttrib);
385
 
                    GLMatrix           wTransform = transform;
386
 
 
387
 
                    if (!pixmap)
388
 
                        sAttrib.opacity = gWindow->paintAttrib ().opacity;
389
 
 
390
 
                    if (mSlot)
391
 
                        fragment.setBrightness (
392
 
                                        (float) fragment.getBrightness () *
393
 
                                        mSlot->depthBrightness);
394
 
 
395
 
                    wTransform.translate (window->x (), window->y (), 0.0f);
396
 
                    wTransform.scale (scale, scale, 1.0f);
397
 
                    wTransform.translate ((x - window->x ()) / scale -
398
 
                                                                window->x (),
399
 
                                          (y - window->y ()) / scale -
400
 
                                                                 window->y (),
401
 
                                          0.0f);
402
 
 
403
 
                    glPushMatrix ();
404
 
                    glLoadMatrixf (wTransform.getMatrix ());
405
 
 
406
 
                    gWindow->glDrawTexture (icon, fragment, mask);
407
 
 
408
 
                    glPopMatrix ();
409
 
                }
410
 
            }
411
 
        }
412
 
    }
413
 
    else
414
 
    {
415
 
        status = gWindow->glPaint (attrib, transform, region, mask);
416
 
    }
417
 
 
418
 
    return status;
419
 
}
420
 
 
421
 
static inline float
422
 
ringLinearInterpolation (float valX,
423
 
                         float minX, float maxX,
424
 
                         float minY, float maxY)
425
 
{
426
 
    double factor = (maxY - minY) / (maxX - minX);
427
 
    return (minY + (factor * (valX - minX)));
428
 
}
429
 
 
430
 
bool
431
 
RingWindow::compareWindows (CompWindow *w1,
432
 
                            CompWindow *w2)
433
 
{
434
 
    if (w1->mapNum () && !w2->mapNum ())
435
 
        return true;
436
 
 
437
 
    if (w2->mapNum () && !w1->mapNum ())
438
 
        return false;
439
 
 
440
 
    return (w2->activeNum () < w1->activeNum ());
441
 
}
442
 
 
443
 
bool
444
 
RingWindow::compareRingWindowDepth (RingScreen::RingDrawSlot e1,
445
 
                                    RingScreen::RingDrawSlot e2)
446
 
{
447
 
    RingScreen::RingSlot *a1   = (*(e1.slot));
448
 
    RingScreen::RingSlot *a2   = (*(e2.slot));
449
 
 
450
 
    if (a1->y < a2->y)
451
 
        return true;
452
 
    else if (a1->y > a2->y)
453
 
        return false;
454
 
    else
455
 
        return false;
456
 
}
457
 
 
458
 
bool
459
 
RingScreen::layoutThumbs ()
460
 
{
461
 
    float      baseAngle, angle;
462
 
    int        index = 0;
463
 
    int        ww, wh;
464
 
    float      xScale, yScale;
465
 
    int        centerX, centerY;
466
 
    int        ellipseA, ellipseB;
467
 
    CompRect   oe;
468
 
 
469
 
    if ((mState == RingStateNone) || (mState == RingStateIn))
470
 
        return false;
471
 
 
472
 
    baseAngle = (2 * PI * mRotTarget) / 3600;
473
 
 
474
 
    oe = screen->getCurrentOutputExtents ();
475
 
 
476
 
    /* the center of the ellipse is in the middle
477
 
       of the used output device */
478
 
    centerX  = oe.centerX ();
479
 
    centerY  = oe.centerY ();
480
 
    ellipseA = oe.width () * optionGetRingWidth () / 200;
481
 
    ellipseB = oe.height () * optionGetRingHeight () / 200;
482
 
 
483
 
    mDrawSlots.resize (mWindows.size ());
484
 
 
485
 
    foreach (CompWindow *w, mWindows)
486
 
    {
487
 
        RING_WINDOW (w);
488
 
 
489
 
        if (!rw->mSlot)
490
 
            rw->mSlot = new RingSlot ();
491
 
 
492
 
        if (!rw->mSlot)
493
 
            return false;
494
 
 
495
 
        /* we subtract the angle from the base angle
496
 
           to order the windows clockwise */
497
 
        angle = baseAngle - (index * (2 * PI / mWindows.size ()));
498
 
 
499
 
        rw->mSlot->x = centerX + (optionGetRingClockwise () ? -1 : 1) *
500
 
                                ((float) ellipseA * sin (angle));
501
 
        rw->mSlot->y = centerY + ((float) ellipseB * cos (angle));
502
 
 
503
 
        ww = w->width ()  + w->input ().left + w->input ().right;
504
 
        wh = w->height () + w->input ().top  + w->input ().bottom;
505
 
 
506
 
        if (ww > optionGetThumbWidth ())
507
 
            xScale = (float)(optionGetThumbWidth ()) / (float) ww;
508
 
        else
509
 
            xScale = 1.0f;
510
 
 
511
 
        if (wh > optionGetThumbHeight ())
512
 
            yScale = (float)(optionGetThumbHeight ()) / (float) wh;
513
 
        else
514
 
            yScale = 1.0f;
515
 
 
516
 
        rw->mSlot->scale = MIN (xScale, yScale);
517
 
 
518
 
        /* scale and brightness are obtained by doing a linear inter-
519
 
           polation - the y positions are the x values for the interpolation
520
 
           (the larger Y is, the nearer is the window), and scale/brightness
521
 
           are the y values for the interpolation */
522
 
        rw->mSlot->depthScale =
523
 
            ringLinearInterpolation (rw->mSlot->y,
524
 
                                     centerY - ellipseB, centerY + ellipseB,
525
 
                                     optionGetMinScale (), 1.0f);
526
 
 
527
 
        rw->mSlot->depthBrightness =
528
 
            ringLinearInterpolation (rw->mSlot->y,
529
 
                                     centerY - ellipseB, centerY + ellipseB,
530
 
                                     optionGetMinBrightness (), 1.0f);
531
 
 
532
 
        mDrawSlots.at (index).w    = w;
533
 
        mDrawSlots.at (index).slot = &rw->mSlot;
534
 
 
535
 
        index++;
536
 
    }
537
 
 
538
 
    /* sort the draw list so that the windows with the
539
 
       lowest Y value (the windows being farest away)
540
 
       are drawn first */
541
 
 
542
 
    sort (mDrawSlots.begin (), mDrawSlots.end (),
543
 
          RingWindow::compareRingWindowDepth); // TODO
544
 
 
545
 
    return true;
546
 
}
547
 
 
548
 
void
549
 
RingScreen::addWindowToList (CompWindow *w)
550
 
{
551
 
    mWindows.push_back (w);
552
 
}
553
 
 
554
 
bool
555
 
RingScreen::updateWindowList ()
556
 
{
557
 
    sort (mWindows.begin (), mWindows.end (), RingWindow::compareWindows);
558
 
 
559
 
    mRotTarget = 0;
560
 
    foreach (CompWindow *w, mWindows)
561
 
    {
562
 
        if (w == mSelectedWindow)
563
 
            break;
564
 
 
565
 
        mRotTarget += DIST_ROT;
566
 
    }
567
 
 
568
 
    return layoutThumbs ();
569
 
}
570
 
 
571
 
bool
572
 
RingScreen::createWindowList ()
573
 
{
574
 
    mWindows.clear ();
575
 
 
576
 
    foreach (CompWindow *w, screen->windows ())
577
 
    {
578
 
        RING_WINDOW (w);
579
 
        if (rw->is ())
580
 
        {
581
 
            addWindowToList (w);
582
 
            rw->mAdjust = true;
583
 
        }
584
 
    }
585
 
 
586
 
    return updateWindowList ();
587
 
}
588
 
 
589
 
void
590
 
RingScreen::switchToWindow (bool           toNext)
591
 
{
592
 
    CompWindow   *w; // We need w to be in this scope
593
 
    unsigned int cur = 0;
594
 
 
595
 
    if (!mGrabIndex)
596
 
        return;
597
 
 
598
 
    foreach (w, mWindows)
599
 
    {
600
 
        if (w == mSelectedWindow)
601
 
            break;
602
 
        cur++;
603
 
    }
604
 
 
605
 
    if (cur == mWindows.size ())
606
 
        return;
607
 
 
608
 
    if (toNext)
609
 
        w = mWindows.at ((cur + 1) % mWindows.size ());
610
 
    else
611
 
        w = mWindows.at ((cur + mWindows.size () - 1) % mWindows.size ());
612
 
 
613
 
    if (w)
614
 
    {
615
 
        CompWindow *old = mSelectedWindow;
616
 
 
617
 
        mSelectedWindow = w;
618
 
        if (old != w)
619
 
        {
620
 
            if (toNext)
621
 
                mRotAdjust += DIST_ROT;
622
 
            else
623
 
                mRotAdjust -= DIST_ROT;
624
 
 
625
 
            mRotateAdjust = true;
626
 
 
627
 
            cScreen->damageScreen ();
628
 
            renderWindowTitle ();
629
 
        }
630
 
    }
631
 
}
632
 
 
633
 
int
634
 
RingScreen::countWindows ()
635
 
{
636
 
    int        count = 0;
637
 
 
638
 
    foreach (CompWindow *w, screen->windows ())
639
 
    {
640
 
        RING_WINDOW (w);
641
 
 
642
 
        if (rw->is ())
643
 
            count++;
644
 
    }
645
 
 
646
 
    return count;
647
 
}
648
 
 
649
 
int
650
 
RingScreen::adjustRingRotation (float      chunk)
651
 
{
652
 
    float dx, adjust, amount;
653
 
    int   change;
654
 
 
655
 
    dx = mRotAdjust;
656
 
 
657
 
    adjust = dx * 0.15f;
658
 
    amount = fabs (dx) * 1.5f;
659
 
    if (amount < 0.2f)
660
 
        amount = 0.2f;
661
 
    else if (amount > 2.0f)
662
 
        amount = 2.0f;
663
 
 
664
 
    mRVelocity = (amount * mRVelocity + adjust) / (amount + 1.0f);
665
 
 
666
 
    if (fabs (dx) < 0.1f && fabs (mRVelocity) < 0.2f)
667
 
    {
668
 
        mRVelocity = 0.0f;
669
 
        mRotTarget += mRotAdjust;
670
 
        mRotAdjust = 0;
671
 
        return 0;
672
 
    }
673
 
 
674
 
    change = mRVelocity * chunk;
675
 
    if (!change)
676
 
    {
677
 
        if (mRVelocity)
678
 
            change = (mRotAdjust > 0) ? 1 : -1;
679
 
    }
680
 
 
681
 
    mRotAdjust -= change;
682
 
    mRotTarget += change;
683
 
 
684
 
    if (!layoutThumbs ())
685
 
        return false;
686
 
 
687
 
    return true;
688
 
}
689
 
 
690
 
int
691
 
RingWindow::adjustVelocity ()
692
 
{
693
 
    float dx, dy, ds, adjust, amount;
694
 
    float x1, y1, scale;
695
 
 
696
 
    if (mSlot)
697
 
    {
698
 
        scale = mSlot->scale * mSlot->depthScale;
699
 
        x1 = mSlot->x - (window->width () * scale) / 2;
700
 
        y1 = mSlot->y - (window->height () * scale) / 2;
701
 
    }
702
 
    else
703
 
    {
704
 
        scale = 1.0f;
705
 
        x1 = window->x ();
706
 
        y1 = window->y ();
707
 
    }
708
 
 
709
 
    dx = x1 - (window->x () + mTx);
710
 
 
711
 
    adjust = dx * 0.15f;
712
 
    amount = fabs (dx) * 1.5f;
713
 
    if (amount < 0.5f)
714
 
        amount = 0.5f;
715
 
    else if (amount > 5.0f)
716
 
        amount = 5.0f;
717
 
 
718
 
    mXVelocity = (amount * mXVelocity + adjust) / (amount + 1.0f);
719
 
 
720
 
    dy = y1 - (window->y () + mTy);
721
 
 
722
 
    adjust = dy * 0.15f;
723
 
    amount = fabs (dy) * 1.5f;
724
 
    if (amount < 0.5f)
725
 
        amount = 0.5f;
726
 
    else if (amount > 5.0f)
727
 
        amount = 5.0f;
728
 
 
729
 
    mYVelocity = (amount * mYVelocity + adjust) / (amount + 1.0f);
730
 
 
731
 
    ds = scale - mScale;
732
 
    adjust = ds * 0.1f;
733
 
    amount = fabs (ds) * 7.0f;
734
 
    if (amount < 0.01f)
735
 
        amount = 0.01f;
736
 
    else if (amount > 0.15f)
737
 
        amount = 0.15f;
738
 
 
739
 
    mScaleVelocity = (amount * mScaleVelocity + adjust) /
740
 
        (amount + 1.0f);
741
 
 
742
 
    if (fabs (dx) < 0.1f && fabs (mXVelocity) < 0.2f &&
743
 
        fabs (dy) < 0.1f && fabs (mYVelocity) < 0.2f &&
744
 
        fabs (ds) < 0.001f && fabs (mScaleVelocity) < 0.002f)
745
 
    {
746
 
        mXVelocity = mYVelocity = mScaleVelocity = 0.0f;
747
 
        mTx = x1 - window->x ();
748
 
        mTy = y1 - window->y ();
749
 
        mScale = scale;
750
 
 
751
 
        return 0;
752
 
    }
753
 
 
754
 
    return 1;
755
 
}
756
 
 
757
 
bool
758
 
RingScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
759
 
                           const GLMatrix            &transform,
760
 
                           const CompRegion          &region,
761
 
                           CompOutput                *output,
762
 
                           unsigned int              mask)
763
 
{
764
 
    bool status;
765
 
 
766
 
    if (mState != RingStateNone)
767
 
        mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
768
 
 
769
 
    //mask |= PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK;
770
 
 
771
 
    status = gScreen->glPaintOutput (attrib, transform, region, output, mask);
772
 
 
773
 
    if (mState != RingStateNone)
774
 
    {
775
 
        GLMatrix      sTransform = transform;
776
 
 
777
 
        sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
778
 
        glPushMatrix ();
779
 
        glLoadMatrixf (sTransform.getMatrix ());
780
 
 
781
 
        /* TODO: This code here should be reworked */
782
 
 
783
 
        if (mState == RingScreen::RingStateSwitching ||
784
 
            mState == RingScreen::RingStateOut)
785
 
        {
786
 
            for (std::vector <RingDrawSlot>::iterator it = mDrawSlots.begin ();
787
 
                 it != mDrawSlots.end (); it++)
788
 
            {
789
 
                CompWindow *w = (*it).w;
790
 
 
791
 
                RING_WINDOW (w);
792
 
 
793
 
                status |= rw->gWindow->glPaint (rw->gWindow->paintAttrib (),
794
 
                                           sTransform, infiniteRegion, 0);
795
 
            }
796
 
        }
797
 
 
798
 
        if (mState != RingStateIn)
799
 
            drawWindowTitle ();
800
 
 
801
 
        glPopMatrix ();
802
 
    }
803
 
 
804
 
    return status;
805
 
}
806
 
 
807
 
void
808
 
RingScreen::preparePaint (int msSinceLastPaint)
809
 
{
810
 
    if (mState != RingStateNone && (mMoreAdjust || mRotateAdjust))
811
 
    {
812
 
        int        steps;
813
 
        float      amount, chunk;
814
 
 
815
 
        amount = msSinceLastPaint * 0.05f * optionGetSpeed ();
816
 
        steps  = amount / (0.5f * optionGetTimestep ());
817
 
 
818
 
        if (!steps)
819
 
            steps = 1;
820
 
        chunk  = amount / (float) steps;
821
 
 
822
 
        while (steps--)
823
 
        {
824
 
            mRotateAdjust = adjustRingRotation (chunk);
825
 
            mMoreAdjust = false;
826
 
 
827
 
            foreach (CompWindow *w, screen->windows ())
828
 
            {
829
 
                RING_WINDOW (w);
830
 
 
831
 
                if (rw->mAdjust)
832
 
                {
833
 
                    rw->mAdjust = rw->adjustVelocity ();
834
 
 
835
 
                    mMoreAdjust |= rw->mAdjust;
836
 
 
837
 
                    rw->mTx += rw->mXVelocity * chunk;
838
 
                    rw->mTy += rw->mYVelocity * chunk;
839
 
                    rw->mScale += rw->mScaleVelocity * chunk;
840
 
                }
841
 
                else if (rw->mSlot)
842
 
                {
843
 
                    rw->mScale = rw->mSlot->scale * rw->mSlot->depthScale;
844
 
                    rw->mTx = rw->mSlot->x - w->x () -
845
 
                             (w->width () * rw->mScale) / 2;
846
 
                    rw->mTy = rw->mSlot->y - w->y () -
847
 
                             (w->height () * rw->mScale) / 2;
848
 
                }
849
 
            }
850
 
 
851
 
            if (!mMoreAdjust && !mRotateAdjust)
852
 
            {
853
 
                switchActivateEvent (false);
854
 
                break;
855
 
            }
856
 
        }
857
 
    }
858
 
 
859
 
    cScreen->preparePaint (msSinceLastPaint);
860
 
}
861
 
 
862
 
void
863
 
RingScreen::donePaint ()
864
 
{
865
 
    if (mState != RingStateNone)
866
 
    {
867
 
        if (mMoreAdjust)
868
 
        {
869
 
            cScreen->damageScreen ();
870
 
        }
871
 
        else
872
 
        {
873
 
            if (mRotateAdjust)
874
 
                cScreen->damageScreen ();
875
 
 
876
 
            if (mState == RingStateIn)
877
 
            {
878
 
                toggleFunctions (false);
879
 
                mState = RingStateNone;
880
 
            }
881
 
            else if (mState == RingStateOut)
882
 
                mState = RingStateSwitching;
883
 
        }
884
 
    }
885
 
 
886
 
    cScreen->donePaint ();
887
 
}
888
 
 
889
 
bool
890
 
RingScreen::terminate (CompAction         *action,
891
 
                       CompAction::State  state,
892
 
                       CompOption::Vector options)
893
 
{
894
 
    if (mGrabIndex)
895
 
    {
896
 
        screen->removeGrab (mGrabIndex, 0);
897
 
        mGrabIndex = 0;
898
 
    }
899
 
 
900
 
    if (mState != RingStateNone)
901
 
    {
902
 
        foreach (CompWindow *w, screen->windows ())
903
 
        {
904
 
            RING_WINDOW (w);
905
 
 
906
 
            if (rw->mSlot)
907
 
            {
908
 
                delete rw->mSlot;
909
 
                rw->mSlot = NULL;
910
 
 
911
 
                rw->mAdjust = true;
912
 
            }
913
 
        }
914
 
        mMoreAdjust = true;
915
 
        mState = RingStateIn;
916
 
        cScreen->damageScreen ();
917
 
 
918
 
        if (!(state & CompAction::StateCancel) &&
919
 
            mSelectedWindow && !mSelectedWindow->destroyed ())
920
 
        {
921
 
            screen->sendWindowActivationRequest (mSelectedWindow->id ());
922
 
        }
923
 
    }
924
 
 
925
 
    if (action)
926
 
        action->setState ( ~(CompAction::StateTermKey |
927
 
                             CompAction::StateTermButton |
928
 
                             CompAction::StateTermEdge));
929
 
 
930
 
    return false;
931
 
}
932
 
 
933
 
bool
934
 
RingScreen::initiate (CompAction         *action,
935
 
                      CompAction::State  state,
936
 
                      CompOption::Vector options)
937
 
{
938
 
    int       count;
939
 
 
940
 
    if (screen->otherGrabExist ("ring", NULL))
941
 
        return false;
942
 
 
943
 
    mCurrentMatch = optionGetWindowMatch ();
944
 
 
945
 
    mMatch = CompOption::getMatchOptionNamed (options, "match", CompMatch ());
946
 
    if (!mMatch.isEmpty ())
947
 
    {
948
 
        mCurrentMatch = mMatch;
949
 
    }
950
 
 
951
 
    count = countWindows ();
952
 
 
953
 
    if (count < 1)
954
 
    {
955
 
        return false;
956
 
    }
957
 
 
958
 
    if (!mGrabIndex)
959
 
    {
960
 
        if (optionGetSelectWithMouse ())
961
 
            mGrabIndex = screen->pushGrab (screen->normalCursor (), "ring");
962
 
        else
963
 
            mGrabIndex = screen->pushGrab (screen->invisibleCursor (), "ring");
964
 
    }
965
 
 
966
 
    if (mGrabIndex)
967
 
    {
968
 
        mState = RingScreen::RingStateOut;
969
 
 
970
 
        if (!createWindowList ())
971
 
            return false;
972
 
 
973
 
        mSelectedWindow = mWindows.front ();
974
 
        renderWindowTitle ();
975
 
        mRotTarget = 0;
976
 
 
977
 
        mMoreAdjust = true;
978
 
        toggleFunctions (true);
979
 
        cScreen->damageScreen ();
980
 
 
981
 
        switchActivateEvent (true);
982
 
    }
983
 
 
984
 
    return true;
985
 
}
986
 
 
987
 
bool
988
 
RingScreen::doSwitch (CompAction         *action,
989
 
                      CompAction::State  state,
990
 
                      CompOption::Vector options,
991
 
                      bool               nextWindow,
992
 
                      RingType           type)
993
 
{
994
 
    bool       ret = true;
995
 
 
996
 
    if ((mState == RingStateNone) || (mState == RingStateIn))
997
 
    {
998
 
        if (type == RingTypeGroup)
999
 
        {
1000
 
            CompWindow *w;
1001
 
            w = screen->findWindow (CompOption::getIntOptionNamed (options,
1002
 
                                                                   "window",
1003
 
                                                                   0));
1004
 
            if (w)
1005
 
            {
1006
 
                mType = RingTypeGroup;
1007
 
                mClientLeader =
1008
 
                    (w->clientLeader ()) ? w->clientLeader () : w->id ();
1009
 
                ret = initiate (action, state, options);
1010
 
            }
1011
 
        }
1012
 
        else
1013
 
        {
1014
 
            mType = type;
1015
 
            ret = initiate (action, mState, options);
1016
 
        }
1017
 
 
1018
 
        if (state & CompAction::StateInitKey)
1019
 
            action->setState (action->state () | CompAction::StateTermKey);
1020
 
 
1021
 
        if (state & CompAction::StateInitEdge)
1022
 
            action->setState (action->state () | CompAction::StateTermEdge);
1023
 
        else if (mState & CompAction::StateInitButton)
1024
 
            action->setState (action->state () |
1025
 
                              CompAction::StateTermButton);
1026
 
    }
1027
 
 
1028
 
    if (ret)
1029
 
        switchToWindow (nextWindow);
1030
 
 
1031
 
 
1032
 
    return ret;
1033
 
}
1034
 
 
1035
 
void
1036
 
RingScreen::windowSelectAt (int  x,
1037
 
                            int  y,
1038
 
                            bool shouldTerminate)
1039
 
{
1040
 
    CompWindow *selected = NULL;
1041
 
 
1042
 
    if (!optionGetSelectWithMouse ())
1043
 
        return;
1044
 
 
1045
 
    /* first find the top-most window the mouse
1046
 
       pointer is over */
1047
 
    foreach (CompWindow *w, mWindows)
1048
 
    {
1049
 
        RING_WINDOW (w);
1050
 
        if (rw->mSlot)
1051
 
        {
1052
 
            if ((x >= (rw->mTx + w->x ())) &&
1053
 
                (x <= (rw->mTx + w->x () + (w->width () * rw->mScale))) &&
1054
 
                (y >= (rw->mTy + w->y ())) &&
1055
 
                (y <= (rw->mTy + w->y () + (w->height () * rw->mScale))))
1056
 
            {
1057
 
                /* we have found one, select it */
1058
 
                selected = w;
1059
 
                break;
1060
 
            }
1061
 
        }
1062
 
    }
1063
 
 
1064
 
    if (selected && shouldTerminate)
1065
 
    {
1066
 
        CompOption o ("root", CompOption::TypeInt);
1067
 
        CompOption::Vector opts;
1068
 
 
1069
 
        o.value ().set ((int) screen->root ());
1070
 
 
1071
 
        opts.push_back (o);
1072
 
 
1073
 
        mSelectedWindow = selected;
1074
 
 
1075
 
        terminate (NULL, 0, opts);
1076
 
    }
1077
 
    else if (!shouldTerminate && (selected != mSelectedWindow ))
1078
 
    {
1079
 
        if (!selected)
1080
 
        {
1081
 
            freeWindowTitle ();
1082
 
        }
1083
 
        else
1084
 
        {
1085
 
            mSelectedWindow = selected;
1086
 
            renderWindowTitle ();
1087
 
        }
1088
 
        cScreen->damageScreen ();
1089
 
    }
1090
 
}
1091
 
 
1092
 
void
1093
 
RingScreen::windowRemove (CompWindow *w)
1094
 
{
1095
 
    if (w)
1096
 
    {
1097
 
        bool   inList = false;
1098
 
        CompWindow *selected;
1099
 
        CompWindowVector::iterator it = mWindows.begin ();
1100
 
 
1101
 
        RING_WINDOW (w);
1102
 
 
1103
 
        if (mState == RingStateNone)
1104
 
            return;
1105
 
 
1106
 
        if (!rw->is (true))
1107
 
            return;
1108
 
 
1109
 
        selected = mSelectedWindow;
1110
 
 
1111
 
        while (it != mWindows.end ())
1112
 
        {
1113
 
            if (*it == w)
1114
 
            {
1115
 
                inList = true;
1116
 
 
1117
 
                if (w == selected)
1118
 
                {
1119
 
                    it++;
1120
 
                    if (it != mWindows.end ())
1121
 
                        selected = *it;
1122
 
                    else
1123
 
                        selected = mWindows.front ();
1124
 
                    it--;
1125
 
 
1126
 
                    mSelectedWindow = selected;
1127
 
                    renderWindowTitle ();
1128
 
                }
1129
 
 
1130
 
                mWindows.erase (it);
1131
 
                break;
1132
 
            }
1133
 
            it++;
1134
 
        }
1135
 
 
1136
 
        if (!inList)
1137
 
            return;
1138
 
 
1139
 
        /* Terminate if the window closed was the last window in the list */
1140
 
 
1141
 
        if (!mWindows.size ())
1142
 
        {
1143
 
            CompOption o ("root", CompOption::TypeInt);
1144
 
            CompOption::Vector opts;
1145
 
 
1146
 
            o.value ().set ((int) screen->root ());
1147
 
 
1148
 
            opts.push_back (o);
1149
 
 
1150
 
            terminate (NULL, 0, opts);
1151
 
            return;
1152
 
        }
1153
 
 
1154
 
        // Let the window list be updated to avoid crash
1155
 
        // when a window is closed while ending (RingStateIn).
1156
 
        if (!mGrabIndex && mState != RingStateIn)
1157
 
            return;
1158
 
 
1159
 
        if (updateWindowList ())
1160
 
        {
1161
 
            mMoreAdjust = true;
1162
 
            mState = RingStateOut;
1163
 
            cScreen->damageScreen ();
1164
 
        }
1165
 
    }
1166
 
}
1167
 
 
1168
 
void
1169
 
RingScreen::handleEvent (XEvent *event)
1170
 
{
1171
 
    CompWindow *w = NULL;
1172
 
 
1173
 
    switch (event->type) {
1174
 
    case DestroyNotify:
1175
 
        /* We need to get the CompWindow * for event->xdestroywindow.window
1176
 
           here because in the ::screen->handleEvent call below, that
1177
 
           CompWindow's id will become 1, so findWindow won't be
1178
 
           able to find the CompWindow after that. */
1179
 
           w = ::screen->findWindow (event->xdestroywindow.window);
1180
 
        break;
1181
 
    default:
1182
 
        break;
1183
 
    }
1184
 
 
1185
 
    screen->handleEvent (event);
1186
 
 
1187
 
    switch (event->type) {
1188
 
    case PropertyNotify:
1189
 
        if (event->xproperty.atom == XA_WM_NAME)
1190
 
        {
1191
 
            w = screen->findWindow (event->xproperty.window);
1192
 
            if (w)
1193
 
            {
1194
 
                if (mGrabIndex && (w == mSelectedWindow))
1195
 
                {
1196
 
                    renderWindowTitle ();
1197
 
                    cScreen->damageScreen ();
1198
 
                }
1199
 
            }
1200
 
        }
1201
 
        break;
1202
 
    case ButtonPress:
1203
 
        if (event->xbutton.button == Button1)
1204
 
        {
1205
 
            if (mGrabIndex)
1206
 
                windowSelectAt (event->xbutton.x_root,
1207
 
                                event->xbutton.y_root,
1208
 
                                true);
1209
 
        }
1210
 
        break;
1211
 
    case MotionNotify:
1212
 
        if (mGrabIndex)
1213
 
            windowSelectAt (event->xmotion.x_root,
1214
 
                            event->xmotion.y_root,
1215
 
                            false);
1216
 
    case UnmapNotify:
1217
 
        w = ::screen->findWindow (event->xunmap.window);
1218
 
        windowRemove (w);
1219
 
        break;
1220
 
    case DestroyNotify:
1221
 
        windowRemove (w);
1222
 
        break;
1223
 
    }
1224
 
}
1225
 
 
1226
 
bool
1227
 
RingWindow::damageRect (bool     initial,
1228
 
                        const CompRect &rect)
1229
 
{
1230
 
    bool       status = false;
1231
 
 
1232
 
    RING_SCREEN (screen);
1233
 
 
1234
 
    if (initial)
1235
 
    {
1236
 
        if (rs->mGrabIndex && is ())
1237
 
        {
1238
 
            rs->addWindowToList (window);
1239
 
            if (rs->updateWindowList ())
1240
 
            {
1241
 
                mAdjust = true;
1242
 
                rs->mMoreAdjust = true;
1243
 
                rs->mState = RingScreen::RingStateOut;
1244
 
                rs->cScreen->damageScreen ();
1245
 
            }
1246
 
        }
1247
 
    }
1248
 
    else if (rs->mState == RingScreen::RingStateSwitching)
1249
 
    {
1250
 
 
1251
 
        if (mSlot)
1252
 
        {
1253
 
            cWindow->damageTransformedRect (mScale, mScale,
1254
 
                                            mTx, mTy,
1255
 
                                            rect);
1256
 
            status = true;
1257
 
        }
1258
 
 
1259
 
    }
1260
 
 
1261
 
    status |= cWindow->damageRect (initial, rect);
1262
 
 
1263
 
    return status;
1264
 
}
1265
 
 
1266
 
RingScreen::RingScreen (CompScreen *screen) :
1267
 
    PluginClassHandler <RingScreen, CompScreen> (screen),
1268
 
    cScreen (CompositeScreen::get (screen)),
1269
 
    gScreen (GLScreen::get (screen)),
1270
 
    mGrabIndex (0),
1271
 
    mState (RingScreen::RingStateNone),
1272
 
    mMoreAdjust (false),
1273
 
    mRotateAdjust (false),
1274
 
    mRotAdjust (0),
1275
 
    mRVelocity (0.0f),
1276
 
    mSelectedWindow (NULL)
1277
 
{
1278
 
 
1279
 
    ScreenInterface::setHandler (screen, false);
1280
 
    CompositeScreenInterface::setHandler (cScreen, false);
1281
 
    GLScreenInterface::setHandler (gScreen, false);
1282
 
 
1283
 
#define RINGTERMBIND(opt, func)                                \
1284
 
    optionSet##opt##Terminate (boost::bind (&RingScreen::func, \
1285
 
                                            this, _1, _2, _3));
1286
 
 
1287
 
#define RINGSWITCHBIND(opt, func, next, type)                 \
1288
 
    optionSet##opt##Initiate (boost::bind (&RingScreen::func, \
1289
 
                                            this, _1, _2, _3, \
1290
 
                                            next, type));
1291
 
 
1292
 
    RINGSWITCHBIND (NextKey, doSwitch, true, RingTypeNormal);
1293
 
    RINGSWITCHBIND (PrevKey, doSwitch, false, RingTypeNormal);
1294
 
    RINGSWITCHBIND (NextAllKey, doSwitch, true, RingTypeAll);
1295
 
    RINGSWITCHBIND (PrevAllKey, doSwitch, false, RingTypeAll);
1296
 
    RINGSWITCHBIND (NextGroupKey, doSwitch, true, RingTypeGroup);
1297
 
    RINGSWITCHBIND (PrevGroupKey, doSwitch, false, RingTypeGroup);
1298
 
 
1299
 
    RINGTERMBIND (NextKey, terminate);
1300
 
    RINGTERMBIND (PrevKey, terminate);
1301
 
    RINGTERMBIND (NextAllKey, terminate);
1302
 
    RINGTERMBIND (PrevAllKey, terminate);
1303
 
    RINGTERMBIND (NextGroupKey, terminate);
1304
 
    RINGTERMBIND (PrevGroupKey, terminate);
1305
 
 
1306
 
    RINGSWITCHBIND (NextButton, doSwitch, true, RingTypeNormal);
1307
 
    RINGSWITCHBIND (PrevButton, doSwitch, false, RingTypeNormal);
1308
 
    RINGSWITCHBIND (NextAllButton, doSwitch, true, RingTypeAll);
1309
 
    RINGSWITCHBIND (PrevAllButton, doSwitch, false, RingTypeAll);
1310
 
    RINGSWITCHBIND (NextGroupButton, doSwitch, true, RingTypeGroup);
1311
 
    RINGSWITCHBIND (PrevGroupButton, doSwitch, false, RingTypeGroup);
1312
 
 
1313
 
    RINGTERMBIND (NextButton, terminate);
1314
 
    RINGTERMBIND (PrevButton, terminate);
1315
 
    RINGTERMBIND (NextAllButton, terminate);
1316
 
    RINGTERMBIND (PrevAllButton, terminate);
1317
 
    RINGTERMBIND (NextGroupButton, terminate);
1318
 
    RINGTERMBIND (PrevGroupButton, terminate);
1319
 
}
1320
 
 
1321
 
 
1322
 
RingScreen::~RingScreen ()
1323
 
{
1324
 
    mWindows.clear ();
1325
 
    mDrawSlots.clear ();
1326
 
}
1327
 
 
1328
 
RingWindow::RingWindow (CompWindow *window) :
1329
 
    PluginClassHandler <RingWindow, CompWindow> (window),
1330
 
    window (window),
1331
 
    cWindow (CompositeWindow::get (window)),
1332
 
    gWindow (GLWindow::get (window)),
1333
 
    mSlot (NULL),
1334
 
    mXVelocity (0.0f),
1335
 
    mYVelocity (0.0f),
1336
 
    mScaleVelocity (0.0f),
1337
 
    mTx (0.0f),
1338
 
    mTy (0.0f),
1339
 
    mScale (1.0f),
1340
 
    mAdjust (false)
1341
 
{
1342
 
    CompositeWindowInterface::setHandler (cWindow, false);
1343
 
    GLWindowInterface::setHandler (gWindow, false);
1344
 
}
1345
 
 
1346
 
RingWindow::~RingWindow ()
1347
 
{
1348
 
    if (mSlot)
1349
 
        delete mSlot;
1350
 
}
1351
 
 
1352
 
bool
1353
 
RingPluginVTable::init ()
1354
 
{
1355
 
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) ||
1356
 
        !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) ||
1357
 
        !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
1358
 
        return false;
1359
 
 
1360
 
    if (!CompPlugin::checkPluginABI ("text", COMPIZ_TEXT_ABI))
1361
 
    {
1362
 
        compLogMessage ("ring", CompLogLevelWarn, "No compatible text plugin"\
1363
 
                                                  " loaded");
1364
 
        textAvailable = false;
1365
 
    }
1366
 
    else
1367
 
        textAvailable = true;
1368
 
 
1369
 
    return true;
1370
 
}