~unity-team/compiz/plugins-main-trunk.fix_wrong_window_move_expo

« back to all changes in this revision

Viewing changes to scaleaddon/src/scaleaddon.cpp

  • Committer: David Barth
  • Date: 2011-03-29 16:36:40 UTC
  • Revision ID: david.barth@canonical.com-20110329163640-fpen5qsoo0lbjode
initial import from compiz-plugins-main_0.9.4git20110322.orig.tar.gz

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 * Compiz scale plugin addon plugin
 
4
 *
 
5
 * scaleaddon.cpp
 
6
 *
 
7
 * Copyright : (C) 2007 by Danny Baumann
 
8
 * E-mail    : maniac@opencompositing.org
 
9
 *
 
10
 * Organic scale mode taken from Beryl's scale.c, written by
 
11
 * Copyright : (C) 2006 Diogo Ferreira
 
12
 * E-mail    : diogo@underdev.org
 
13
 *
 
14
 * Ported to Compiz 0.9 by:
 
15
 * Copyright : (C) 2009 by 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
 
 
31
#include "scaleaddon.h"
 
32
#include <iostream>
 
33
 
 
34
COMPIZ_PLUGIN_20090315 (scaleaddon, ScaleAddonPluginVTable);
 
35
 
 
36
bool textAvailable;
 
37
 
 
38
void
 
39
ScaleAddonWindow::renderTitle ()
 
40
{
 
41
    CompText::Attrib attrib;
 
42
    float            scale;
 
43
    int              titleOpt;
 
44
 
 
45
    ADDON_SCREEN (screen);
 
46
 
 
47
    if (!textAvailable)
 
48
        return;
 
49
 
 
50
    text.clear ();
 
51
 
 
52
    if (!sWindow->hasSlot ())
 
53
        return;
 
54
 
 
55
    titleOpt = as->optionGetWindowTitle ();
 
56
 
 
57
    if (titleOpt == ScaleaddonOptions::WindowTitleNoDisplay)
 
58
        return;
 
59
 
 
60
    if (titleOpt == ScaleaddonOptions::WindowTitleHighlightedWindowOnly &&
 
61
        as->highlightedWindow != window->id ())
 
62
    {
 
63
        return;
 
64
    }
 
65
 
 
66
    scale = sWindow->getSlot ().scale;
 
67
    attrib.maxWidth = window->width () * scale;
 
68
    attrib.maxHeight = window->height () * scale;
 
69
 
 
70
    attrib.family = "Sans";
 
71
    attrib.size = as->optionGetTitleSize ();
 
72
    attrib.color[0] = as->optionGetFontColorRed ();
 
73
    attrib.color[1] = as->optionGetFontColorGreen ();
 
74
    attrib.color[2] = as->optionGetFontColorBlue ();
 
75
    attrib.color[3] = as->optionGetFontColorAlpha ();
 
76
 
 
77
    attrib.flags = CompText::WithBackground | CompText::Ellipsized;
 
78
    if (as->optionGetTitleBold ())
 
79
        attrib.flags |= CompText::StyleBold;
 
80
 
 
81
    attrib.bgHMargin = as->optionGetBorderSize ();
 
82
    attrib.bgVMargin = as->optionGetBorderSize ();
 
83
    attrib.bgColor[0] = as->optionGetBackColorRed ();
 
84
    attrib.bgColor[1] = as->optionGetBackColorGreen ();
 
85
    attrib.bgColor[2] = as->optionGetBackColorBlue ();
 
86
    attrib.bgColor[3] = as->optionGetBackColorAlpha ();
 
87
 
 
88
    text.renderWindowTitle (window->id (),
 
89
                            as->sScreen->getType () == ScaleTypeAll,
 
90
                            attrib);
 
91
}
 
92
 
 
93
void
 
94
ScaleAddonWindow::drawTitle ()
 
95
{
 
96
    float         x, y, width, height;
 
97
    ScalePosition pos = sWindow->getCurrentPosition ();
 
98
    CompRect      geom = window->borderRect ();
 
99
 
 
100
    width  = text.getWidth ();
 
101
    height = text.getHeight ();
 
102
 
 
103
    x = pos.x () + window->x () + geom.width () * pos.scale / 2 - width / 2;
 
104
    y = pos.y () + window->y () + geom.height () * pos.scale / 2 - height / 2;
 
105
 
 
106
    text.draw (floor (x), floor (y), 1.0f);
 
107
}
 
108
 
 
109
void
 
110
ScaleAddonWindow::drawHighlight ()
 
111
{
 
112
    GLboolean     wasBlend;
 
113
    GLint         oldBlendSrc, oldBlendDst;
 
114
    float         x, y, width, height;
 
115
    ScalePosition pos = sWindow->getCurrentPosition ();
 
116
    CompRect      geom = window->borderRect ();
 
117
 
 
118
    ADDON_SCREEN (screen);
 
119
 
 
120
    if (rescaled)
 
121
        return;
 
122
 
 
123
    x      = pos.x () + window->x () - (window->border ().left * pos.scale);
 
124
    y      = pos.y () + window->y () - (window->border ().top * pos.scale);
 
125
    width  = geom.width () * pos.scale;
 
126
    height = geom.height () * pos.scale;
 
127
 
 
128
    /* we use a poor replacement for roundf()
 
129
     * (available in C99 only) here */
 
130
    x = floor (x + 0.5f);
 
131
    y = floor (y + 0.5f);
 
132
 
 
133
    wasBlend = glIsEnabled (GL_BLEND);
 
134
    glGetIntegerv (GL_BLEND_SRC, &oldBlendSrc);
 
135
    glGetIntegerv (GL_BLEND_DST, &oldBlendDst);
 
136
 
 
137
    if (!wasBlend)
 
138
        glEnable (GL_BLEND);
 
139
 
 
140
    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
141
 
 
142
    glColor4us (as->optionGetHighlightColorRed (),
 
143
                as->optionGetHighlightColorGreen (),
 
144
                as->optionGetHighlightColorBlue (),
 
145
                as->optionGetHighlightColorAlpha ());
 
146
 
 
147
    glRectf (x, y + height, x + width, y);
 
148
 
 
149
    glColor4usv (defaultColor);
 
150
 
 
151
    if (!wasBlend)
 
152
        glDisable (GL_BLEND);
 
153
    glBlendFunc (oldBlendSrc, oldBlendDst);
 
154
}
 
155
 
 
156
void
 
157
ScaleAddonScreen::checkWindowHighlight ()
 
158
{
 
159
    if (highlightedWindow != lastHighlightedWindow)
 
160
    {
 
161
        CompWindow *w;
 
162
 
 
163
        w = screen->findWindow (highlightedWindow);
 
164
        if (w)
 
165
        {
 
166
            ADDON_WINDOW (w);
 
167
            aw->renderTitle ();
 
168
            aw->cWindow->addDamage ();
 
169
        }
 
170
 
 
171
        w = screen->findWindow (lastHighlightedWindow);
 
172
        if (w)
 
173
        {
 
174
            ADDON_WINDOW (w);
 
175
            aw->renderTitle ();
 
176
            aw->cWindow->addDamage (w);
 
177
        }
 
178
 
 
179
        lastHighlightedWindow = highlightedWindow;
 
180
    }
 
181
}
 
182
 
 
183
bool
 
184
ScaleAddonScreen::closeWindow (CompAction         *action,
 
185
                               CompAction::State  state,
 
186
                               CompOption::Vector options)
 
187
{
 
188
    CompWindow *w;
 
189
 
 
190
    if (!sScreen->hasGrab ())
 
191
        return false;
 
192
 
 
193
    w = screen->findWindow (highlightedWindow);
 
194
    if (w)
 
195
        w->close (screen->getCurrentTime ());
 
196
 
 
197
    return true;
 
198
}
 
199
 
 
200
bool
 
201
ScaleAddonScreen::pullWindow (CompAction         *action,
 
202
                              CompAction::State  state,
 
203
                              CompOption::Vector options)
 
204
{
 
205
    CompWindow *w;
 
206
 
 
207
    if (!sScreen->hasGrab ())
 
208
        return false;
 
209
 
 
210
    w = screen->findWindow (highlightedWindow);
 
211
    if (w)
 
212
    {
 
213
        int       x, y, xOffset, yOffset;
 
214
        CompPoint vp;
 
215
 
 
216
        vp = w->defaultViewport ();
 
217
 
 
218
        xOffset = (screen->vp ().x () - vp.x ()) * screen->width ();
 
219
        yOffset = (screen->vp ().y () - vp.y ()) * screen->height ();
 
220
 
 
221
        x = w->x () + xOffset;
 
222
        y = w->y () + yOffset;
 
223
 
 
224
        if (optionGetConstrainPullToScreen ())
 
225
        {
 
226
            CompRect workArea, extents;
 
227
 
 
228
            workArea = screen->outputDevs ()[w->outputDevice ()].workArea ();
 
229
            extents  = w->borderRect ();
 
230
 
 
231
            extents.setX (extents.x () + xOffset);
 
232
            extents.setY (extents.y () + yOffset);
 
233
 
 
234
            if (extents.x1 () < workArea.x1 ())
 
235
                x += workArea.x1 () - extents.x1 ();
 
236
            else if (extents.x2 () > workArea.x2 ())
 
237
                x += workArea.x2 () - extents.x2 ();
 
238
 
 
239
            if (extents.y1 () < workArea.y1 ())
 
240
                y += workArea.y1 () - extents.y1 ();
 
241
            else if (extents.y2 () > workArea.y2 ())
 
242
                y += workArea.y2 () - extents.y2 ();
 
243
        }
 
244
 
 
245
        if (x != w->x () || y != w->y ())
 
246
        {
 
247
            ScalePosition pos, oldPos;
 
248
            ADDON_WINDOW (w);
 
249
 
 
250
            oldPos = aw->sWindow->getCurrentPosition ();
 
251
 
 
252
            w->moveToViewportPosition (x, y, true);
 
253
 
 
254
            /* Select this window when ending scale */
 
255
            aw->sWindow->scaleSelectWindow ();
 
256
 
 
257
            /* stop scaled window dissapearing */
 
258
            pos.setX (oldPos.x () - xOffset);
 
259
            pos.setY (oldPos.y () - yOffset);
 
260
 
 
261
            if (optionGetExitAfterPull ())
 
262
            {
 
263
                CompAction         *action;
 
264
                CompOption::Vector o;
 
265
                CompOption         *opt;
 
266
 
 
267
                o.push_back (CompOption ("root", CompOption::TypeInt));
 
268
                o[0].value ().set ((int) screen->root ());
 
269
 
 
270
                opt = CompOption::findOption (sScreen->getOptions (),
 
271
                                              "initiate_key", 0);
 
272
                action = &opt->value ().action ();
 
273
 
 
274
                if (action->terminate ())
 
275
                    action->terminate () (action, 0, o);
 
276
            }
 
277
            else
 
278
            {
 
279
                ScaleSlot slot = aw->sWindow->getSlot ();
 
280
 
 
281
                /* provide a simple animation */
 
282
                aw->cWindow->addDamage ();
 
283
 
 
284
                pos.setX (oldPos.x () -  slot.width () / 20);
 
285
                pos.setY (oldPos.y () - slot.height () / 20);
 
286
                pos.scale = oldPos.scale * 1.1f;
 
287
 
 
288
                aw->sWindow->setCurrentPosition (pos);
 
289
 
 
290
                aw->cWindow->addDamage ();
 
291
            }
 
292
        }
 
293
    }
 
294
 
 
295
    return true;
 
296
}
 
297
 
 
298
bool
 
299
ScaleAddonScreen::zoomWindow (CompAction         *action,
 
300
                              CompAction::State  state,
 
301
                              CompOption::Vector options)
 
302
{
 
303
    CompWindow *w;
 
304
 
 
305
    if (!sScreen->hasGrab ())
 
306
        return false;
 
307
 
 
308
    w = screen->findWindow (highlightedWindow);
 
309
    if (w)
 
310
    {
 
311
        CompRect output;
 
312
        int      head;
 
313
 
 
314
        ADDON_WINDOW (w);
 
315
 
 
316
        if (!aw->sWindow->hasSlot ())
 
317
            return false;
 
318
 
 
319
        head   = screen->outputDeviceForPoint (aw->sWindow->getSlot ().pos ());
 
320
        output = screen->outputDevs ()[head];
 
321
 
 
322
        /* damage old rect */
 
323
        aw->cWindow->addDamage ();
 
324
 
 
325
        if (!aw->rescaled)
 
326
        {
 
327
            ScaleSlot slot = aw->sWindow->getSlot ();
 
328
            int       x1, x2, y1, y2;
 
329
            CompRect  geom = w->borderRect ();
 
330
 
 
331
            aw->oldAbove = w->next;
 
332
            w->raise ();
 
333
 
 
334
            /* backup old values */
 
335
            aw->origSlot = slot;
 
336
            aw->rescaled = true;
 
337
 
 
338
            x1 = output.centerX () - geom.width () / 2 + w->border ().left;
 
339
            y1 = output.centerY () - geom.height () / 2 + w->border ().top;
 
340
            x2 = slot.x () + geom.width ();
 
341
            y2 = slot.y () + geom.height ();
 
342
 
 
343
            slot.scale = 1.0f;
 
344
            slot.setGeometry (x1, y1, x2 - x1, y2 - y1);
 
345
 
 
346
            aw->sWindow->setSlot (slot);
 
347
        }
 
348
        else
 
349
        {
 
350
            if (aw->oldAbove)
 
351
                w->restackBelow (aw->oldAbove);
 
352
 
 
353
            aw->rescaled = false;
 
354
            aw->sWindow->setSlot (aw->origSlot);
 
355
        }
 
356
 
 
357
        /* slot size may have changed, so
 
358
         * update window title */
 
359
        aw->renderTitle ();
 
360
 
 
361
        aw->cWindow->addDamage ();
 
362
    }
 
363
 
 
364
    return true;
 
365
}
 
366
 
 
367
void
 
368
ScaleAddonScreen::handleEvent (XEvent *event)
 
369
{
 
370
    screen->handleEvent (event);
 
371
 
 
372
    switch (event->type)
 
373
    {
 
374
    case PropertyNotify:
 
375
        if (event->xproperty.atom == XA_WM_NAME && sScreen->hasGrab ())
 
376
        {
 
377
            CompWindow *w;
 
378
 
 
379
            w = screen->findWindow (event->xproperty.window);
 
380
            if (w)
 
381
            {
 
382
                ADDON_WINDOW (w);
 
383
                aw->renderTitle ();
 
384
                aw->cWindow->addDamage ();
 
385
            }
 
386
        }
 
387
        break;
 
388
    case MotionNotify:
 
389
        if (sScreen->hasGrab ())
 
390
        {
 
391
            highlightedWindow = sScreen->getHoveredWindow ();
 
392
            checkWindowHighlight ();
 
393
        }
 
394
        break;
 
395
    default:
 
396
        break;
 
397
    }
 
398
}
 
399
 
 
400
void
 
401
ScaleAddonWindow::scalePaintDecoration (const GLWindowPaintAttrib &attrib,
 
402
                                        const GLMatrix            &transform,
 
403
                                        const CompRegion          &region,
 
404
                                        unsigned int              mask)
 
405
{
 
406
    ScaleScreen::State state;
 
407
 
 
408
    ADDON_SCREEN (screen);
 
409
 
 
410
    state = as->sScreen->getState ();
 
411
    sWindow->scalePaintDecoration (attrib, transform, region, mask);
 
412
 
 
413
    if (state == ScaleScreen::Wait || state == ScaleScreen::Out)
 
414
    {
 
415
        if (as->optionGetWindowHighlight ())
 
416
        {
 
417
            if (window->id () == as->highlightedWindow)
 
418
                drawHighlight ();
 
419
        }
 
420
 
 
421
        if (textAvailable)
 
422
            drawTitle ();
 
423
    }
 
424
}
 
425
 
 
426
void
 
427
ScaleAddonWindow::scaleSelectWindow ()
 
428
{
 
429
    ADDON_SCREEN (screen);
 
430
 
 
431
    as->highlightedWindow = window->id ();
 
432
    as->checkWindowHighlight ();
 
433
 
 
434
    sWindow->scaleSelectWindow ();
 
435
}
 
436
 
 
437
void
 
438
ScaleAddonScreen::donePaint ()
 
439
{
 
440
    ScaleScreen::State state = sScreen->getState ();
 
441
 
 
442
    if (state != ScaleScreen::Idle && lastState == ScaleScreen::Idle)
 
443
    {
 
444
        foreach (CompWindow *w, screen->windows ())
 
445
            ScaleAddonWindow::get (w)->renderTitle ();
 
446
    }
 
447
    else if (state == ScaleScreen::Idle && lastState != ScaleScreen::Idle)
 
448
    {
 
449
        foreach (CompWindow *w, screen->windows ())
 
450
            ScaleAddonWindow::get (w)->text.clear ();
 
451
    }
 
452
 
 
453
    if (state == ScaleScreen::Out && lastState != ScaleScreen::Out)
 
454
    {
 
455
        lastHighlightedWindow = None;
 
456
        checkWindowHighlight ();
 
457
    }
 
458
 
 
459
    lastState = state;
 
460
 
 
461
    cScreen->donePaint ();
 
462
}
 
463
 
 
464
void
 
465
ScaleAddonScreen::handleCompizEvent (const char         *pluginName,
 
466
                                     const char         *eventName,
 
467
                                     CompOption::Vector &options)
 
468
{
 
469
    screen->handleCompizEvent (pluginName, eventName, options);
 
470
 
 
471
    if ((strcmp (pluginName, "scale") == 0) &&
 
472
        (strcmp (eventName, "activate") == 0))
 
473
    {
 
474
        bool activated =
 
475
            CompOption::getBoolOptionNamed (options, "active", false);
 
476
 
 
477
        if (activated)
 
478
        {
 
479
            screen->addAction (&optionGetCloseKey ());
 
480
            screen->addAction (&optionGetZoomKey ());
 
481
            screen->addAction (&optionGetPullKey ());
 
482
            screen->addAction (&optionGetCloseButton ());
 
483
            screen->addAction (&optionGetZoomButton ());
 
484
            screen->addAction (&optionGetPullButton ());
 
485
 
 
486
            /* TODO: or better
 
487
               ad->highlightedWindow     = sd->selectedWindow;
 
488
               here? do we want to show up the highlight without
 
489
               mouse move initially? */
 
490
 
 
491
            highlightedWindow     = None;
 
492
            lastHighlightedWindow = None;
 
493
            checkWindowHighlight ();
 
494
        }
 
495
        else
 
496
        {
 
497
            foreach (CompWindow *w, screen->windows ())
 
498
            {
 
499
                ADDON_WINDOW (w);
 
500
                aw->rescaled = false;
 
501
            }
 
502
 
 
503
            screen->removeAction (&optionGetCloseKey ());
 
504
            screen->removeAction (&optionGetZoomKey ());
 
505
            screen->removeAction (&optionGetPullKey ());
 
506
            screen->removeAction (&optionGetCloseButton ());
 
507
            screen->removeAction (&optionGetZoomButton ());
 
508
            screen->removeAction (&optionGetPullButton ());
 
509
        }
 
510
    }
 
511
}
 
512
 
 
513
/**
 
514
 * experimental organic layout method
 
515
 * inspired by smallwindows (smallwindows.sf.net) by Jens Egeblad
 
516
 * FIXME: broken.
 
517
 * */
 
518
#define ORGANIC_STEP 0.05
 
519
#if 0
 
520
static int
 
521
organicCompareWindows (const void *elem1,
 
522
                       const void *elem2)
 
523
{
 
524
    CompWindow *w1 = *((CompWindow **) elem1);
 
525
    CompWindow *w2 = *((CompWindow **) elem2);
 
526
 
 
527
    return (WIN_X (w1) + WIN_Y (w1)) - (WIN_X (w2) + WIN_Y (w2));
 
528
}
 
529
 
 
530
static double
 
531
layoutOrganicCalculateOverlap (CompScreen *s,
 
532
                               int        win,
 
533
                               int        x,
 
534
                               int        y)
 
535
{
 
536
    int    i;
 
537
    int    x1, y1, x2, y2;
 
538
    int    overlapX, overlapY;
 
539
    int    xMin, xMax, yMin, yMax;
 
540
    double result = -0.01;
 
541
 
 
542
    SCALE_SCREEN ();
 
543
    ADDON_SCREEN ();
 
544
 
 
545
    x1 = x;
 
546
    y1 = y;
 
547
    x2 = x1 + WIN_W (ss->windows[win]) * as->scale;
 
548
    y2 = y1 + WIN_H (ss->windows[win]) * as->scale;
 
549
 
 
550
    for (i = 0; i < ss->nWindows; i++)
 
551
    {
 
552
        if (i == win)
 
553
            continue;
 
554
 
 
555
        overlapX = overlapY = 0;
 
556
        xMax = MAX (ss->slots[i].x1, x1);
 
557
        xMin = MIN (ss->slots[i].x1 + WIN_W (ss->windows[i]) * as->scale, x2);
 
558
        if (xMax <= xMin)
 
559
            overlapX = xMin - xMax;
 
560
 
 
561
        yMax = MAX (ss->slots[i].y1, y1);
 
562
        yMin = MIN (ss->slots[i].y1 + WIN_H (ss->windows[i]) * as->scale, y2);
 
563
 
 
564
        if (yMax <= yMin)
 
565
            overlapY = yMin - yMax;
 
566
 
 
567
        result += (double)overlapX * overlapY;
 
568
    }
 
569
 
 
570
    return result;
 
571
}
 
572
 
 
573
static double
 
574
layoutOrganicFindBestHorizontalPosition (CompScreen *s,
 
575
                                         int        win,
 
576
                                         int        *bestX,
 
577
                                         int        areaWidth)
 
578
{
 
579
    int    i, y1, y2, w;
 
580
    double bestOverlap = 1e31, overlap;
 
581
 
 
582
    SCALE_SCREEN ();
 
583
    ADDON_SCREEN ();
 
584
 
 
585
    y1 = ss->slots[win].y1;
 
586
    y2 = ss->slots[win].y1 + WIN_H (ss->windows[win]) * as->scale;
 
587
 
 
588
    w = WIN_W (ss->windows[win]) * as->scale;
 
589
    *bestX = ss->slots[win].x1;
 
590
 
 
591
    for (i = 0; i < ss->nWindows; i++)
 
592
    {
 
593
        CompWindow *lw = ss->windows[i];
 
594
        if (i == win)
 
595
            continue;
 
596
 
 
597
        if (ss->slots[i].y1 < y2 &&
 
598
            ss->slots[i].y1 + WIN_H (lw) * as->scale > y1)
 
599
        {
 
600
            if (ss->slots[i].x1 - w >= 0)
 
601
            {
 
602
                double overlap;
 
603
                
 
604
                overlap = layoutOrganicCalculateOverlap (s, win,
 
605
                                                         ss->slots[i].x1 - w,
 
606
                                                         y1);
 
607
 
 
608
                if (overlap < bestOverlap)
 
609
                {
 
610
                    *bestX = ss->slots[i].x1 - w;
 
611
                    bestOverlap = overlap;
 
612
                }
 
613
            }
 
614
            if (WIN_W (lw) * as->scale + ss->slots[i].x1 + w < areaWidth)
 
615
            {
 
616
                double overlap;
 
617
                
 
618
                overlap = layoutOrganicCalculateOverlap (s, win,
 
619
                                                         ss->slots[i].x1 +
 
620
                                                         WIN_W (lw) * as->scale,
 
621
                                                         y1);
 
622
 
 
623
                if (overlap < bestOverlap)
 
624
                {
 
625
                    *bestX = ss->slots[i].x1 + WIN_W (lw) * as->scale;
 
626
                    bestOverlap = overlap;
 
627
                }
 
628
            }
 
629
        }
 
630
    }
 
631
 
 
632
    overlap = layoutOrganicCalculateOverlap (s, win, 0, y1);
 
633
    if (overlap < bestOverlap)
 
634
    {
 
635
        *bestX = 0;
 
636
        bestOverlap = overlap;
 
637
    }
 
638
 
 
639
    overlap = layoutOrganicCalculateOverlap (s, win, areaWidth - w, y1);
 
640
    if (overlap < bestOverlap)
 
641
    {
 
642
        *bestX = areaWidth - w;
 
643
        bestOverlap = overlap;
 
644
    }
 
645
 
 
646
    return bestOverlap;
 
647
}
 
648
 
 
649
static double
 
650
layoutOrganicFindBestVerticalPosition (CompScreen *s,
 
651
                                       int        win,
 
652
                                       int        *bestY,
 
653
                                       int        areaHeight)
 
654
{
 
655
    int    i, x1, x2, h;
 
656
    double bestOverlap = 1e31, overlap;
 
657
 
 
658
    SCALE_SCREEN ();
 
659
    ADDON_SCREEN ();
 
660
 
 
661
    x1 = ss->slots[win].x1;
 
662
    x2 = ss->slots[win].x1 + WIN_W (ss->windows[win]) * as->scale;
 
663
    h = WIN_H (ss->windows[win]) * as->scale;
 
664
    *bestY = ss->slots[win].y1;
 
665
 
 
666
    for (i = 0; i < ss->nWindows; i++)
 
667
    {
 
668
        CompWindow *w = ss->windows[i];
 
669
 
 
670
        if (i == win)
 
671
            continue;
 
672
 
 
673
        if (ss->slots[i].x1 < x2 &&
 
674
            ss->slots[i].x1 + WIN_W (w) * as->scale > x1)
 
675
        {
 
676
            if (ss->slots[i].y1 - h >= 0 && ss->slots[i].y1 < areaHeight)
 
677
            {
 
678
                double overlap;
 
679
                overlap = layoutOrganicCalculateOverlap (s, win, x1,
 
680
                                                         ss->slots[i].y1 - h);
 
681
                if (overlap < bestOverlap)
 
682
                {
 
683
                    *bestY = ss->slots[i].y1 - h;
 
684
                    bestOverlap = overlap;
 
685
                }
 
686
            }
 
687
            if (WIN_H (w) * as->scale + ss->slots[i].y1 > 0 &&
 
688
                WIN_H (w) * as->scale + h + ss->slots[i].y1 < areaHeight)
 
689
            {
 
690
                double overlap;
 
691
                
 
692
                overlap = layoutOrganicCalculateOverlap (s, win, x1,
 
693
                                                         WIN_H (w) * as->scale +
 
694
                                                         ss->slots[i].y1);
 
695
 
 
696
                if (overlap < bestOverlap)
 
697
                {
 
698
                    *bestY = ss->slots[i].y1 + WIN_H(w) * as->scale;
 
699
                    bestOverlap = overlap;
 
700
                }
 
701
            }
 
702
        }
 
703
    }
 
704
 
 
705
    overlap = layoutOrganicCalculateOverlap (s, win, x1, 0);
 
706
    if (overlap < bestOverlap)
 
707
    {
 
708
        *bestY = 0;
 
709
        bestOverlap = overlap;
 
710
    }
 
711
 
 
712
    overlap = layoutOrganicCalculateOverlap (s, win, x1, areaHeight - h);
 
713
    if (overlap < bestOverlap)
 
714
    {
 
715
        *bestY = areaHeight - h;
 
716
        bestOverlap = overlap;
 
717
    }
 
718
 
 
719
    return bestOverlap;
 
720
}
 
721
 
 
722
static bool
 
723
layoutOrganicLocalSearch (CompScreen *s,
 
724
                          int        areaWidth,
 
725
                          int        areaHeight)
 
726
{
 
727
    bool   improvement;
 
728
    int    i;
 
729
    double totalOverlap;
 
730
 
 
731
    SCALE_SCREEN ();
 
732
 
 
733
    do
 
734
    {
 
735
        improvement = false;
 
736
        for (i = 0; i < ss->nWindows; i++)
 
737
        {
 
738
            bool improved;
 
739
 
 
740
            do
 
741
            {
 
742
                int    newX, newY;
 
743
                double oldOverlap, overlapH, overlapV;
 
744
 
 
745
                improved = false;
 
746
                oldOverlap = layoutOrganicCalculateOverlap (s, i,
 
747
                                                            ss->slots[i].x1,
 
748
                                                            ss->slots[i].y1);
 
749
 
 
750
                overlapH = layoutOrganicFindBestHorizontalPosition (s, i,
 
751
                                                                    &newX,
 
752
                                                                    areaWidth);
 
753
                overlapV = layoutOrganicFindBestVerticalPosition (s, i,
 
754
                                                                  &newY,
 
755
                                                                  areaHeight);
 
756
 
 
757
                if (overlapH < oldOverlap - 0.1 ||
 
758
                    overlapV < oldOverlap - 0.1)
 
759
                {
 
760
                    improved = true;
 
761
                    improvement = true;
 
762
                    if (overlapV > overlapH)
 
763
                        ss->slots[i].x1 = newX;
 
764
                    else
 
765
                        ss->slots[i].y1 = newY;
 
766
                }
 
767
            }
 
768
            while (improved);
 
769
        }
 
770
    }
 
771
    while (improvement);
 
772
 
 
773
    totalOverlap = 0.0;
 
774
    for (i = 0; i < ss->nWindows; i++)
 
775
    {
 
776
        totalOverlap += layoutOrganicCalculateOverlap (s, i,
 
777
                                                       ss->slots[i].x1,
 
778
                                                       ss->slots[i].y1);
 
779
    }
 
780
 
 
781
    return (totalOverlap > 0.1);
 
782
}
 
783
 
 
784
static void
 
785
layoutOrganicRemoveOverlap (CompScreen *s,
 
786
                            int        areaWidth,
 
787
                            int        areaHeight)
 
788
{
 
789
    int        i, spacing;
 
790
    CompWindow *w;
 
791
 
 
792
    SCALE_SCREEN ();
 
793
    ADDON_SCREEN ();
 
794
 
 
795
    spacing = ss->opt[SCALE_SCREEN_OPTION_SPACING].value.i;
 
796
 
 
797
    while (layoutOrganicLocalSearch (s, areaWidth, areaHeight))
 
798
    {
 
799
        for (i = 0; i < ss->nWindows; i++)
 
800
        {
 
801
            int centerX, centerY;
 
802
            int newX, newY, newWidth, newHeight;
 
803
 
 
804
            w = ss->windows[i];
 
805
 
 
806
            centerX = ss->slots[i].x1 + WIN_W (w) / 2;
 
807
            centerY = ss->slots[i].y1 + WIN_H (w) / 2;
 
808
 
 
809
            newWidth = (int)((1.0 - ORGANIC_STEP) *
 
810
                             (double)WIN_W (w)) - spacing / 2;
 
811
            newHeight = (int)((1.0 - ORGANIC_STEP) *
 
812
                              (double)WIN_H (w)) - spacing / 2;
 
813
            newX = centerX - (newWidth / 2);
 
814
            newY = centerY - (newHeight / 2);
 
815
 
 
816
            ss->slots[i].x1 = newX;
 
817
            ss->slots[i].y1 = newY;
 
818
            ss->slots[i].x2 = newX + WIN_W (w);
 
819
            ss->slots[i].y2 = newY + WIN_H (w);
 
820
        }
 
821
        as->scale -= ORGANIC_STEP;
 
822
    }
 
823
}
 
824
 
 
825
static bool
 
826
layoutOrganicThumbs (CompScreen *s)
 
827
{
 
828
    CompWindow *w;
 
829
    int        i, moMode;
 
830
    XRectangle workArea;
 
831
 
 
832
    SCALE_SCREEN ();
 
833
    ADDON_SCREEN ();
 
834
 
 
835
    moMode = ss->opt[SCALE_SCREEN_OPTION_MULTIOUTPUT_MODE].value.i;
 
836
 
 
837
    switch (moMode) {
 
838
    case SCALE_MOMODE_ALL:
 
839
        workArea = s->workArea;
 
840
        break;
 
841
    case SCALE_MOMODE_CURRENT:
 
842
    default:
 
843
        workArea = s->outputDev[s->currentOutputDev].workArea;
 
844
        break;
 
845
    }
 
846
 
 
847
    as->scale = 1.0f;
 
848
 
 
849
    qsort (ss->windows, ss->nWindows, sizeof(CompWindow *),
 
850
           organicCompareWindows);
 
851
 
 
852
    for (i = 0; i < ss->nWindows; i++)
 
853
    {
 
854
        w = ss->windows[i];
 
855
        SCALE_WINDOW (w);
 
856
 
 
857
        sWindow->slot = &ss->slots[i];
 
858
        ss->slots[i].x1 = WIN_X (w) - workArea.x;
 
859
        ss->slots[i].y1 = WIN_Y (w) - workArea.y;
 
860
        ss->slots[i].x2 = WIN_X (w) + WIN_W (w) - workArea.x;
 
861
        ss->slots[i].y2 = WIN_Y (w) + WIN_H (w) - workArea.y;
 
862
 
 
863
        if (ss->slots[i].x1 < 0)
 
864
        {
 
865
            ss->slots[i].x2 += abs (ss->slots[i].x1);
 
866
            ss->slots[i].x1 = 0;
 
867
        }
 
868
        if (ss->slots[i].x2 > workArea.width - workArea.x)
 
869
        {
 
870
            ss->slots[i].x1 -= abs (ss->slots[i].x2 - workArea.width);
 
871
            ss->slots[i].x2 = workArea.width - workArea.x;
 
872
        }
 
873
 
 
874
        if (ss->slots[i].y1 < 0)
 
875
        {
 
876
            ss->slots[i].y2 += abs (ss->slots[i].y1);
 
877
            ss->slots[i].y1 = 0;
 
878
        }
 
879
        if (ss->slots[i].y2 > workArea.height - workArea.y)
 
880
        {
 
881
            ss->slots[i].y1 -= abs (ss->slots[i].y2 -
 
882
                                    workArea.height - workArea.y);
 
883
            ss->slots[i].y2 = workArea.height - workArea.y;
 
884
        }
 
885
    }
 
886
 
 
887
    ss->nSlots = ss->nWindows;
 
888
 
 
889
    layoutOrganicRemoveOverlap (s, workArea.width - workArea.x,
 
890
                                workArea.height - workArea.y);
 
891
    for (i = 0; i < ss->nWindows; i++)
 
892
    {
 
893
        w = ss->windows[i];
 
894
        SCALE_WINDOW (w);
 
895
 
 
896
        if (ss->type == ScaleTypeGroup)
 
897
            raiseWindow (ss->windows[i]);
 
898
 
 
899
        ss->slots[i].x1 += w->input.left + workArea.x;
 
900
        ss->slots[i].x2 += w->input.left + workArea.x;
 
901
        ss->slots[i].y1 += w->input.top + workArea.y;
 
902
        ss->slots[i].y2 += w->input.top + workArea.y;
 
903
        sWindow->adjust = true;
 
904
    }
 
905
 
 
906
    return true;
 
907
}
 
908
 
 
909
#endif
 
910
 
 
911
/*
 
912
 * Inspired by KWin - the KDE Window Manager
 
913
 * presentwindows.cpp
 
914
 * Copyright (C) 2007 Rivo Laks <rivolaks@hot.ee>
 
915
 * Copyright (C) 2008 Lucas Murray <lmurray@undefinedfire.com>
 
916
 * 
 
917
 */
 
918
 
 
919
bool
 
920
ScaleAddonScreen::isOverlappingAny (ScaleWindow *w,
 
921
                                    std::map <ScaleWindow *, CompRegion> targets,
 
922
                                    const CompRegion &border)
 
923
{
 
924
    if (border.intersects (targets[w]))
 
925
        return true;
 
926
    // Is there a better way to do this?
 
927
    std::map <ScaleWindow *, CompRegion>::const_iterator i;
 
928
    for (i = targets.begin (); i != targets.end (); ++i)
 
929
    {
 
930
        if (w == (*i).first)
 
931
            continue;
 
932
        if (targets[w].intersects ((*i).second))
 
933
            return true;
 
934
    }
 
935
    return false;
 
936
}
 
937
 
 
938
bool
 
939
ScaleAddonScreen::layoutNaturalThumbs ()
 
940
{
 
941
    ScaleScreen::WindowList windows = ScaleScreen::get (screen)->getWindows ();
 
942
    bool overlapping;
 
943
    CompRect area = screen->workArea ();
 
944
    CompRect bounds = area;
 
945
    std::map <ScaleWindow *, CompRegion> targets;
 
946
    std::map <ScaleWindow *, int> directions;
 
947
    int                           direction = 0;
 
948
    int                           iterCount = 0;
 
949
 
 
950
    if (windows.size () == 1)
 
951
    {
 
952
        // Just move the window to its original location to save time
 
953
        if (screen->fullscreenOutput ().workArea ().contains (windows.front ()->window->geometry ()))
 
954
        {
 
955
            ScaleSlot slot ((CompRect &) windows.front ()->window->geometry ());
 
956
            windows.front ()->setSlot (slot);
 
957
            return true;
 
958
        }
 
959
    }
 
960
 
 
961
    foreach (ScaleWindow *w, windows)
 
962
    {
 
963
        bounds = CompRegion (bounds).united (w->window->outputRect ()).boundingRect ();
 
964
        targets[w] = CompRegion (w->window->outputRect ());
 
965
        // Reuse the unused "slot" as a preferred direction attribute. This is used when the window
 
966
        // is on the edge of the screen to try to use as much screen real estate as possible.
 
967
        directions[w] = direction;
 
968
        direction++;
 
969
        if (direction == 4)
 
970
            direction = 0;
 
971
    }
 
972
        
 
973
    do
 
974
    {
 
975
        overlapping = false;
 
976
        foreach (ScaleWindow *w, windows)
 
977
        {
 
978
            foreach (ScaleWindow *e, windows)
 
979
            {
 
980
                if (e->window->id () != w->window->id () && targets[w].intersects (targets[e]))
 
981
                {
 
982
                    int moveX = targets[w].boundingRect ().centerX () - targets[e].boundingRect ().centerX ();
 
983
                    int moveY = targets[w].boundingRect ().centerY () - targets[e].boundingRect ().centerY ();
 
984
                    //int xSection, ySection;
 
985
                    // Overlap detected, determine direction to push
 
986
                    
 
987
                    overlapping = true;
 
988
 
 
989
                    moveX /= optionGetNaturalPrecision ();
 
990
                    moveY /= optionGetNaturalPrecision ();
 
991
                    
 
992
                    /* Force movement */
 
993
                    if (moveX == 0)
 
994
                        moveX = optionGetNaturalPrecision ();
 
995
                    if (moveY == 0)
 
996
                        moveY = optionGetNaturalPrecision ();
 
997
                    
 
998
                    targets[w] = targets[w].translated (moveX, moveY);
 
999
                    targets[e] = targets[e].translated (-moveX, -moveY);
 
1000
                    
 
1001
                    /* Try to keep the bounding rect the same aspect as the screen so that more
 
1002
                     * screen real estate is utilised. We do this by splitting the screen into nine
 
1003
                     * equal sections, if the window center is in any of the corner sections pull the
 
1004
                     * window towards the outer corner. If it is in any of the other edge sections
 
1005
                     * alternate between each corner on that edge. We don't want to determine it
 
1006
                     * randomly as it will not produce consistant locations when using the filter.
 
1007
                     * Only move one window so we don't cause large amounts of unnecessary zooming
 
1008
                     * in some situations. We need to do this even when expanding later just in case
 
1009
                     * all windows are the same size.
 
1010
                     * (We are using an old bounding rect for this, hopefully it doesn't matter)
 
1011
                     * FIXME: Disabled for now
 
1012
                     *
 
1013
                    xSection = (targets[w].boundingRect ().x () - bounds.x ()) / (bounds.width () / 3);
 
1014
                    ySection = (targets[w].boundingRect ().y () - bounds.y ()) / (bounds.height () / 3);
 
1015
                    moveX = 0;
 
1016
                    moveY = 0;
 
1017
                    if (xSection != 1 || ySection != 1) // Remove this if you want the center to pull as well
 
1018
                    {
 
1019
                        if (xSection == 1)
 
1020
                            xSection = (directions[w] / 2 ? 2 : 0);
 
1021
                        if (ySection == 1)
 
1022
                            ySection = (directions[w] % 2 ? 2 : 0);
 
1023
                    }
 
1024
                    
 
1025
                    if (xSection == 0 && ySection == 0)
 
1026
                    {
 
1027
                        moveX = bounds.left () - targets[w].boundingRect ().centerX ();
 
1028
                        moveY = bounds.top () - targets[w].boundingRect ().centerY ();
 
1029
                    }
 
1030
                    if (xSection == 2 && ySection == 0)
 
1031
                    {
 
1032
                        moveX = bounds.right () - targets[w].boundingRect ().centerX ();
 
1033
                        moveY = bounds.top () - targets[w].boundingRect ().centerY ();
 
1034
                    }
 
1035
                    if (xSection == 2 && ySection == 2)
 
1036
                    {
 
1037
                        moveX = bounds.right () - targets[w].boundingRect ().centerX ();
 
1038
                        moveY = bounds.bottom () - targets[w].boundingRect ().centerY ();
 
1039
                    }
 
1040
                    if (xSection == 0 && ySection == 2)
 
1041
                    {
 
1042
                        moveX = bounds.left () - targets[w].boundingRect ().centerX ();
 
1043
                        moveY = bounds.right () - targets[w].boundingRect ().centerY ();
 
1044
                    }
 
1045
                    if (moveX != 0 || moveY != 0)
 
1046
                        targets[w].translate (moveX, moveY);
 
1047
                    */
 
1048
                }
 
1049
                
 
1050
                // Update bounding rect
 
1051
                bounds = CompRegion (bounds).united (targets[w]).boundingRect ();
 
1052
                bounds = CompRegion (bounds).united (targets[e]).boundingRect ();
 
1053
            }
 
1054
        }
 
1055
    }
 
1056
    while (overlapping);
 
1057
 
 
1058
    // Work out scaling by getting the most top-left and most bottom-right window coords.
 
1059
    // The 20's and 10's are so that the windows don't touch the edge of the screen.
 
1060
    double scale;
 
1061
    if (bounds == area)
 
1062
        scale = 1.0; // Don't add borders to the screen
 
1063
    else if (area.width () / double (bounds.width ()) < area.height () / double (bounds.height ()))
 
1064
        scale = (area.width () - 20) / double (bounds.width ());
 
1065
    else
 
1066
        scale = (area.height () - 20) / double (bounds.height ());
 
1067
    // Make bounding rect fill the screen size for later steps
 
1068
    bounds = CompRect (
 
1069
        bounds.x () - (area.width () - 20 - bounds.width () * scale ) / 2 - 10 / scale,
 
1070
        bounds.y () - (area.height () - 20 - bounds.height () * scale ) / 2 - 10 / scale,
 
1071
        area.width () / scale,
 
1072
        area.height () / scale
 
1073
        );
 
1074
    
 
1075
    // Move all windows back onto the screen and set their scale
 
1076
    foreach (ScaleWindow *w, windows)
 
1077
    {
 
1078
        targets[w] = CompRect (
 
1079
            (targets[w].boundingRect ().x () - bounds.x () ) * scale + area.x (),
 
1080
            (targets[w].boundingRect ().y () - bounds.y ()) * scale + area.y (),
 
1081
            targets[w].boundingRect ().width () * scale,
 
1082
            targets[w].boundingRect ().height () * scale
 
1083
            );
 
1084
        ScaleSlot slt (targets[w].boundingRect ());
 
1085
        slt.scale = scale;
 
1086
        slt.filled = true;
 
1087
        
 
1088
        w->setSlot (slt);
 
1089
    }
 
1090
 
 
1091
    // Don't expand onto or over the border
 
1092
    CompRegion borderRegion = CompRegion (area);
 
1093
    CompRegion areaRegion = CompRegion (area);
 
1094
    borderRegion.translate (-200, -200);
 
1095
    borderRegion.shrink (-200, -200); // actually expands the region
 
1096
    areaRegion.translate (10 / scale, 10 / scale);
 
1097
    areaRegion.shrink (10 / scale, 10 / scale);
 
1098
    
 
1099
    borderRegion ^= areaRegion;
 
1100
 
 
1101
    bool moved = false;
 
1102
    do
 
1103
    {
 
1104
        moved = false;
 
1105
        foreach (ScaleWindow *w, windows)
 
1106
        {
 
1107
            CompRegion oldRegion;
 
1108
            
 
1109
            // This may cause some slight distortion if the windows are enlarged a large amount
 
1110
            int widthDiff = optionGetNaturalPrecision ();
 
1111
            int heightDiff = ((w->window->height () / w->window->width ()) * 
 
1112
            (targets[w].boundingRect ().width() + widthDiff)) - targets[w].boundingRect ().height ();
 
1113
            int xDiff = widthDiff / 2;  // Also move a bit in the direction of the enlarge, allows the
 
1114
            int yDiff = heightDiff / 2; // center windows to be enlarged if there is gaps on the side.
 
1115
            
 
1116
            // Attempt enlarging to the top-right
 
1117
            oldRegion = targets[w];
 
1118
            targets[w] = CompRegion (
 
1119
                                     targets[w].boundingRect ().x () + xDiff,
 
1120
                                     targets[w].boundingRect ().y () - yDiff - heightDiff,
 
1121
                                     targets[w].boundingRect ().width () + widthDiff,
 
1122
                                     targets[w].boundingRect ().height () + heightDiff
 
1123
                                        );
 
1124
            if (isOverlappingAny (w, targets, borderRegion))
 
1125
                targets[w] = oldRegion;
 
1126
            else
 
1127
                moved = true;
 
1128
            
 
1129
            // Attempt enlarging to the bottom-right
 
1130
            oldRegion = targets[w];
 
1131
            targets[w] = CompRegion(
 
1132
                                    targets[w].boundingRect ().x () + xDiff,
 
1133
                                    targets[w].boundingRect ().y () + yDiff,
 
1134
                                    targets[w].boundingRect ().width () + widthDiff,
 
1135
                                    targets[w].boundingRect ().height () + heightDiff
 
1136
                                    );
 
1137
            if (isOverlappingAny (w, targets, borderRegion))
 
1138
                targets[w] = oldRegion;
 
1139
            else
 
1140
                moved = true;
 
1141
                
 
1142
            // Attempt enlarging to the bottom-left
 
1143
            oldRegion = targets[w];
 
1144
            targets[w] = CompRegion (
 
1145
                                    targets[w].boundingRect ().x() - xDiff - widthDiff,
 
1146
                                    targets[w].boundingRect ().y() + yDiff,
 
1147
                                    targets[w].boundingRect ().width() + widthDiff,
 
1148
                                    targets[w].boundingRect ().height() + heightDiff
 
1149
                                    );
 
1150
            if (isOverlappingAny (w, targets, borderRegion))
 
1151
                targets[w] = oldRegion;
 
1152
            else
 
1153
                moved = true;
 
1154
                    
 
1155
            // Attempt enlarging to the top-left
 
1156
            oldRegion = targets[w];
 
1157
            targets[w] = CompRegion (
 
1158
                                    targets[w].boundingRect ().x() - xDiff - widthDiff,
 
1159
                                    targets[w].boundingRect ().y() - yDiff - heightDiff,
 
1160
                                    targets[w].boundingRect ().width() + widthDiff,
 
1161
                                    targets[w].boundingRect ().height() + heightDiff
 
1162
                                    );
 
1163
            if (isOverlappingAny (w, targets, borderRegion))
 
1164
                targets[w] = oldRegion;
 
1165
            else
 
1166
                moved = true;
 
1167
        }
 
1168
        
 
1169
        iterCount++;
 
1170
    }
 
1171
    while (moved && iterCount < 100);
 
1172
 
 
1173
    // The expanding code above can actually enlarge windows over 1.0/2.0 scale, we don't like this
 
1174
    // We can't add this to the loop above as it would cause a never-ending loop so we have to make
 
1175
    // do with the less-than-optimal space usage with using this method.
 
1176
    foreach (ScaleWindow *w, windows)
 
1177
    {
 
1178
        double scale = targets[w].boundingRect ().width() / double( w->window->width());
 
1179
        if (scale > 2.0 || (scale > 1.0 && (w->window->width() > 300 || w->window->height() > 300)))
 
1180
        {
 
1181
            scale = (w->window->width () > 300 || w->window->height () > 300) ? 1.0 : 2.0;
 
1182
            targets[w] = CompRegion (
 
1183
                                    targets[w].boundingRect ().center().x() - int (w->window->width() * scale) / 2,
 
1184
                                    targets[w].boundingRect ().center().y() - int (w->window->height () * scale) / 2,
 
1185
                                    w->window->width() * scale,
 
1186
                                    w->window->height() * scale
 
1187
                                    );
 
1188
        }
 
1189
    }
 
1190
 
 
1191
    return true;
 
1192
 
 
1193
}
 
1194
 
 
1195
bool
 
1196
ScaleAddonScreen::layoutSlotsAndAssignWindows ()
 
1197
{
 
1198
    bool status;
 
1199
 
 
1200
    switch (optionGetLayoutMode ())
 
1201
    {
 
1202
    case LayoutModeNatural:
 
1203
        status = layoutNaturalThumbs ();
 
1204
        break;
 
1205
    case LayoutModeNormal:
 
1206
    default:
 
1207
        status = sScreen->layoutSlotsAndAssignWindows ();
 
1208
        break;
 
1209
    }
 
1210
 
 
1211
    return status;
 
1212
}
 
1213
 
 
1214
void
 
1215
ScaleAddonScreen::optionChanged (CompOption                 *opt,
 
1216
                                 ScaleaddonOptions::Options num)
 
1217
{
 
1218
    switch (num)
 
1219
    {
 
1220
        case ScaleaddonOptions::WindowTitle:
 
1221
        case ScaleaddonOptions::TitleBold:
 
1222
        case ScaleaddonOptions::TitleSize:
 
1223
        case ScaleaddonOptions::BorderSize:
 
1224
        case ScaleaddonOptions::FontColor:
 
1225
        case ScaleaddonOptions::BackColor:
 
1226
            if (textAvailable)
 
1227
            {
 
1228
                foreach (CompWindow *w, screen->windows ())
 
1229
                {
 
1230
                    ADDON_WINDOW (w);
 
1231
                    aw->renderTitle ();
 
1232
                }
 
1233
            }
 
1234
            break;
 
1235
        default:
 
1236
            break;
 
1237
    }
 
1238
}
 
1239
 
 
1240
ScaleAddonScreen::ScaleAddonScreen (CompScreen *) :
 
1241
    PluginClassHandler <ScaleAddonScreen, CompScreen> (screen),
 
1242
    cScreen (CompositeScreen::get (screen)),
 
1243
    sScreen (ScaleScreen::get (screen)),
 
1244
    highlightedWindow (0),
 
1245
    lastHighlightedWindow (0),
 
1246
    lastState (ScaleScreen::Idle),
 
1247
    scale (1.0f)
 
1248
{
 
1249
    CompAction::CallBack cb;
 
1250
    ChangeNotify         notify;
 
1251
 
 
1252
    ScreenInterface::setHandler (screen, true);
 
1253
    CompositeScreenInterface::setHandler (cScreen, true);
 
1254
    ScaleScreenInterface::setHandler (sScreen, true);
 
1255
 
 
1256
    cb = boost::bind (&ScaleAddonScreen::closeWindow, this, _1, _2, _3);
 
1257
    optionSetCloseKeyInitiate (cb);
 
1258
    optionSetCloseButtonInitiate (cb);
 
1259
 
 
1260
    cb = boost::bind (&ScaleAddonScreen::zoomWindow, this, _1, _2, _3);
 
1261
    optionSetZoomKeyInitiate (cb);
 
1262
    optionSetZoomButtonInitiate (cb);
 
1263
 
 
1264
    cb = boost::bind (&ScaleAddonScreen::pullWindow, this, _1, _2, _3);
 
1265
    optionSetPullKeyInitiate (cb);
 
1266
    optionSetPullButtonInitiate (cb);
 
1267
 
 
1268
    notify = boost::bind (&ScaleAddonScreen::optionChanged, this, _1, _2);
 
1269
    optionSetWindowTitleNotify (notify);
 
1270
    optionSetTitleBoldNotify (notify);
 
1271
    optionSetTitleSizeNotify (notify);
 
1272
    optionSetBorderSizeNotify (notify);
 
1273
    optionSetFontColorNotify (notify);
 
1274
    optionSetBackColorNotify (notify);
 
1275
}
 
1276
 
 
1277
ScaleAddonWindow::ScaleAddonWindow (CompWindow *window) :
 
1278
    PluginClassHandler <ScaleAddonWindow, CompWindow> (window),
 
1279
    window (window),
 
1280
    sWindow (ScaleWindow::get (window)),
 
1281
    cWindow (CompositeWindow::get (window)),
 
1282
    rescaled (false),
 
1283
    oldAbove (NULL)
 
1284
{
 
1285
    ScaleWindowInterface::setHandler (sWindow);
 
1286
}
 
1287
 
 
1288
bool
 
1289
ScaleAddonPluginVTable::init ()
 
1290
{
 
1291
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) ||
 
1292
        !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) ||
 
1293
        !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI) ||
 
1294
        !CompPlugin::checkPluginABI ("scale", COMPIZ_SCALE_ABI))
 
1295
        return false;
 
1296
 
 
1297
    if (!CompPlugin::checkPluginABI ("text", COMPIZ_TEXT_ABI))
 
1298
    {
 
1299
        compLogMessage ("scaleaddon", CompLogLevelInfo,
 
1300
                        "Text Plugin not loaded, no text will be drawn.");
 
1301
        textAvailable = false;
 
1302
    }
 
1303
    else
 
1304
        textAvailable = true;
 
1305
 
 
1306
    return true;
 
1307
}