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

« back to all changes in this revision

Viewing changes to shift/src/shift.cpp

  • Committer: Sam Spilsbury
  • Date: 2011-08-12 06:41:38 UTC
  • Revision ID: sam.spilsbury@canonical.com-20110812064138-sg45sswip9zgk0og
Sync in changes from upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 * Compiz shift switcher plugin
 
4
 *
 
5
 * shift.cpp
 
6
 *
 
7
 * Copyright : (C) 2007 by Dennis Kasprzyk
 
8
 * E-mail    : onestone@opencompositing.org
 
9
 *
 
10
 *
 
11
 * Based on ring.c:
 
12
 * Copyright : (C) 2007 by Danny Baumann
 
13
 * E-mail    : maniac@opencompositing.org
 
14
 *
 
15
 * Based on scale.c and switcher.c:
 
16
 * Copyright : (C) 2007 David Reveman
 
17
 * E-mail    : davidr@novell.com
 
18
 *
 
19
 * Rounded corner drawing taken from wall.c:
 
20
 * Copyright : (C) 2007 Robert Carr
 
21
 * E-mail    : racarr@beryl-project.org
 
22
 *
 
23
 * This program is free software; you can redistribute it and/or
 
24
 * modify it under the terms of the GNU General Public License
 
25
 * as published by the Free Software Foundation; either version 2
 
26
 * of the License, or (at your option) any later version.
 
27
 *
 
28
 * This program is distributed in the hope that it will be useful,
 
29
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
30
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
31
 * GNU General Public License for more details.
 
32
 *
 
33
 */
 
34
 
 
35
 
 
36
#include "shift.h"
 
37
 
 
38
COMPIZ_PLUGIN_20090315 (shift, ShiftPluginVTable);
 
39
 
 
40
bool textAvailable = false;
 
41
 
 
42
void
 
43
setFunctions (bool enabled)
 
44
{
 
45
    SHIFT_SCREEN (screen);
 
46
 
 
47
    screen->handleEventSetEnabled (ss, enabled);
 
48
    ss->cScreen->preparePaintSetEnabled (ss, enabled);
 
49
    ss->cScreen->paintSetEnabled (ss, enabled);
 
50
    ss->gScreen->glPaintOutputSetEnabled (ss, enabled);
 
51
    ss->cScreen->donePaintSetEnabled (ss, enabled);
 
52
 
 
53
    foreach (CompWindow *w, screen->windows ())
 
54
    {
 
55
        SHIFT_WINDOW (w);
 
56
 
 
57
        sw->gWindow->glPaintSetEnabled (sw, enabled);
 
58
        sw->cWindow->damageRectSetEnabled (sw, enabled);
 
59
    }
 
60
}
 
61
 
 
62
void
 
63
ShiftScreen::activateEvent (bool        activating)
 
64
{
 
65
    CompOption::Vector o;
 
66
 
 
67
    o.resize (2);
 
68
 
 
69
    o[0] = CompOption ("root", CompOption::TypeInt);
 
70
    o[0].value ().set ((int) screen->root ());
 
71
 
 
72
    o[1] = CompOption ("active", CompOption::TypeBool);
 
73
    o[1].value ().set (activating);
 
74
 
 
75
    screen->handleCompizEvent ("shift", "activate", o);
 
76
}
 
77
 
 
78
bool
 
79
ShiftWindow::isShiftable ()
 
80
{
 
81
    SHIFT_SCREEN (screen);
 
82
 
 
83
    if (window->overrideRedirect ())
 
84
        return false;
 
85
 
 
86
    if (window->wmType () & (CompWindowTypeDockMask | CompWindowTypeDesktopMask))
 
87
        return false;
 
88
 
 
89
    if (!window->mapNum () || !window->isViewable ())
 
90
    {
 
91
        if (ss->optionGetMinimized ())
 
92
        {
 
93
            if (!window->minimized () && !window->inShowDesktopMode () && !window->shaded ())
 
94
                return false;
 
95
        }
 
96
        else
 
97
            return false;
 
98
    }
 
99
 
 
100
    if (ss->mType == ShiftTypeNormal)
 
101
    {
 
102
        if (!window->mapNum () || !window->isViewable ())
 
103
        {
 
104
            if (window->serverGeometry ().x () + window->serverGeometry ().width () <= 0    ||
 
105
                window->serverGeometry ().y () + window->serverGeometry ().height () <= 0    ||
 
106
                window->serverGeometry ().x () >= screen->width () ||
 
107
                window->serverGeometry ().y () >= screen->height ())
 
108
                return false;
 
109
        }
 
110
        else
 
111
        {
 
112
            if (!window->focus ())
 
113
                return false;
 
114
        }
 
115
    }
 
116
    else if (ss->mType == ShiftTypeGroup &&
 
117
             ss->mClientLeader != window->clientLeader () &&
 
118
             ss->mClientLeader != window->id ())
 
119
    {
 
120
        return false;
 
121
    }
 
122
 
 
123
    if (window->state () & CompWindowStateSkipTaskbarMask)
 
124
        return false;
 
125
 
 
126
    if (ss->mCurrentMatch && !ss->mCurrentMatch->evaluate (window))
 
127
        return false;
 
128
 
 
129
    return true;
 
130
}
 
131
 
 
132
void
 
133
ShiftScreen::freeWindowTitle ()
 
134
{
 
135
}
 
136
 
 
137
void
 
138
ShiftScreen::renderWindowTitle ()
 
139
{
 
140
    CompText::Attrib tA;
 
141
    CompRect         oe;
 
142
 
 
143
    freeWindowTitle ();
 
144
 
 
145
    if (!textAvailable)
 
146
        return;
 
147
 
 
148
    if (!optionGetWindowTitle ())
 
149
        return;
 
150
 
 
151
    if (optionGetMultioutputMode () ==
 
152
                                    ShiftOptions::MultioutputModeOneBigSwitcher)
 
153
    {
 
154
        oe.setGeometry (0, 0, screen->width (), screen->height ());
 
155
    }
 
156
    else
 
157
        oe = screen->getCurrentOutputExtents ();
 
158
 
 
159
    /* 75% of the output device as maximum width */
 
160
    tA.maxWidth = oe.width () * 3 / 4;
 
161
    tA.maxHeight = 100;
 
162
 
 
163
    tA.family = "Sans";
 
164
    tA.size = optionGetTitleFontSize ();
 
165
    tA.color[0] = optionGetTitleFontColorRed ();
 
166
    tA.color[1] = optionGetTitleFontColorGreen ();
 
167
    tA.color[2] = optionGetTitleFontColorBlue ();
 
168
    tA.color[3] = optionGetTitleFontColorAlpha ();
 
169
 
 
170
    tA.flags = CompText::WithBackground | CompText::Ellipsized;
 
171
    if (optionGetTitleFontBold ())
 
172
        tA.flags |= CompText::StyleBold;
 
173
 
 
174
    tA.bgHMargin = 15;
 
175
    tA.bgVMargin = 15;
 
176
    tA.bgColor[0] = optionGetTitleBackColorRed ();
 
177
    tA.bgColor[1] = optionGetTitleBackColorGreen ();
 
178
    tA.bgColor[2] = optionGetTitleBackColorBlue ();
 
179
    tA.bgColor[3] = optionGetTitleBackColorAlpha ();
 
180
 
 
181
    text.renderWindowTitle (mSelectedWindow ? mSelectedWindow : None,
 
182
                            mType == ShiftTypeAll, tA);
 
183
}
 
184
 
 
185
void
 
186
ShiftScreen::drawWindowTitle ()
 
187
{
 
188
    float width, height, border = 10.0f;
 
189
    CompRect oe;
 
190
 
 
191
    width = text.getWidth ();
 
192
    height = text.getHeight ();
 
193
 
 
194
    if (optionGetMultioutputMode () == MultioutputModeOneBigSwitcher)
 
195
    {
 
196
        oe.setGeometry (0, 0, screen->width (), screen->height ());
 
197
    }
 
198
    else
 
199
    {
 
200
        oe = (CompRect) screen->outputDevs ()[mUsedOutput];
 
201
    }
 
202
 
 
203
    float x = oe.centerX () - width / 2;
 
204
    float y;
 
205
 
 
206
    /* assign y (for the lower corner!) according to the setting */
 
207
    switch (optionGetTitleTextPlacement ())
 
208
    {
 
209
    case TitleTextPlacementCenteredOnScreen:
 
210
        y = oe.centerY () + height / 2;
 
211
        break;
 
212
    case TitleTextPlacementAbove:
 
213
    case TitleTextPlacementBelow:
 
214
        {
 
215
            CompRect workArea = screen->currentOutputDev ().workArea ();
 
216
 
 
217
            if (optionGetTitleTextPlacement () ==
 
218
                TitleTextPlacementAbove)
 
219
                y = oe.y1 () + workArea.y1 () + 2 * border + height;
 
220
            else
 
221
                y = oe.y1 () + workArea.y2 () - 2 * border;
 
222
        }
 
223
        break;
 
224
    default:
 
225
        return;
 
226
    }
 
227
 
 
228
    text.draw (floor (x), floor (y), 1.0f);
 
229
}
 
230
 
 
231
bool
 
232
ShiftWindow::glPaint (const GLWindowPaintAttrib &attrib,
 
233
                      const GLMatrix            &transform,
 
234
                      const CompRegion          &region,
 
235
                      unsigned int              mask)
 
236
{
 
237
    bool       status;
 
238
 
 
239
    SHIFT_SCREEN (screen);
 
240
    if (ss->mState != ShiftStateNone && !ss->mPaintingAbove &&
 
241
        !(window->wmType () & (CompWindowTypeDesktopMask |
 
242
                               CompWindowTypeDockMask)))
 
243
    {
 
244
        GLWindowPaintAttrib sAttrib = attrib;
 
245
        bool              scaled = false;
 
246
 
 
247
        if (window->mapNum ())
 
248
        {
 
249
            if (gWindow->textures ().empty ())
 
250
                gWindow->bind ();
 
251
        }
 
252
 
 
253
 
 
254
        if (mActive)
 
255
            scaled = (ss->mActiveSlot != NULL);
 
256
 
 
257
        if (mOpacity > 0.01 && (ss->mActiveSlot == NULL))
 
258
        {
 
259
            sAttrib.brightness = sAttrib.brightness * mBrightness;
 
260
            sAttrib.opacity = sAttrib.opacity * mOpacity;
 
261
        }
 
262
        else
 
263
            mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
 
264
 
 
265
        if (mActive &&
 
266
            ((unsigned int) ss->mOutput->id () == (unsigned int) ss->mUsedOutput ||
 
267
             (unsigned int) ss->mOutput->id () == (unsigned int) ~0))
 
268
            mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
 
269
 
 
270
 
 
271
        status = gWindow->glPaint (sAttrib, transform, region, mask);
 
272
 
 
273
        if (scaled && !gWindow->textures ().empty ())
 
274
        {
 
275
            GLFragment::Attrib fragment (attrib);
 
276
            GLMatrix wTransform = transform;
 
277
            ShiftSlot      *slot = ss->mActiveSlot->slot;
 
278
 
 
279
            float sx     = ss->mAnim * slot->tx;
 
280
            float sy     = ss->mAnim * slot->ty;
 
281
            float sz     = ss->mAnim * slot->z;
 
282
            float srot   = (ss->mAnim * slot->rotation);
 
283
            float anim   = MIN (1.0, MAX (0.0, ss->mAnim));
 
284
 
 
285
            float sscale;
 
286
            float sopacity;
 
287
 
 
288
 
 
289
            if (slot->primary)
 
290
                sscale = (ss->mAnim * slot->scale) + (1 - ss->mAnim);
 
291
            else
 
292
                sscale = ss->mAnim * slot->scale;
 
293
 
 
294
            if (slot->primary && !ss->mReflectActive)
 
295
                sopacity = (ss->mAnim * slot->opacity) + (1 - ss->mAnim);
 
296
            else
 
297
                sopacity = anim * anim * slot->opacity;
 
298
 
 
299
            if (sopacity <= 0.05)
 
300
                return status;
 
301
 
 
302
            /*if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
 
303
                return false;*/
 
304
 
 
305
            fragment.setOpacity ((float)fragment.getOpacity () * sopacity);
 
306
            fragment.setBrightness ((float)fragment.getBrightness () *
 
307
                                    ss->mReflectBrightness);
 
308
 
 
309
            if (window->alpha () || fragment.getOpacity () != OPAQUE)
 
310
                mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
 
311
 
 
312
            wTransform.translate (sx, sy, sz);
 
313
 
 
314
            wTransform.translate (window->x () + (window->width ()  * sscale / 2),
 
315
                                  window->y () + (window->height ()  * sscale / 2.0),
 
316
                                  0.0f);
 
317
 
 
318
            wTransform.scale (ss->mOutput->width (), -ss->mOutput->height (),
 
319
                         1.0f);
 
320
 
 
321
            wTransform.rotate (srot, 0.0, 1.0, 0.0);
 
322
 
 
323
            wTransform.scale (1.0f  / ss->mOutput->width (),
 
324
                         -1.0f / ss->mOutput->height (), 1.0f);
 
325
 
 
326
            wTransform.scale (sscale, sscale, 1.0f);
 
327
            wTransform.translate (-window->x () - (window->width () / 2),
 
328
                                  -window->y () - (window->height () / 2), 0.0f);
 
329
 
 
330
            glPushMatrix ();
 
331
            glLoadMatrixf (wTransform.getMatrix ());
 
332
 
 
333
            gWindow->glDraw (wTransform, fragment, region,
 
334
                              mask | PAINT_WINDOW_TRANSFORMED_MASK);
 
335
 
 
336
            glPopMatrix ();
 
337
        }
 
338
 
 
339
        if (scaled && ((ss->optionGetOverlayIcon () != ShiftOptions::OverlayIconNone) ||
 
340
             gWindow->textures ().empty ()))
 
341
        {
 
342
            GLTexture *icon;
 
343
 
 
344
            icon = gWindow->getIcon (96, 96);
 
345
            if (!icon)
 
346
                icon = ss->gScreen->defaultIcon ();
 
347
 
 
348
            if (icon && (icon->name ()))
 
349
            {
 
350
                CompRegion iconReg;
 
351
                float  scale;
 
352
                float  x, y;
 
353
                int    width, height;
 
354
                int    scaledWinWidth, scaledWinHeight;
 
355
                int iconOverlay = ss->optionGetOverlayIcon ();
 
356
                ShiftSlot      *slot = ss->mActiveSlot->slot;
 
357
                GLTexture::MatrixList matl;
 
358
 
 
359
                float sx       = ss->mAnim * slot->tx;
 
360
                float sy       = ss->mAnim * slot->ty;
 
361
                float sz       = ss->mAnim * slot->z;
 
362
                float srot     = (ss->mAnim * slot->rotation);
 
363
                float sopacity = ss->mAnim * slot->opacity;
 
364
 
 
365
                float sscale;
 
366
 
 
367
                if (slot->primary)
 
368
                    sscale = (ss->mAnim * slot->scale) + (1 - ss->mAnim);
 
369
                else
 
370
                    sscale = ss->mAnim * ss->mAnim * slot->scale;
 
371
 
 
372
                scaledWinWidth  = window->width ()  * sscale;
 
373
                scaledWinHeight = window->height () * sscale;
 
374
 
 
375
                if (gWindow->textures ().empty ())
 
376
                    iconOverlay = ShiftOptions::OverlayIconBig;
 
377
 
 
378
                switch (iconOverlay)
 
379
                {
 
380
                    case ShiftOptions::OverlayIconNone:
 
381
                    case ShiftOptions::OverlayIconEmblem:
 
382
                        scale = 1.0f;
 
383
                        break;
 
384
                    case ShiftOptions::OverlayIconBig:
 
385
                    default:
 
386
                        /* only change opacity if not painting an
 
387
                        icon for a minimized window */
 
388
                        if (!gWindow->textures ().empty ())
 
389
                            sAttrib.opacity /= 3;
 
390
                        scale = MIN (((float) scaledWinWidth / icon->width ()),
 
391
                                    ((float) scaledWinHeight / icon->height ()));
 
392
                        break;
 
393
                }
 
394
 
 
395
                width  = icon->width ()  * scale;
 
396
                height = icon->height () * scale;
 
397
 
 
398
                switch (iconOverlay)
 
399
                {
 
400
                    case ShiftOptions::OverlayIconNone:
 
401
                    case ShiftOptions::OverlayIconEmblem:
 
402
                        x = scaledWinWidth - width;
 
403
                        y = scaledWinHeight - height;
 
404
                    break;
 
405
                    case ShiftOptions::OverlayIconBig:
 
406
                    default:
 
407
                        x = scaledWinWidth / 2 - width / 2;
 
408
                        y = scaledWinHeight / 2 - height / 2;
 
409
                        break;
 
410
                }
 
411
 
 
412
                mask |= PAINT_WINDOW_BLEND_MASK;
 
413
 
 
414
                /* if we paint the icon for a minimized window, we need
 
415
                   to force the usage of a good texture filter */
 
416
                if (gWindow->textures ().empty ())
 
417
                    mask |= PAINT_WINDOW_TRANSFORMED_MASK;
 
418
 
 
419
                iconReg = CompRegion (0, 0, icon->width (), icon->height ());
 
420
 
 
421
                gWindow->geometry ().reset ();
 
422
 
 
423
                matl.push_back (icon->matrix ());
 
424
 
 
425
                gWindow->glAddGeometry (matl, iconReg, iconReg);
 
426
 
 
427
                if (gWindow->geometry ().vCount)
 
428
                {
 
429
                    GLFragment::Attrib  fragment (sAttrib);
 
430
                    GLMatrix            wTransform (transform);
 
431
 
 
432
                    if (gWindow->textures ().empty ())
 
433
                        sAttrib.opacity = gWindow->paintAttrib ().opacity;
 
434
 
 
435
                    fragment = GLFragment::Attrib (sAttrib);
 
436
 
 
437
                    fragment.setOpacity  ((float)fragment.getOpacity () * sopacity);
 
438
                    fragment.setBrightness ((float)fragment.getBrightness () *
 
439
                                            ss->mReflectBrightness);
 
440
 
 
441
                    wTransform.translate (sx, sy, sz);
 
442
 
 
443
                    wTransform.translate (window->x () +
 
444
                                     (window->width ()  * sscale / 2),
 
445
                                     window->y () +
 
446
                                     (window->height ()  * sscale / 2.0), 0.0f);
 
447
 
 
448
                    wTransform.scale (ss->mOutput->width (),
 
449
                                      -ss->mOutput->height (), 1.0f);
 
450
 
 
451
                    wTransform.rotate (srot, 0.0, 1.0, 0.0);
 
452
 
 
453
                    wTransform.scale (1.0f  / ss->mOutput->width (),
 
454
                                 -1.0f / ss->mOutput->height (), 1.0f);
 
455
 
 
456
                    wTransform.translate (x -
 
457
                                          (window->width () * sscale / 2), y -
 
458
                                          (window->height () * sscale / 2.0), 0.0f);
 
459
                    wTransform.scale (scale, scale, 1.0f);
 
460
 
 
461
                    glPushMatrix ();
 
462
                    glLoadMatrixf (wTransform.getMatrix ());
 
463
 
 
464
                    gWindow->glDrawTexture (icon, fragment, mask);
 
465
 
 
466
                    glPopMatrix ();
 
467
                }
 
468
            }
 
469
        }
 
470
 
 
471
    }
 
472
    else
 
473
    {
 
474
        GLWindowPaintAttrib sAttrib = attrib;
 
475
 
 
476
        if (ss->mPaintingAbove)
 
477
        {
 
478
            sAttrib.opacity = sAttrib.opacity * (1.0 - ss->mAnim);
 
479
 
 
480
            if (ss->mAnim > 0.99)
 
481
                mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
 
482
        }
 
483
 
 
484
        status = gWindow->glPaint (sAttrib, transform, region, mask);
 
485
    }
 
486
 
 
487
    return status;
 
488
}
 
489
 
 
490
static int
 
491
compareWindows (const void *elem1,
 
492
                const void *elem2)
 
493
{
 
494
    CompWindow *w1 = *((CompWindow **) elem1);
 
495
    CompWindow *w2 = *((CompWindow **) elem2);
 
496
    CompWindow *w  = w1;
 
497
 
 
498
    if (w1 == w2)
 
499
        return 0;
 
500
 
 
501
    if (!w1->shaded () && !w1->isViewable () &&
 
502
        (w2->shaded () || w2->isViewable ()))
 
503
    {
 
504
        return 1;
 
505
    }
 
506
 
 
507
    if (!w2->shaded () && !w2->isViewable () &&
 
508
        (w1->shaded () || w1->isViewable ()))
 
509
    {
 
510
        return -1;
 
511
    }
 
512
 
 
513
    while (w)
 
514
    {
 
515
        if (w == w2)
 
516
            return 1;
 
517
        w = w->next;
 
518
    }
 
519
    return -1;
 
520
}
 
521
 
 
522
static int
 
523
compareShiftWindowDistance (const void *elem1,
 
524
                            const void *elem2)
 
525
{
 
526
    float a1   = ((ShiftDrawSlot *) elem1)->distance;
 
527
    float a2   = ((ShiftDrawSlot *) elem2)->distance;
 
528
    float ab   = fabs (a1 - a2);
 
529
 
 
530
    if (ab > 0.3 && a1 > a2)
 
531
        return -1;
 
532
    else if (ab > 0.3 && a1 < a2)
 
533
        return 1;
 
534
    else
 
535
        return compareWindows (&((ShiftDrawSlot *) elem2)->w,
 
536
                               &((ShiftDrawSlot *) elem1)->w);
 
537
}
 
538
 
 
539
bool
 
540
ShiftScreen::layoutThumbsCover ()
 
541
{
 
542
    CompWindow *w;
 
543
    int index;
 
544
    int ww, wh;
 
545
    float xScale, yScale;
 
546
    float distance;
 
547
    int i;
 
548
 
 
549
    CompRect oe;
 
550
 
 
551
    if (optionGetMultioutputMode () ==
 
552
        ShiftScreen::MultioutputModeOneBigSwitcher)
 
553
    {
 
554
        oe.setGeometry (0, 0, screen->width (), screen->height ());
 
555
    }
 
556
    else
 
557
    {
 
558
        oe = screen->outputDevs ()[mUsedOutput];
 
559
    }
 
560
 
 
561
    /* the center of the ellipse is in the middle
 
562
       of the used output device */
 
563
    int centerX = oe.centerX ();
 
564
    int centerY = oe.centerY ();
 
565
 
 
566
    int maxThumbWidth  = oe.width () * optionGetSize () / 100;
 
567
    int maxThumbHeight = oe.height () * optionGetSize () / 100;
 
568
 
 
569
    for (index = 0; index < mNWindows; index++)
 
570
    {
 
571
        w = mWindows[index];
 
572
        SHIFT_WINDOW (w);
 
573
 
 
574
        ww = w->width ()  + w->border ().left + w->border ().right;
 
575
        wh = w->height () + w->border ().top  + w->border ().bottom;
 
576
 
 
577
        if (ww > maxThumbWidth)
 
578
            xScale = (float)(maxThumbWidth) / (float)ww;
 
579
        else
 
580
            xScale = 1.0f;
 
581
 
 
582
        if (wh > maxThumbHeight)
 
583
            yScale = (float)(maxThumbHeight) / (float)wh;
 
584
        else
 
585
            yScale = 1.0f;
 
586
 
 
587
 
 
588
        float val1 = floor((float) MIN (mNWindows,
 
589
                                        optionGetCoverMaxVisibleWindows ()) / 2.0);
 
590
 
 
591
        float pos;
 
592
        float space = (maxThumbWidth / 2);
 
593
        space *= cos (sin (PI / 4) * PI / 3);
 
594
        space *= 2;
 
595
        //space += (space / sin (PI / 4)) - space;
 
596
 
 
597
        for (i = 0; i < 2; i++)
 
598
        {
 
599
            if (mInvert ^ (i == 0))
 
600
            {
 
601
                distance = mMvTarget - index;
 
602
                distance += optionGetCoverOffset ();
 
603
            }
 
604
            else
 
605
            {
 
606
                distance = mMvTarget - index + mNWindows;
 
607
                distance += optionGetCoverOffset ();
 
608
                if (distance > mNWindows)
 
609
                    distance -= mNWindows * 2;
 
610
            }
 
611
 
 
612
 
 
613
            pos = MIN (1.0, MAX (-1.0, distance));
 
614
 
 
615
            sw->mSlots[i].opacity = 1.0 - MIN (1.0, MAX (0.0, fabs(distance) - val1));
 
616
            sw->mSlots[i].scale   = MIN (xScale, yScale);
 
617
 
 
618
            sw->mSlots[i].y = centerY + (maxThumbHeight / 2.0) -
 
619
                                (((w->height () / 2.0) + w->border ().bottom) *
 
620
                                sw->mSlots[i].scale);
 
621
 
 
622
            if (fabs(distance) < 1.0)
 
623
            {
 
624
                sw->mSlots[i].x  = centerX + (sin(pos * PI * 0.5) * space * optionGetCoverExtraSpace ());
 
625
                sw->mSlots[i].z  = fabs (distance);
 
626
                sw->mSlots[i].z *= -(maxThumbWidth / (2.0 * oe.width ()));
 
627
 
 
628
                sw->mSlots[i].rotation = sin(pos * PI * 0.5) * -optionGetCoverAngle ();
 
629
            }
 
630
            else
 
631
            {
 
632
                float rad = (space / oe.width ()) / sin(PI / 6.0);
 
633
 
 
634
                float ang = (PI / MAX(72.0, mNWindows * 2)) *
 
635
                            (distance - pos) + (pos * (PI / 6.0));
 
636
 
 
637
                sw->mSlots[i].x  = centerX;
 
638
                sw->mSlots[i].x += sin(ang) * rad * oe.width () * optionGetCoverExtraSpace ();
 
639
 
 
640
                sw->mSlots[i].rotation  = optionGetCoverAngle () + 30;
 
641
                sw->mSlots[i].rotation -= fabs(ang) * 180.0 / PI;
 
642
                sw->mSlots[i].rotation *= -pos;
 
643
 
 
644
                sw->mSlots[i].z  = -(maxThumbWidth / (2.0 * oe.width ()));
 
645
                sw->mSlots[i].z += -(cos(PI / 6.0) * rad);
 
646
                sw->mSlots[i].z += (cos(ang) * rad);
 
647
            }
 
648
 
 
649
            mDrawSlots[index * 2 + i].w     = w;
 
650
            mDrawSlots[index * 2 + i].slot  = &sw->mSlots[i];
 
651
            mDrawSlots[index * 2 + i].distance = fabs(distance);
 
652
 
 
653
        }
 
654
 
 
655
        if (mDrawSlots[index * 2].distance >
 
656
            mDrawSlots[index * 2 + 1].distance)
 
657
        {
 
658
            mDrawSlots[index * 2].slot->primary     = false;
 
659
            mDrawSlots[index * 2 + 1].slot->primary = true;
 
660
        }
 
661
        else
 
662
        {
 
663
            mDrawSlots[index * 2].slot->primary     = true;
 
664
            mDrawSlots[index * 2 + 1].slot->primary = false;
 
665
        }
 
666
 
 
667
    }
 
668
 
 
669
    mNSlots = mNWindows * 2;
 
670
 
 
671
    qsort (mDrawSlots, mNSlots, sizeof (ShiftDrawSlot),
 
672
           compareShiftWindowDistance);
 
673
 
 
674
    return true;
 
675
}
 
676
 
 
677
bool
 
678
ShiftScreen::layoutThumbsFlip ()
 
679
{
 
680
    CompWindow *w;
 
681
    int index;
 
682
    int ww, wh;
 
683
    float xScale, yScale;
 
684
    float distance;
 
685
    int i;
 
686
    float angle;
 
687
    int slotNum;
 
688
 
 
689
    CompRect oe;
 
690
 
 
691
    if (optionGetMultioutputMode () ==
 
692
        ShiftOptions::MultioutputModeOneBigSwitcher)
 
693
    {
 
694
        oe.setGeometry (0, 0, screen->width (), screen->height ());
 
695
    }
 
696
    else
 
697
    {
 
698
        oe = screen->outputDevs ()[mUsedOutput];
 
699
    }
 
700
 
 
701
    /* the center of the ellipse is in the middle
 
702
       of the used output device */
 
703
    int centerX = oe.centerX ();
 
704
    int centerY = oe.centerY ();
 
705
 
 
706
    int maxThumbWidth  = oe.width () * optionGetSize () / 100;
 
707
    int maxThumbHeight = oe.height () * optionGetSize () / 100;
 
708
 
 
709
    slotNum = 0;
 
710
 
 
711
    for (index = 0; index < mNWindows; index++)
 
712
    {
 
713
        w = mWindows[index];
 
714
        SHIFT_WINDOW (w);
 
715
 
 
716
        ww = w->width ()  + w->border ().left + w->border ().right;
 
717
        wh = w->height () + w->border ().top  + w->border ().bottom;
 
718
 
 
719
        if (ww > maxThumbWidth)
 
720
            xScale = (float)(maxThumbWidth) / (float)ww;
 
721
        else
 
722
            xScale = 1.0f;
 
723
 
 
724
        if (wh > maxThumbHeight)
 
725
            yScale = (float)(maxThumbHeight) / (float)wh;
 
726
        else
 
727
            yScale = 1.0f;
 
728
 
 
729
        angle = optionGetFlipRotation () * PI / 180.0;
 
730
 
 
731
        for (i = 0; i < 2; i++)
 
732
        {
 
733
            if (mInvert ^ (i == 0))
 
734
                distance = mMvTarget - index;
 
735
            else
 
736
            {
 
737
                distance = mMvTarget - index + mNWindows;
 
738
                if (distance > 1.0)
 
739
                    distance -= mNWindows * 2;
 
740
            }
 
741
 
 
742
            if (distance > 0.0)
 
743
                sw->mSlots[i].opacity = MAX (0.0, 1.0 - (distance * 1.0));
 
744
            else
 
745
            {
 
746
                if (distance < -(mNWindows - 1))
 
747
                    sw->mSlots[i].opacity = MAX (0.0, mNWindows +
 
748
                                                distance);
 
749
                else
 
750
                    sw->mSlots[i].opacity = 1.0;
 
751
            }
 
752
 
 
753
            if (distance > 0.0 && w->id () != mSelectedWindow)
 
754
                sw->mSlots[i].primary = false;
 
755
            else
 
756
                sw->mSlots[i].primary = true;
 
757
 
 
758
 
 
759
            sw->mSlots[i].scale   = MIN (xScale, yScale);
 
760
 
 
761
            sw->mSlots[i].y = centerY + (maxThumbHeight / 2.0) -
 
762
                                (((w->height () / 2.0) + w->border ().bottom) *
 
763
                                sw->mSlots[i].scale);
 
764
 
 
765
            sw->mSlots[i].x  = sin(angle) * distance * (maxThumbWidth / 2);
 
766
            if (distance > 0 && false)
 
767
                sw->mSlots[i].x *= 1.5;
 
768
            sw->mSlots[i].x += centerX;
 
769
 
 
770
            sw->mSlots[i].z  = cos(angle) * distance;
 
771
            if (distance > 0)
 
772
                sw->mSlots[i].z *= 1.5;
 
773
            sw->mSlots[i].z *= (maxThumbWidth / (2.0 * oe.width ()));
 
774
 
 
775
            sw->mSlots[i].rotation = optionGetFlipRotation ();
 
776
 
 
777
            if (sw->mSlots[i].opacity > 0.0)
 
778
            {
 
779
                mDrawSlots[slotNum].w     = w;
 
780
                mDrawSlots[slotNum].slot  = &sw->mSlots[i];
 
781
                mDrawSlots[slotNum].distance = -distance;
 
782
                slotNum++;
 
783
            }
 
784
        }
 
785
    }
 
786
 
 
787
    mNSlots = slotNum;
 
788
 
 
789
    qsort (mDrawSlots, mNSlots, sizeof (ShiftDrawSlot),
 
790
           compareShiftWindowDistance);
 
791
 
 
792
    return true;
 
793
}
 
794
 
 
795
 
 
796
bool
 
797
ShiftScreen::layoutThumbs ()
 
798
{
 
799
    bool result = false;
 
800
 
 
801
    if (mState == ShiftStateNone)
 
802
        return false;
 
803
 
 
804
    switch (optionGetMode ())
 
805
    {
 
806
        case ShiftScreen::ModeCover:
 
807
            result = layoutThumbsCover ();
 
808
            break;
 
809
        case ShiftScreen::ModeFlip:
 
810
            result = layoutThumbsFlip ();
 
811
            break;
 
812
    }
 
813
 
 
814
    if (mState == ShiftStateIn)
 
815
        return false;
 
816
 
 
817
    return result;
 
818
}
 
819
 
 
820
 
 
821
void
 
822
ShiftScreen::addWindowToList (CompWindow *w)
 
823
{
 
824
    if (mWindowsSize <= mNWindows)
 
825
    {
 
826
        mWindows = (CompWindow **) realloc (mWindows,
 
827
                               sizeof (CompWindow *) * (mNWindows + 32));
 
828
        if (!mWindows)
 
829
            return;
 
830
 
 
831
        mWindowsSize = mNWindows + 32;
 
832
    }
 
833
 
 
834
    if (mSlotsSize <= mNWindows * 2)
 
835
    {
 
836
        mDrawSlots = (ShiftDrawSlot *) realloc (mDrawSlots,
 
837
                                 sizeof (ShiftDrawSlot) *
 
838
                                 ((mNWindows * 2) + 64));
 
839
 
 
840
        if (!mDrawSlots)
 
841
        {
 
842
            free (mDrawSlots);
 
843
            return;
 
844
        }
 
845
 
 
846
        mSlotsSize = (mNWindows * 2) + 64;
 
847
    }
 
848
 
 
849
    mWindows[mNWindows++] = w;
 
850
}
 
851
 
 
852
bool
 
853
ShiftScreen::updateWindowList ()
 
854
{
 
855
    int        i, idx;
 
856
    CompWindow **wins;
 
857
 
 
858
    qsort (mWindows, mNWindows, sizeof (CompWindow *), compareWindows);
 
859
 
 
860
    mMvTarget = 0;
 
861
    mMvAdjust = 0;
 
862
    mMvVelocity = 0;
 
863
    for (i = 0; i < mNWindows; i++)
 
864
    {
 
865
        if (mWindows[i]->id () == mSelectedWindow)
 
866
            break;
 
867
 
 
868
        mMvTarget++;
 
869
    }
 
870
    if (mMvTarget == mNWindows)
 
871
        mMvTarget = 0;
 
872
 
 
873
    /* create spetial window order to create a good animation
 
874
       A,B,C,D,E --> A,B,D,E,C to get B,D,E,C,(A),B,D,E,C as initial state */
 
875
    if (optionGetMode () == ShiftScreen::ModeCover)
 
876
    {
 
877
        wins = (CompWindow **) malloc(mNWindows * sizeof (CompWindow *));
 
878
        if (!wins)
 
879
            return false;
 
880
 
 
881
        memcpy(wins, mWindows, mNWindows * sizeof (CompWindow *));
 
882
        for (i = 0; i < mNWindows; i++)
 
883
        {
 
884
            idx = ceil (i * 0.5);
 
885
            idx *= (i & 1) ? 1 : -1;
 
886
            if (idx < 0)
 
887
                idx += mNWindows;
 
888
            mWindows[idx] = wins[i];
 
889
        }
 
890
        free (wins);
 
891
    }
 
892
 
 
893
    return layoutThumbs ();
 
894
}
 
895
 
 
896
bool
 
897
ShiftScreen::createWindowList ()
 
898
{
 
899
    mNWindows = 0;
 
900
 
 
901
    foreach (CompWindow *w, screen->windows ())
 
902
    {
 
903
        SHIFT_WINDOW (w);
 
904
        if (sw->isShiftable ())
 
905
        {
 
906
            addWindowToList (w);
 
907
            sw->mActive = true;
 
908
        }
 
909
    }
 
910
 
 
911
    return updateWindowList ();
 
912
}
 
913
 
 
914
void
 
915
ShiftScreen::switchToWindow (bool          toNext)
 
916
{
 
917
    CompWindow *w;
 
918
    int        cur;
 
919
 
 
920
    if (!mGrabIndex)
 
921
        return;
 
922
 
 
923
    for (cur = 0; cur < mNWindows; cur++)
 
924
    {
 
925
        if (mWindows[cur]->id () == mSelectedWindow)
 
926
            break;
 
927
    }
 
928
 
 
929
    if (cur == mNWindows)
 
930
        return;
 
931
 
 
932
    if (toNext)
 
933
        w = mWindows[(cur + 1) % mNWindows];
 
934
    else
 
935
        w = mWindows[(cur + mNWindows - 1) % mNWindows];
 
936
 
 
937
    if (w)
 
938
    {
 
939
        Window old = mSelectedWindow;
 
940
        mSelectedWindow = w->id ();
 
941
 
 
942
        if (old != w->id ())
 
943
        {
 
944
            if (toNext)
 
945
                mMvAdjust += 1;
 
946
            else
 
947
                mMvAdjust -= 1;
 
948
 
 
949
            mMoveAdjust = true;
 
950
            cScreen->damageScreen ();
 
951
            renderWindowTitle ();
 
952
        }
 
953
    }
 
954
}
 
955
 
 
956
int
 
957
ShiftScreen::countWindows ()
 
958
{
 
959
    int        count = 0;
 
960
 
 
961
    foreach (CompWindow *w, screen->windows ())
 
962
    {
 
963
        if (ShiftWindow::get (w)->isShiftable ())
 
964
            count++;
 
965
    }
 
966
 
 
967
    return count;
 
968
}
 
969
 
 
970
int
 
971
ShiftScreen::adjustShiftMovement (float chunk)
 
972
{
 
973
    float dx, adjust, amount;
 
974
    float change;
 
975
 
 
976
    dx = mMvAdjust;
 
977
 
 
978
    adjust = dx * 0.15f;
 
979
    amount = fabs(dx) * 1.5f;
 
980
    if (amount < 0.2f)
 
981
        amount = 0.2f;
 
982
    else if (amount > 2.0f)
 
983
        amount = 2.0f;
 
984
 
 
985
    mMvVelocity = (amount * mMvVelocity + adjust) / (amount + 1.0f);
 
986
 
 
987
    if (fabs (dx) < 0.002f && fabs (mMvVelocity) < 0.004f)
 
988
    {
 
989
        mMvVelocity = 0.0f;
 
990
        mMvTarget = mMvTarget + mMvAdjust;
 
991
        mMvAdjust = 0;
 
992
        layoutThumbs ();
 
993
        return false;
 
994
    }
 
995
 
 
996
    change = mMvVelocity * chunk;
 
997
    if (!change)
 
998
    {
 
999
        if (mMvVelocity)
 
1000
            change = (mMvAdjust > 0) ? 0.01 : -0.01;
 
1001
    }
 
1002
 
 
1003
    mMvAdjust -= change;
 
1004
    mMvTarget += change;
 
1005
 
 
1006
    while (mMvTarget >= mNWindows)
 
1007
    {
 
1008
        mMvTarget -= mNWindows;
 
1009
        mInvert = !mInvert;
 
1010
    }
 
1011
 
 
1012
    while (mMvTarget < 0)
 
1013
    {
 
1014
        mMvTarget += mNWindows;
 
1015
        mInvert = !mInvert;
 
1016
    }
 
1017
 
 
1018
    if (!layoutThumbs ())
 
1019
        return false;
 
1020
 
 
1021
    return true;
 
1022
}
 
1023
 
 
1024
bool
 
1025
ShiftWindow::adjustShiftAttribs (float chunk)
 
1026
{
 
1027
    float dp, db, adjust, amount;
 
1028
    float opacity, brightness;
 
1029
 
 
1030
    SHIFT_SCREEN (screen);
 
1031
 
 
1032
    if ((mActive && ss->mState != ShiftStateIn &&
 
1033
        ss->mState != ShiftStateNone) ||
 
1034
        (ss->optionGetHideAll () && !(window->type () & CompWindowTypeDesktopMask) &&
 
1035
        (ss->mState == ShiftStateOut || ss->mState == ShiftStateSwitching ||
 
1036
         ss->mState == ShiftStateFinish)))
 
1037
        opacity = 0.0;
 
1038
    else
 
1039
        opacity = 1.0;
 
1040
 
 
1041
    if (ss->mState == ShiftStateIn || ss->mState == ShiftStateNone)
 
1042
        brightness = 1.0;
 
1043
    else
 
1044
        brightness = ss->optionGetBackgroundIntensity ();
 
1045
 
 
1046
    dp = opacity - mOpacity;
 
1047
    adjust = dp * 0.1f;
 
1048
    amount = fabs (dp) * 7.0f;
 
1049
    if (amount < 0.01f)
 
1050
        amount = 0.01f;
 
1051
    else if (amount > 0.15f)
 
1052
        amount = 0.15f;
 
1053
 
 
1054
    mOpacityVelocity = (amount * mOpacityVelocity + adjust) /
 
1055
        (amount + 1.0f);
 
1056
 
 
1057
    db = brightness - mBrightness;
 
1058
    adjust = db * 0.1f;
 
1059
    amount = fabs (db) * 7.0f;
 
1060
    if (amount < 0.01f)
 
1061
        amount = 0.01f;
 
1062
    else if (amount > 0.15f)
 
1063
        amount = 0.15f;
 
1064
 
 
1065
    mBrightnessVelocity = (amount * mBrightnessVelocity + adjust) /
 
1066
        (amount + 1.0f);
 
1067
 
 
1068
    /* FIXME: There is a possible floating point overflow here,
 
1069
     * can be worked-around but not particularly nice */
 
1070
 
 
1071
    if ((fabs (dp) < 0.1f && fabs (mOpacityVelocity) < 0.2f &&
 
1072
        fabs (db) < 0.1f && fabs (mBrightnessVelocity) < 0.2f) ||
 
1073
        (fabs(db) != fabs (db) || fabs (mOpacityVelocity) != fabs (mOpacityVelocity) ||
 
1074
        fabs (dp) != fabs (dp) || fabs (mBrightnessVelocity) != fabs (mBrightnessVelocity)))
 
1075
    {
 
1076
        mBrightness = brightness;
 
1077
        mOpacity = opacity;
 
1078
        return false;
 
1079
    }
 
1080
 
 
1081
    mBrightness += mBrightnessVelocity * chunk;
 
1082
    mOpacity += mOpacityVelocity * chunk;
 
1083
    return true;
 
1084
}
 
1085
 
 
1086
bool
 
1087
ShiftScreen::adjustShiftAnimationAttribs (float chunk)
 
1088
{
 
1089
    float dr, adjust, amount;
 
1090
    float anim;
 
1091
 
 
1092
    if (mState != ShiftStateIn && mState != ShiftStateNone)
 
1093
        anim = 1.0;
 
1094
    else
 
1095
        anim = 0.0;
 
1096
 
 
1097
    dr = anim - mAnim;
 
1098
    adjust = dr * 0.1f;
 
1099
    amount = fabs (dr) * 7.0f;
 
1100
    if (amount < 0.002f)
 
1101
        amount = 0.002f;
 
1102
    else if (amount > 0.15f)
 
1103
        amount = 0.15f;
 
1104
 
 
1105
    mAnimVelocity = (amount * mAnimVelocity + adjust) /
 
1106
        (amount + 1.0f);
 
1107
 
 
1108
    if (fabs (dr) < 0.002f && fabs (mAnimVelocity) < 0.004f)
 
1109
    {
 
1110
        mAnim = anim;
 
1111
        return false;
 
1112
    }
 
1113
 
 
1114
    mAnim += mAnimVelocity * chunk;
 
1115
    return true;
 
1116
}
 
1117
 
 
1118
bool
 
1119
ShiftScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
 
1120
                            const GLMatrix            &transform,
 
1121
                            const CompRegion          &region,
 
1122
                            CompOutput                *output,
 
1123
                            unsigned int              mask)
 
1124
{
 
1125
    bool status;
 
1126
 
 
1127
    if (mState != ShiftStateNone)
 
1128
        mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
 
1129
 
 
1130
    mPaintingAbove = false;
 
1131
 
 
1132
    mOutput = output;
 
1133
 
 
1134
    status = gScreen->glPaintOutput (attrib, transform, region, output, mask);
 
1135
 
 
1136
    if (mState != ShiftStateNone &&
 
1137
        ((unsigned int) output->id () == (unsigned int) mUsedOutput ||
 
1138
        ((unsigned int) output->id () == (unsigned int) ~0)))
 
1139
    {
 
1140
        CompWindow    *w;
 
1141
        GLMatrix      sTransform (transform);
 
1142
        int           i;
 
1143
        int           oy1 = screen->outputDevs ()[mUsedOutput].region ()->extents.y1;
 
1144
        int           oy2 = screen->outputDevs ()[mUsedOutput].region ()->extents.y2;
 
1145
        int           maxThumbHeight = (oy2 - oy1) * optionGetSize () / 100;
 
1146
        int           oldFilter = gScreen->textureFilter ();
 
1147
 
 
1148
        if (optionGetMultioutputMode () == ShiftOptions::MultioutputModeOneBigSwitcher)
 
1149
        {
 
1150
            oy1 = 0;
 
1151
            oy2 = screen->height ();
 
1152
        }
 
1153
 
 
1154
        sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
 
1155
 
 
1156
        GLdouble clip[4] = { 0.0, -1.0, 0.0, 0.0};
 
1157
 
 
1158
        clip[3] = ((oy1 + (oy2 - oy1) / 2)) + (maxThumbHeight / 2.0);
 
1159
 
 
1160
        /* Reflection drawing */
 
1161
 
 
1162
        if (optionGetReflection ())
 
1163
        {
 
1164
            GLMatrix       rTransform = sTransform;
 
1165
            unsigned short color[4];
 
1166
            int            cull, cullInv;
 
1167
            glGetIntegerv (GL_CULL_FACE_MODE, &cull);
 
1168
            cullInv = (cull == GL_BACK)? GL_FRONT : GL_BACK;
 
1169
 
 
1170
            rTransform.translate (0.0, oy1 + oy2 + maxThumbHeight,
 
1171
                             0.0);
 
1172
            rTransform.scale (1.0, -1.0, 1.0);
 
1173
 
 
1174
            glPushMatrix ();
 
1175
            glLoadMatrixf (rTransform.getMatrix ());
 
1176
 
 
1177
            glCullFace (cullInv);
 
1178
 
 
1179
            if (optionGetMipmaps ())
 
1180
                gScreen->setTextureFilter (GL_LINEAR_MIPMAP_LINEAR);
 
1181
 
 
1182
 
 
1183
            if (mAnim == 1.0)
 
1184
            {
 
1185
                glClipPlane (GL_CLIP_PLANE0, clip);
 
1186
                glEnable (GL_CLIP_PLANE0);
 
1187
            }
 
1188
 
 
1189
            mReflectActive = true;
 
1190
            mReflectBrightness = optionGetIntensity ();
 
1191
            for (i = 0; i < mNSlots; i++)
 
1192
            {
 
1193
                w = mDrawSlots[i].w;
 
1194
 
 
1195
                SHIFT_WINDOW (w);
 
1196
 
 
1197
                mActiveSlot = &mDrawSlots[i];
 
1198
                {
 
1199
                    sw->gWindow->glPaint (sw->gWindow->paintAttrib (), rTransform,
 
1200
                                          infiniteRegion, 0);
 
1201
                }
 
1202
            }
 
1203
 
 
1204
            glDisable (GL_CLIP_PLANE0);
 
1205
            glCullFace (cull);
 
1206
 
 
1207
            glLoadIdentity();
 
1208
            glTranslatef (0.0, 0.0, -DEFAULT_Z_CAMERA);
 
1209
 
 
1210
            glEnable(GL_BLEND);
 
1211
            glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
1212
 
 
1213
            glBegin (GL_QUADS);
 
1214
            glColor4f (0.0, 0.0, 0.0, 0.0);
 
1215
            glVertex2f (0.5, 0.0);
 
1216
            glVertex2f (-0.5, 0.0);
 
1217
            glColor4f (0.0, 0.0, 0.0,
 
1218
                       MIN (1.0, 1.0 - optionGetIntensity ()) * 2.0 *
 
1219
                       mAnim);
 
1220
            glVertex2f (-0.5, -0.5);
 
1221
            glVertex2f (0.5, -0.5);
 
1222
            glEnd();
 
1223
 
 
1224
            if (optionGetGroundSize () > 0.0)
 
1225
            {
 
1226
                glBegin (GL_QUADS);
 
1227
                color[0] = optionGetGroundColor1 ()[0];
 
1228
                color[1] = optionGetGroundColor1 ()[1];
 
1229
                color[2] = optionGetGroundColor1 ()[2];
 
1230
                color[3] = (float)optionGetGroundColor1 ()[3] * mAnim;
 
1231
                glColor4usv (color);
 
1232
                glVertex2f (-0.5, -0.5);
 
1233
                glVertex2f (0.5, -0.5);
 
1234
                color[0] = optionGetGroundColor2 ()[0];
 
1235
                color[1] = optionGetGroundColor2 ()[1];
 
1236
                color[2] = optionGetGroundColor2 ()[2];
 
1237
                color[3] = (float)optionGetGroundColor2 ()[3] * mAnim;
 
1238
                glColor4usv (color);
 
1239
                glVertex2f (0.5, -0.5 + optionGetGroundSize ());
 
1240
                glVertex2f (-0.5, -0.5 + optionGetGroundSize ());
 
1241
                glEnd();
 
1242
            }
 
1243
 
 
1244
            glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 
1245
            glDisable(GL_BLEND);
 
1246
            glColor4f (1.0, 1.0, 1.0, 1.0);
 
1247
            glPopMatrix ();
 
1248
        }
 
1249
 
 
1250
        /* Drawing normal windows */
 
1251
 
 
1252
        glPushMatrix ();
 
1253
        glLoadMatrixf (sTransform.getMatrix ());
 
1254
 
 
1255
        if (optionGetReflection () && mAnim == 1.0)
 
1256
        {
 
1257
            glClipPlane (GL_CLIP_PLANE0, clip);
 
1258
            glEnable (GL_CLIP_PLANE0);
 
1259
        }
 
1260
 
 
1261
        mReflectBrightness = 1.0;
 
1262
        mReflectActive     = false;
 
1263
 
 
1264
        for (i = 0; i < mNSlots; i++)
 
1265
        {
 
1266
            w = mDrawSlots[i].w;
 
1267
 
 
1268
            SHIFT_WINDOW (w);
 
1269
 
 
1270
            mActiveSlot = &mDrawSlots[i];
 
1271
            {
 
1272
                sw->gWindow->glPaint (sw->gWindow->paintAttrib (), sTransform,
 
1273
                                      infiniteRegion, 0);
 
1274
            }
 
1275
        }
 
1276
 
 
1277
        glDisable (GL_CLIP_PLANE0);
 
1278
 
 
1279
        mActiveSlot = NULL;
 
1280
 
 
1281
        gScreen->setTextureFilter (oldFilter);
 
1282
 
 
1283
        if (textAvailable && (mState != ShiftStateIn))
 
1284
            drawWindowTitle ();
 
1285
 
 
1286
        if (mState == ShiftStateIn || mState == ShiftStateOut)
 
1287
        {
 
1288
            bool found;
 
1289
            mPaintingAbove = true;
 
1290
 
 
1291
            w = screen->findWindow (mSelectedWindow);
 
1292
 
 
1293
            for (; w; w = w->next)
 
1294
            {
 
1295
                if (w->destroyed ())
 
1296
                    continue;
 
1297
 
 
1298
                if (!w->shaded ())
 
1299
                {
 
1300
                    if (!w->isViewable () || !CompositeWindow::get (w)->damaged ())
 
1301
                        continue;
 
1302
                }
 
1303
 
 
1304
                found = false;
 
1305
                for (i = 0; i < mNWindows; i++)
 
1306
                    if (mWindows[i] == w)
 
1307
                        found = true;
 
1308
                if (found)
 
1309
                    continue;
 
1310
 
 
1311
                SHIFT_WINDOW (w);
 
1312
 
 
1313
                sw->gWindow->glPaint (sw->gWindow->paintAttrib (), sTransform,
 
1314
                                      infiniteRegion, 0);
 
1315
            }
 
1316
 
 
1317
            mPaintingAbove = false;
 
1318
        }
 
1319
 
 
1320
        glPopMatrix ();
 
1321
    }
 
1322
 
 
1323
    return status;
 
1324
}
 
1325
 
 
1326
void
 
1327
ShiftScreen::paint (CompOutput::ptrList &outputs,
 
1328
                    unsigned int       mask)
 
1329
{
 
1330
 
 
1331
    if (mState != ShiftStateNone && outputs.size () > 0 &&
 
1332
        optionGetMultioutputMode () == ShiftOptions::MultioutputModeOneBigSwitcher)
 
1333
    {
 
1334
        CompOutput::ptrList newOutputs;
 
1335
        newOutputs.push_back (&screen->fullscreenOutput ());
 
1336
 
 
1337
        cScreen->paint (newOutputs, mask);
 
1338
        return;
 
1339
    }
 
1340
 
 
1341
    cScreen->paint (outputs, mask);
 
1342
    return;
 
1343
}
 
1344
 
 
1345
void
 
1346
ShiftScreen::preparePaint (int  msSinceLastPaint)
 
1347
{
 
1348
    if (mState != ShiftStateNone &&
 
1349
        (mMoreAdjust || mMoveAdjust))
 
1350
    {
 
1351
        int        steps;
 
1352
        float      amount, chunk;
 
1353
        int        i;
 
1354
 
 
1355
        amount = msSinceLastPaint * 0.05f * optionGetShiftSpeed ();
 
1356
        steps  = amount / (0.5f * optionGetTimestep ());
 
1357
 
 
1358
        if (!steps)
 
1359
            steps = 1;
 
1360
        chunk  = amount / (float) steps;
 
1361
 
 
1362
 
 
1363
        while (steps--)
 
1364
        {
 
1365
            mMoveAdjust = adjustShiftMovement (chunk);
 
1366
            if (!mMoveAdjust)
 
1367
                break;
 
1368
        }
 
1369
 
 
1370
        amount = msSinceLastPaint * 0.05f * optionGetSpeed ();
 
1371
        steps  = amount / (0.5f * optionGetTimestep ());
 
1372
 
 
1373
        if (!steps)
 
1374
            steps = 1;
 
1375
        chunk  = amount / (float) steps;
 
1376
 
 
1377
        while (steps--)
 
1378
        {
 
1379
            mMoreAdjust = adjustShiftAnimationAttribs (chunk);
 
1380
 
 
1381
            foreach (CompWindow *w, screen->windows ())
 
1382
            {
 
1383
                SHIFT_WINDOW (w);
 
1384
 
 
1385
                mMoreAdjust |= sw->adjustShiftAttribs (chunk);
 
1386
                for (i = 0; i < 2; i++)
 
1387
                {
 
1388
                    ShiftSlot *slot = &sw->mSlots[i];
 
1389
                    slot->tx = slot->x - w->x () -
 
1390
                        (w->width () * slot->scale) / 2;
 
1391
                    slot->ty = slot->y - w->y () -
 
1392
                        (w->height () * slot->scale) / 2;
 
1393
                }
 
1394
            }
 
1395
 
 
1396
            if (!mMoreAdjust)
 
1397
                break;
 
1398
        }
 
1399
    }
 
1400
 
 
1401
    cScreen->preparePaint (msSinceLastPaint);
 
1402
}
 
1403
 
 
1404
bool
 
1405
ShiftWindow::canStackRelativeTo ()
 
1406
{
 
1407
    if (window->overrideRedirect ())
 
1408
        return false;
 
1409
 
 
1410
    if (!window->shaded () && !window->pendingMaps ())
 
1411
    {
 
1412
        if (!window->isViewable () || window->mapNum () == 0)
 
1413
            return false;
 
1414
    }
 
1415
 
 
1416
    return true;
 
1417
}
 
1418
 
 
1419
void
 
1420
ShiftScreen::donePaint ()
 
1421
{
 
1422
    if (mState != ShiftStateNone)
 
1423
    {
 
1424
        if (mMoreAdjust)
 
1425
        {
 
1426
            cScreen->damageScreen ();
 
1427
        }
 
1428
        else
 
1429
        {
 
1430
            if (mState == ShiftStateIn)
 
1431
            {
 
1432
                mState = ShiftStateNone;
 
1433
                activateEvent (false);
 
1434
                foreach (CompWindow *w, screen->windows ())
 
1435
                {
 
1436
                    SHIFT_WINDOW (w);
 
1437
                    sw->mActive = false;
 
1438
                }
 
1439
                setFunctions (false);
 
1440
                cScreen->damageScreen ();
 
1441
            }
 
1442
            else if (mState == ShiftStateOut)
 
1443
                     mState = ShiftStateSwitching;
 
1444
 
 
1445
            if (mMoveAdjust)
 
1446
            {
 
1447
                cScreen->damageScreen ();
 
1448
            }
 
1449
            else if (mState == ShiftStateFinish)
 
1450
            {
 
1451
 
 
1452
                CompWindow *w;
 
1453
 
 
1454
                CompWindow *pw = NULL;
 
1455
                int i;
 
1456
 
 
1457
                mState = ShiftStateIn;
 
1458
                mMoreAdjust = true;
 
1459
                cScreen->damageScreen ();
 
1460
 
 
1461
                if (!mCancelled && mMvTarget != 0)
 
1462
                    for (i = 0; i < mNSlots; i++)
 
1463
                    {
 
1464
                        w = mDrawSlots[i].w;
 
1465
 
 
1466
                        SHIFT_WINDOW (w);
 
1467
 
 
1468
                        if (mDrawSlots[i].slot->primary && sw->canStackRelativeTo ())
 
1469
                        {
 
1470
                            if (pw)
 
1471
                                w->restackAbove (pw);
 
1472
                            pw = w;
 
1473
                        }
 
1474
                    }
 
1475
 
 
1476
                if (!mCancelled && mSelectedWindow)
 
1477
                {
 
1478
                    w = screen->findWindow (mSelectedWindow);
 
1479
                    if (w)
 
1480
                        screen->sendWindowActivationRequest (mSelectedWindow);
 
1481
 
 
1482
                }
 
1483
            }
 
1484
 
 
1485
            cScreen->damageScreen ();
 
1486
        }
 
1487
    }
 
1488
 
 
1489
    cScreen->donePaint ();
 
1490
}
 
1491
 
 
1492
void
 
1493
ShiftScreen::term (bool cancel)
 
1494
{
 
1495
    if (mGrabIndex)
 
1496
    {
 
1497
        screen->removeGrab (mGrabIndex, 0);
 
1498
        mGrabIndex = 0;
 
1499
    }
 
1500
 
 
1501
    if (mState != ShiftStateNone)
 
1502
    {
 
1503
        if (cancel && mMvTarget != 0)
 
1504
        {
 
1505
            if (mNWindows - mMvTarget > mMvTarget)
 
1506
                mMvAdjust = -mMvTarget;
 
1507
            else
 
1508
                mMvAdjust = mNWindows - mMvTarget;
 
1509
            mMoveAdjust = true;
 
1510
        }
 
1511
 
 
1512
        mMoreAdjust = false;
 
1513
        mMoveAdjust = false;
 
1514
        mState = ShiftStateFinish;
 
1515
        mCancelled = cancel;
 
1516
        cScreen->damageScreen ();
 
1517
    }
 
1518
}
 
1519
 
 
1520
bool
 
1521
ShiftScreen::terminate (CompAction         *action,
 
1522
                        CompAction::State          state,
 
1523
                        CompOption::Vector &options)
 
1524
{
 
1525
    Window     xid;
 
1526
 
 
1527
    xid = CompOption::getIntOptionNamed (options, "root", 0);
 
1528
 
 
1529
    if (!(xid && screen->root () != xid))
 
1530
    {
 
1531
        term ((state & CompAction::StateCancel));
 
1532
 
 
1533
        if (action->state () & CompAction::StateTermButton)
 
1534
            action->setState (action->state () & ~CompAction::StateTermButton);
 
1535
 
 
1536
        if (action->state () & CompAction::StateTermKey)
 
1537
            action->setState (action->state () & ~CompAction::StateTermKey);
 
1538
    }
 
1539
 
 
1540
    return false;
 
1541
}
 
1542
 
 
1543
bool
 
1544
ShiftScreen::initiateScreen (CompAction         *action,
 
1545
                             CompAction::State    state,
 
1546
                             CompOption::Vector &options)
 
1547
{
 
1548
    CompMatch match;
 
1549
    int       count;
 
1550
 
 
1551
    if (screen->otherGrabExist ("shift", NULL))
 
1552
        return false;
 
1553
 
 
1554
    mCurrentMatch = &(optionGetWindowMatch ());
 
1555
 
 
1556
    match = CompOption::getMatchOptionNamed (options, "match", CompMatch::emptyMatch);
 
1557
    if (match != CompMatch::emptyMatch)
 
1558
    {
 
1559
        mMatch = match;
 
1560
        mMatch.update ();
 
1561
        mCurrentMatch = &mMatch;
 
1562
    }
 
1563
 
 
1564
    count = countWindows ();
 
1565
 
 
1566
    if (count < 1)
 
1567
        return false;
 
1568
 
 
1569
    if (!mGrabIndex)
 
1570
        mGrabIndex = screen->pushGrab (screen->invisibleCursor (), "shift");
 
1571
 
 
1572
 
 
1573
    if (mGrabIndex)
 
1574
    {
 
1575
        mState = ShiftStateOut;
 
1576
        activateEvent (true);
 
1577
 
 
1578
        if (!createWindowList ())
 
1579
            return false;
 
1580
 
 
1581
        mSelectedWindow = mWindows[0]->id ();
 
1582
        renderWindowTitle ();
 
1583
        mMvTarget = 0;
 
1584
        mMvAdjust = 0;
 
1585
        mMvVelocity = 0;
 
1586
 
 
1587
        mMoreAdjust = true;
 
1588
        cScreen->damageScreen ();
 
1589
    }
 
1590
 
 
1591
    mUsedOutput = screen->currentOutputDev ().id ();
 
1592
 
 
1593
    setFunctions (true);
 
1594
 
 
1595
    return true;
 
1596
}
 
1597
 
 
1598
bool
 
1599
ShiftScreen::doSwitch (CompAction         *action,
 
1600
                       CompAction::State    state,
 
1601
                       CompOption::Vector &options,
 
1602
                       bool               nextWindow,
 
1603
                       ShiftType          type)
 
1604
{
 
1605
    bool       ret = true;
 
1606
    bool       initial = false;
 
1607
 
 
1608
    if ((mState == ShiftStateNone) || (mState == ShiftStateIn))
 
1609
    {
 
1610
        if (type == ShiftTypeGroup)
 
1611
        {
 
1612
            CompWindow *w;
 
1613
            w = screen->findWindow (CompOption::getIntOptionNamed (options,
 
1614
                                                                   "window",
 
1615
                                                                   0));
 
1616
            if (w)
 
1617
            {
 
1618
                mType = ShiftTypeGroup;
 
1619
                mClientLeader =
 
1620
                    (w->clientLeader ()) ? w->clientLeader () : w->id ();
 
1621
                ret = initiateScreen (action, state, options);
 
1622
            }
 
1623
        }
 
1624
        else
 
1625
        {
 
1626
            mType = type;
 
1627
            ret = initiateScreen (action, state, options);
 
1628
        }
 
1629
 
 
1630
        if (state & CompAction::StateInitKey)
 
1631
            action->setState (state | CompAction::StateTermKey);
 
1632
 
 
1633
        if (state & CompAction::StateInitButton)
 
1634
            action->setState (state | CompAction::StateTermButton);
 
1635
 
 
1636
        if (state & CompAction::StateInitEdge)
 
1637
            action->setState (state | CompAction::StateTermEdge);
 
1638
 
 
1639
        initial = true;
 
1640
    }
 
1641
 
 
1642
    if (ret)
 
1643
    {
 
1644
        switchToWindow (nextWindow);
 
1645
        if (initial && false)
 
1646
        {
 
1647
            mMvTarget += mMvAdjust;
 
1648
            mMvAdjust  = 0.0;
 
1649
        }
 
1650
    }
 
1651
 
 
1652
 
 
1653
    return ret;
 
1654
}
 
1655
 
 
1656
bool
 
1657
ShiftScreen::initiate (CompAction         *action,
 
1658
                       CompAction::State    state,
 
1659
                       CompOption::Vector &options)
 
1660
{
 
1661
    bool       ret = true;
 
1662
 
 
1663
    mType = ShiftTypeNormal;
 
1664
 
 
1665
    if ((mState == ShiftStateNone) || (mState == ShiftStateIn) ||
 
1666
        (mState == ShiftStateFinish))
 
1667
        ret = initiateScreen (action, state, options);
 
1668
    else
 
1669
        ret = terminate (action, state, options);
 
1670
 
 
1671
    if (state & CompAction::StateTermButton)
 
1672
        action->setState (state & ~CompAction::StateTermButton);
 
1673
 
 
1674
    if (state & CompAction::StateTermKey)
 
1675
        action->setState (state & ~CompAction::StateTermKey);
 
1676
 
 
1677
    return ret;
 
1678
}
 
1679
 
 
1680
bool
 
1681
ShiftScreen::initiateAll (CompAction         *action,
 
1682
                          CompAction::State    state,
 
1683
                          CompOption::Vector &options)
 
1684
{
 
1685
    bool       ret = true;
 
1686
 
 
1687
    mType = ShiftTypeAll;
 
1688
 
 
1689
    if ((mState == ShiftStateNone) || (mState == ShiftStateIn) ||
 
1690
        (mState == ShiftStateFinish))
 
1691
        ret = initiateScreen (action, state, options);
 
1692
    else
 
1693
        ret = terminate (action, state, options);
 
1694
 
 
1695
    if (state & CompAction::StateTermButton)
 
1696
        action->setState (state & ~CompAction::StateTermButton);
 
1697
 
 
1698
    if (state & CompAction::StateTermKey)
 
1699
        action->setState (state & ~CompAction::StateTermKey);
 
1700
 
 
1701
 
 
1702
    return ret;
 
1703
}
 
1704
void
 
1705
ShiftScreen::windowRemove (Window id)
 
1706
{
 
1707
    CompWindow *w = screen->findWindow (id);
 
1708
    if (w)
 
1709
    {
 
1710
        bool inList = false;
 
1711
        int j, i = 0;
 
1712
        Window selected;
 
1713
 
 
1714
        SHIFT_WINDOW (w);
 
1715
 
 
1716
        if (mState == ShiftStateNone)
 
1717
            return;
 
1718
 
 
1719
        if (sw->isShiftable ())
 
1720
            return;
 
1721
 
 
1722
        selected = mSelectedWindow;
 
1723
 
 
1724
        while (i < mNWindows)
 
1725
        {
 
1726
            if (w->id () == mWindows[i]->id ())
 
1727
            {
 
1728
                inList = true;
 
1729
 
 
1730
                if (w->id () == selected)
 
1731
                {
 
1732
                    if (i < (mNWindows - 1))
 
1733
                        selected = mWindows[i + 1]->id ();
 
1734
                    else
 
1735
                        selected = mWindows[0]->id ();
 
1736
 
 
1737
                    mSelectedWindow = selected;
 
1738
                }
 
1739
 
 
1740
                mNWindows--;
 
1741
                for (j = i; j < mNWindows; j++)
 
1742
                    mWindows[j] = mWindows[j + 1];
 
1743
            }
 
1744
            else
 
1745
            {
 
1746
                i++;
 
1747
            }
 
1748
        }
 
1749
 
 
1750
        if (!inList)
 
1751
            return;
 
1752
 
 
1753
        if (mNWindows == 0)
 
1754
        {
 
1755
            CompOption o;
 
1756
            CompOption::Vector opts;
 
1757
 
 
1758
            o = CompOption ("root", CompOption::TypeInt);
 
1759
            o.value ().set ((int) screen->root ());
 
1760
 
 
1761
            opts.push_back (o);
 
1762
 
 
1763
            terminate (NULL, 0, opts);
 
1764
            return;
 
1765
        }
 
1766
 
 
1767
        // Let the window list be updated to avoid crash
 
1768
        // when a window is closed while ending shift (ShiftStateIn).
 
1769
        if (!mGrabIndex && mState != ShiftStateIn)
 
1770
            return;
 
1771
 
 
1772
        if (updateWindowList ())
 
1773
        {
 
1774
            mMoreAdjust = true;
 
1775
            mState = ShiftStateOut;
 
1776
            cScreen->damageScreen ();
 
1777
        }
 
1778
    }
 
1779
}
 
1780
 
 
1781
void
 
1782
ShiftScreen::handleEvent (XEvent      *event)
 
1783
{
 
1784
    screen->handleEvent (event);
 
1785
 
 
1786
    switch (event->type) {
 
1787
    case PropertyNotify:
 
1788
        if (event->xproperty.atom == XA_WM_NAME)
 
1789
        {
 
1790
            CompWindow *w;
 
1791
            w = screen->findWindow (event->xproperty.window);
 
1792
            if (w)
 
1793
            {
 
1794
                if (mGrabIndex && (w->id () == mSelectedWindow))
 
1795
                {
 
1796
                    renderWindowTitle ();
 
1797
                    cScreen->damageScreen ();
 
1798
                }
 
1799
            }
 
1800
        }
 
1801
        break;
 
1802
    case UnmapNotify:
 
1803
        windowRemove (event->xunmap.window);
 
1804
        break;
 
1805
    case DestroyNotify:
 
1806
        windowRemove (event->xdestroywindow.window);
 
1807
        break;
 
1808
    case KeyPress:
 
1809
        if (mState == ShiftStateSwitching)
 
1810
        {
 
1811
            if (event->xkey.keycode == mLeftKey)
 
1812
                switchToWindow (false);
 
1813
            else if (event->xkey.keycode == mRightKey)
 
1814
                switchToWindow (true);
 
1815
            else if (event->xkey.keycode == mUpKey)
 
1816
                switchToWindow (false);
 
1817
            else if (event->xkey.keycode == mDownKey)
 
1818
                switchToWindow (true);
 
1819
        }
 
1820
 
 
1821
        break;
 
1822
    case ButtonPress:
 
1823
        if (mState == ShiftStateSwitching || mState == ShiftStateOut)
 
1824
        {
 
1825
            if (event->xbutton.button == Button5)
 
1826
                switchToWindow (false);
 
1827
            else if (event->xbutton.button == Button4)
 
1828
                switchToWindow (true);
 
1829
            if (event->xbutton.button == Button1)
 
1830
            {
 
1831
                mButtonPressTime = event->xbutton.time;
 
1832
                mButtonPressed   = true;
 
1833
                mStartX          = event->xbutton.x_root;
 
1834
                mStartY          = event->xbutton.y_root;
 
1835
                mStartTarget     = mMvTarget + mMvAdjust;
 
1836
            }
 
1837
        }
 
1838
 
 
1839
        break;
 
1840
    case ButtonRelease:
 
1841
        if (mState == ShiftStateSwitching || mState == ShiftStateOut)
 
1842
        {
 
1843
            if (event->xbutton.button == Button1 && mButtonPressed)
 
1844
            {
 
1845
                int iNew;
 
1846
                if ((int)(event->xbutton.time - mButtonPressTime) <
 
1847
                    optionGetClickDuration ())
 
1848
                    term (false);
 
1849
 
 
1850
                mButtonPressTime = 0;
 
1851
                mButtonPressed   = false;
 
1852
 
 
1853
                if (mMvTarget - floor (mMvTarget) >= 0.5)
 
1854
                {
 
1855
                    mMvAdjust = ceil(mMvTarget) - mMvTarget;
 
1856
                    iNew = ceil(mMvTarget);
 
1857
                }
 
1858
                else
 
1859
                {
 
1860
                    mMvAdjust = floor(mMvTarget) - mMvTarget;
 
1861
                    iNew = floor(mMvTarget);
 
1862
                }
 
1863
 
 
1864
                while (iNew < 0)
 
1865
                    iNew += mNWindows;
 
1866
                iNew = iNew % mNWindows;
 
1867
 
 
1868
                mSelectedWindow = mWindows[iNew]->id ();
 
1869
 
 
1870
                renderWindowTitle ();
 
1871
                mMoveAdjust = true;
 
1872
                cScreen->damageScreen ();
 
1873
            }
 
1874
 
 
1875
        }
 
1876
        break;
 
1877
    case MotionNotify:
 
1878
        if (mState == ShiftStateSwitching || mState == ShiftStateOut)
 
1879
        {
 
1880
            if (mButtonPressed)
 
1881
            {
 
1882
                CompRect oe = screen->outputDevs ()[mUsedOutput];
 
1883
                float div = 0;
 
1884
                int   wx  = 0;
 
1885
                int   wy  = 0;
 
1886
                int   iNew;
 
1887
 
 
1888
                switch (optionGetMode ())
 
1889
                {
 
1890
                    case ShiftOptions::ModeCover:
 
1891
                        div = event->xmotion.x_root - mStartX;
 
1892
                        div /= oe.width () / optionGetMouseSpeed ();
 
1893
                        break;
 
1894
                    case ShiftOptions::ModeFlip:
 
1895
                        div = event->xmotion.y_root - mStartY;
 
1896
                        div /= oe.height () / optionGetMouseSpeed ();
 
1897
                        break;
 
1898
                }
 
1899
 
 
1900
                mMvTarget = mStartTarget + div - mMvAdjust;
 
1901
                mMoveAdjust = true;
 
1902
                while (mMvTarget >= mNWindows)
 
1903
                {
 
1904
                    mMvTarget -= mNWindows;
 
1905
                    mInvert = !mInvert;
 
1906
                }
 
1907
 
 
1908
                while (mMvTarget < 0)
 
1909
                {
 
1910
                    mMvTarget += mNWindows;
 
1911
                    mInvert = !mInvert;
 
1912
                }
 
1913
 
 
1914
                if (mMvTarget - floor (mMvTarget) >= 0.5)
 
1915
                    iNew = ceil(mMvTarget);
 
1916
                else
 
1917
                    iNew = floor(mMvTarget);
 
1918
 
 
1919
                while (iNew < 0)
 
1920
                    iNew += mNWindows;
 
1921
                iNew = iNew % mNWindows;
 
1922
 
 
1923
                if (mSelectedWindow != mWindows[iNew]->id ())
 
1924
                {
 
1925
                    mSelectedWindow = mWindows[iNew]->id ();
 
1926
                    renderWindowTitle ();
 
1927
                }
 
1928
 
 
1929
                if (event->xmotion.x_root < 50)
 
1930
                    wx = 50;
 
1931
                if (screen->width () - event->xmotion.x_root < 50)
 
1932
                    wx = -50;
 
1933
                if (event->xmotion.y_root < 50)
 
1934
                    wy = 50;
 
1935
                if (screen->height () - event->xmotion.y_root < 50)
 
1936
                    wy = -50;
 
1937
                if (wx != 0 || wy != 0)
 
1938
                {
 
1939
                    screen->warpPointer (wx, wy);
 
1940
                    mStartX += wx;
 
1941
                    mStartY += wy;
 
1942
                }
 
1943
 
 
1944
                cScreen->damageScreen ();
 
1945
            }
 
1946
 
 
1947
        }
 
1948
        break;
 
1949
    }
 
1950
}
 
1951
 
 
1952
bool
 
1953
ShiftWindow::damageRect (bool initial,
 
1954
                         const CompRect &rect)
 
1955
{
 
1956
    bool status = false;
 
1957
 
 
1958
    SHIFT_SCREEN (screen);
 
1959
 
 
1960
    if (initial)
 
1961
    {
 
1962
        if (ss->mGrabIndex && isShiftable ())
 
1963
        {
 
1964
            ss->addWindowToList (window);
 
1965
            if (ss->updateWindowList ())
 
1966
            {
 
1967
                mActive = true;
 
1968
                ss->mMoreAdjust = true;
 
1969
                ss->mState = ShiftStateOut;
 
1970
                ss->cScreen->damageScreen ();
 
1971
            }
 
1972
        }
 
1973
    }
 
1974
    else if (ss->mState == ShiftStateSwitching)
 
1975
    {
 
1976
        if (mActive)
 
1977
        {
 
1978
            ss->cScreen->damageScreen ();
 
1979
            status = true;
 
1980
        }
 
1981
    }
 
1982
 
 
1983
    status |= cWindow->damageRect (initial, rect);
 
1984
 
 
1985
    return status;
 
1986
}
 
1987
 
 
1988
ShiftScreen::ShiftScreen (CompScreen *screen) :
 
1989
    PluginClassHandler <ShiftScreen, CompScreen> (screen),
 
1990
    cScreen (CompositeScreen::get (screen)),
 
1991
    gScreen (GLScreen::get (screen)),
 
1992
    mLeftKey (XKeysymToKeycode (screen->dpy (), XStringToKeysym ("Left"))),
 
1993
    mRightKey (XKeysymToKeycode (screen->dpy (), XStringToKeysym ("Right"))),
 
1994
    mUpKey (XKeysymToKeycode (screen->dpy (), XStringToKeysym ("Up"))),
 
1995
    mDownKey (XKeysymToKeycode (screen->dpy (), XStringToKeysym ("Down"))),
 
1996
    mGrabIndex (0),
 
1997
    mState (ShiftStateNone),
 
1998
    mMoreAdjust (false),
 
1999
    mMvTarget (0),
 
2000
    mMvVelocity (0),
 
2001
    mInvert (false),
 
2002
    mCursor (XCreateFontCursor (screen->dpy (), XC_left_ptr)),
 
2003
    mWindows (NULL),
 
2004
    mNWindows (0),
 
2005
    mWindowsSize (0),
 
2006
    mDrawSlots (NULL),
 
2007
    mNSlots (0),
 
2008
    mSlotsSize (0),
 
2009
    mActiveSlot (NULL),
 
2010
    mSelectedWindow (0),
 
2011
    mCurrentMatch (NULL),
 
2012
    mUsedOutput (0),
 
2013
    mAnim (0.0),
 
2014
    mAnimVelocity (0.0),
 
2015
    mButtonPressTime (0),
 
2016
    mButtonPressed (false),
 
2017
    mStartX (0),
 
2018
    mStartY (0),
 
2019
    mStartTarget (0.0f)
 
2020
{
 
2021
    ScreenInterface::setHandler (screen, false);
 
2022
    CompositeScreenInterface::setHandler (cScreen, false);
 
2023
    GLScreenInterface::setHandler (gScreen, false);
 
2024
 
 
2025
#define SHIFTINITBIND(opt, func)                                \
 
2026
    optionSet##opt##Initiate (boost::bind (&ShiftScreen::func, \
 
2027
                                            this, _1, _2, _3));
 
2028
 
 
2029
#define SHIFTTERMBIND(opt, func)                                \
 
2030
    optionSet##opt##Terminate (boost::bind (&ShiftScreen::func, \
 
2031
                                            this, _1, _2, _3));
 
2032
 
 
2033
#define SHIFTSWITCHBIND(opt, func, next, type)                 \
 
2034
    optionSet##opt##Initiate (boost::bind (&ShiftScreen::func, \
 
2035
                                            this, _1, _2, _3, \
 
2036
                                            next, type));
 
2037
 
 
2038
    /* Key actions */
 
2039
 
 
2040
    SHIFTINITBIND (InitiateKey, initiate);
 
2041
    SHIFTINITBIND (InitiateAllKey, initiateAll);
 
2042
 
 
2043
    SHIFTSWITCHBIND (NextKey, doSwitch, true, ShiftTypeNormal);
 
2044
    SHIFTSWITCHBIND (PrevKey, doSwitch, false, ShiftTypeNormal);
 
2045
    SHIFTSWITCHBIND (NextAllKey, doSwitch, true, ShiftTypeAll);
 
2046
    SHIFTSWITCHBIND (PrevAllKey, doSwitch, false, ShiftTypeAll);
 
2047
    SHIFTSWITCHBIND (NextGroupKey, doSwitch, true, ShiftTypeGroup);
 
2048
    SHIFTSWITCHBIND (PrevGroupKey, doSwitch, false, ShiftTypeGroup);
 
2049
 
 
2050
    SHIFTTERMBIND (NextKey, terminate);
 
2051
    SHIFTTERMBIND (PrevKey, terminate);
 
2052
    SHIFTTERMBIND (NextAllKey, terminate);
 
2053
    SHIFTTERMBIND (PrevAllKey, terminate);
 
2054
    SHIFTTERMBIND (NextGroupKey, terminate);
 
2055
    SHIFTTERMBIND (PrevGroupKey, terminate);
 
2056
 
 
2057
    SHIFTTERMBIND (InitiateKey, terminate);
 
2058
    SHIFTTERMBIND (InitiateAllKey, terminate);
 
2059
 
 
2060
    /* Button Actions */
 
2061
 
 
2062
    SHIFTINITBIND (InitiateButton, initiate);
 
2063
    SHIFTINITBIND (InitiateAllButton, initiateAll);
 
2064
 
 
2065
    SHIFTSWITCHBIND (NextButton, doSwitch, true, ShiftTypeNormal);
 
2066
    SHIFTSWITCHBIND (PrevButton, doSwitch, false, ShiftTypeNormal);
 
2067
    SHIFTSWITCHBIND (NextAllButton, doSwitch, true, ShiftTypeAll);
 
2068
    SHIFTSWITCHBIND (PrevAllButton, doSwitch, false, ShiftTypeAll);
 
2069
    SHIFTSWITCHBIND (NextGroupButton, doSwitch, true, ShiftTypeGroup);
 
2070
    SHIFTSWITCHBIND (PrevGroupButton, doSwitch, false, ShiftTypeGroup);
 
2071
 
 
2072
    SHIFTTERMBIND (NextButton, terminate);
 
2073
    SHIFTTERMBIND (PrevButton, terminate);
 
2074
    SHIFTTERMBIND (NextAllButton, terminate);
 
2075
    SHIFTTERMBIND (PrevAllButton, terminate);
 
2076
    SHIFTTERMBIND (NextGroupButton, terminate);
 
2077
    SHIFTTERMBIND (PrevGroupButton, terminate);
 
2078
 
 
2079
    SHIFTTERMBIND (InitiateButton, terminate);
 
2080
    SHIFTTERMBIND (InitiateAllButton, terminate);
 
2081
 
 
2082
    /* Edge Actions */
 
2083
 
 
2084
    SHIFTINITBIND (InitiateEdge, initiate);
 
2085
    SHIFTINITBIND (InitiateAllEdge, initiateAll);
 
2086
    SHIFTTERMBIND (InitiateEdge, terminate);
 
2087
    SHIFTTERMBIND (InitiateAllEdge, terminate);
 
2088
}
 
2089
 
 
2090
ShiftScreen::~ShiftScreen ()
 
2091
{
 
2092
    freeWindowTitle ();
 
2093
 
 
2094
    XFreeCursor (screen->dpy (), mCursor);
 
2095
 
 
2096
    if (mWindows)
 
2097
        free (mWindows);
 
2098
 
 
2099
    if (mDrawSlots)
 
2100
        free (mDrawSlots);
 
2101
 
 
2102
}
 
2103
 
 
2104
ShiftWindow::ShiftWindow (CompWindow *window) :
 
2105
    PluginClassHandler <ShiftWindow, CompWindow> (window),
 
2106
    window (window),
 
2107
    cWindow (CompositeWindow::get (window)),
 
2108
    gWindow (GLWindow::get (window)),
 
2109
    mOpacity (1.0),
 
2110
    mBrightness (1.0),
 
2111
    mOpacityVelocity (0.0f),
 
2112
    mBrightnessVelocity (0.0f),
 
2113
    mActive (false)
 
2114
{
 
2115
    CompositeWindowInterface::setHandler (cWindow, false);
 
2116
    GLWindowInterface::setHandler (gWindow, false);
 
2117
 
 
2118
    mSlots[0].scale = 1.0;
 
2119
    mSlots[1].scale = 1.0;
 
2120
}
 
2121
 
 
2122
ShiftWindow::~ShiftWindow ()
 
2123
{
 
2124
}
 
2125
 
 
2126
bool
 
2127
ShiftPluginVTable::init ()
 
2128
{
 
2129
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) ||
 
2130
        !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) ||
 
2131
        !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
 
2132
        return false;
 
2133
 
 
2134
    if (!CompPlugin::checkPluginABI ("text", COMPIZ_TEXT_ABI))
 
2135
    {
 
2136
        compLogMessage ("shift", CompLogLevelWarn, "No compatible text plugin"\
 
2137
                                                   " loaded");
 
2138
        textAvailable = false;
 
2139
    }
 
2140
    else
 
2141
        textAvailable = true;
 
2142
 
 
2143
    return true;
 
2144
}