~ubuntu-branches/ubuntu/precise/kde-workspace/precise-proposed

« back to all changes in this revision

Viewing changes to .pc/enable_kwinactive.diff/kwin/libkwineffects/kwineffects.cpp

  • Committer: Package Import Robot
  • Author(s): Philip Muškovac, Rodrigo Belem, Philip Muškovac
  • Date: 2012-04-10 19:37:37 UTC
  • Revision ID: package-import@ubuntu.com-20120410193737-rhsuhcb6mfsdom0f
Tags: 4:4.8.2a-0ubuntu2
[ Rodrigo Belem ]
* Move kwin4_effect_builtins.so to kde-window-manager
* Move libkwinnvidiahack4 to its own package
* Add breaks/replaces for kde-window-manager-common on
  libkwinnvidiahack4 and kde-window-manager << 4:4.8.2a-0ubuntu2~
* Enable kwinactive (LP: #956186)
* Build the source twice to create kwinactive binaries
* Add the packages
  - kde-window-manager-active
  - kde-window-manager-active-gles
  - libkwinactiveglutils1
  - libkwinactiveglesutils1
  - libkwinactiveeffects1abi3
  - libkwinactivenvidiahack4
* Fix kwinactive build failure with the patch
  kubuntu_active_fix_kwin_xrender_disable.diff

[ Philip Muškovac ]
* kde-window-manager/-gles depends on libkwinnvidiahack4
  kde-window-manager-active/-gles depends on libkwinactivenvidiahack4
* use ${allLibaries} to generate the library dependencies for
  kde-workspace-dev again

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/********************************************************************
 
2
 KWin - the KDE window manager
 
3
 This file is part of the KDE project.
 
4
 
 
5
Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
 
6
Copyright (C) 2009 Lucas Murray <lmurray@undefinedfire.com>
 
7
 
 
8
This program is free software; you can redistribute it and/or modify
 
9
it under the terms of the GNU General Public License as published by
 
10
the Free Software Foundation; either version 2 of the License, or
 
11
(at your option) any later version.
 
12
 
 
13
This program is distributed in the hope that it will be useful,
 
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
GNU General Public License for more details.
 
17
 
 
18
You should have received a copy of the GNU General Public License
 
19
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
*********************************************************************/
 
21
 
 
22
#include "kwineffects.h"
 
23
 
 
24
#include "kwinxrenderutils.h"
 
25
 
 
26
#include <QtDBus/QtDBus>
 
27
#include <QVariant>
 
28
#include <QList>
 
29
#include <QtCore/QTimeLine>
 
30
#include <QtGui/QFontMetrics>
 
31
#include <QtGui/QPainter>
 
32
#include <QtGui/QPixmap>
 
33
 
 
34
#include <kdebug.h>
 
35
#include <ksharedconfig.h>
 
36
#include <kstandarddirs.h>
 
37
#include <kconfiggroup.h>
 
38
 
 
39
#include <assert.h>
 
40
 
 
41
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
 
42
#include <X11/extensions/Xrender.h>
 
43
#include <X11/extensions/Xfixes.h>
 
44
#endif
 
45
 
 
46
namespace KWin
 
47
{
 
48
 
 
49
void WindowPrePaintData::setTranslucent()
 
50
{
 
51
    mask |= Effect::PAINT_WINDOW_TRANSLUCENT;
 
52
    mask &= ~Effect::PAINT_WINDOW_OPAQUE;
 
53
    clip = QRegion(); // cannot clip, will be transparent
 
54
}
 
55
 
 
56
void WindowPrePaintData::setTransformed()
 
57
{
 
58
    mask |= Effect::PAINT_WINDOW_TRANSFORMED;
 
59
}
 
60
 
 
61
 
 
62
WindowPaintData::WindowPaintData(EffectWindow* w)
 
63
    : opacity(w->opacity())
 
64
    , contents_opacity(1.0)
 
65
    , decoration_opacity(1.0)
 
66
    , xScale(1)
 
67
    , yScale(1)
 
68
    , zScale(1)
 
69
    , xTranslate(0)
 
70
    , yTranslate(0)
 
71
    , zTranslate(0)
 
72
    , saturation(1)
 
73
    , brightness(1)
 
74
    , shader(NULL)
 
75
    , rotation(NULL)
 
76
{
 
77
    quads = w->buildQuads();
 
78
}
 
79
 
 
80
ScreenPaintData::ScreenPaintData()
 
81
    : xScale(1)
 
82
    , yScale(1)
 
83
    , zScale(1)
 
84
    , xTranslate(0)
 
85
    , yTranslate(0)
 
86
    , zTranslate(0)
 
87
    , rotation(NULL)
 
88
{
 
89
}
 
90
 
 
91
RotationData::RotationData()
 
92
    : axis(ZAxis)
 
93
    , angle(0.0)
 
94
    , xRotationPoint(0.0)
 
95
    , yRotationPoint(0.0)
 
96
    , zRotationPoint(0.0)
 
97
{
 
98
}
 
99
 
 
100
//****************************************
 
101
// Effect
 
102
//****************************************
 
103
 
 
104
Effect::Effect()
 
105
{
 
106
}
 
107
 
 
108
Effect::~Effect()
 
109
{
 
110
}
 
111
 
 
112
void Effect::reconfigure(ReconfigureFlags)
 
113
{
 
114
}
 
115
 
 
116
void* Effect::proxy()
 
117
{
 
118
    return NULL;
 
119
}
 
120
 
 
121
void Effect::windowInputMouseEvent(Window, QEvent*)
 
122
{
 
123
}
 
124
 
 
125
void Effect::grabbedKeyboardEvent(QKeyEvent*)
 
126
{
 
127
}
 
128
 
 
129
bool Effect::borderActivated(ElectricBorder)
 
130
{
 
131
    return false;
 
132
}
 
133
 
 
134
void Effect::prePaintScreen(ScreenPrePaintData& data, int time)
 
135
{
 
136
    effects->prePaintScreen(data, time);
 
137
}
 
138
 
 
139
void Effect::paintScreen(int mask, QRegion region, ScreenPaintData& data)
 
140
{
 
141
    effects->paintScreen(mask, region, data);
 
142
}
 
143
 
 
144
void Effect::postPaintScreen()
 
145
{
 
146
    effects->postPaintScreen();
 
147
}
 
148
 
 
149
void Effect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time)
 
150
{
 
151
    effects->prePaintWindow(w, data, time);
 
152
}
 
153
 
 
154
void Effect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data)
 
155
{
 
156
    effects->paintWindow(w, mask, region, data);
 
157
}
 
158
 
 
159
void Effect::postPaintWindow(EffectWindow* w)
 
160
{
 
161
    effects->postPaintWindow(w);
 
162
}
 
163
 
 
164
void Effect::paintEffectFrame(KWin::EffectFrame* frame, QRegion region, double opacity, double frameOpacity)
 
165
{
 
166
    effects->paintEffectFrame(frame, region, opacity, frameOpacity);
 
167
}
 
168
 
 
169
bool Effect::provides(Feature)
 
170
{
 
171
    return false;
 
172
}
 
173
 
 
174
bool Effect::isActive() const
 
175
{
 
176
    return true;
 
177
}
 
178
 
 
179
void Effect::drawWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data)
 
180
{
 
181
    effects->drawWindow(w, mask, region, data);
 
182
}
 
183
 
 
184
void Effect::buildQuads(EffectWindow* w, WindowQuadList& quadList)
 
185
{
 
186
    effects->buildQuads(w, quadList);
 
187
}
 
188
 
 
189
void Effect::setPositionTransformations(WindowPaintData& data, QRect& region, EffectWindow* w,
 
190
                                        const QRect& r, Qt::AspectRatioMode aspect)
 
191
{
 
192
    QSize size = w->size();
 
193
    size.scale(r.size(), aspect);
 
194
    data.xScale = size.width() / double(w->width());
 
195
    data.yScale = size.height() / double(w->height());
 
196
    int width = int(w->width() * data.xScale);
 
197
    int height = int(w->height() * data.yScale);
 
198
    int x = r.x() + (r.width() - width) / 2;
 
199
    int y = r.y() + (r.height() - height) / 2;
 
200
    region = QRect(x, y, width, height);
 
201
    data.xTranslate = x - w->x();
 
202
    data.yTranslate = y - w->y();
 
203
}
 
204
 
 
205
int Effect::displayWidth()
 
206
{
 
207
    return KWin::displayWidth();
 
208
}
 
209
 
 
210
int Effect::displayHeight()
 
211
{
 
212
    return KWin::displayHeight();
 
213
}
 
214
 
 
215
QPoint Effect::cursorPos()
 
216
{
 
217
    return effects->cursorPos();
 
218
}
 
219
 
 
220
double Effect::animationTime(const KConfigGroup& cfg, const QString& key, int defaultTime)
 
221
{
 
222
    int time = cfg.readEntry(key, 0);
 
223
    return time != 0 ? time : qMax(defaultTime * effects->animationTimeFactor(), 1.);
 
224
}
 
225
 
 
226
double Effect::animationTime(int defaultTime)
 
227
{
 
228
    // at least 1ms, otherwise 0ms times can break some things
 
229
    return qMax(defaultTime * effects->animationTimeFactor(), 1.);
 
230
}
 
231
 
 
232
//****************************************
 
233
// EffectsHandler
 
234
//****************************************
 
235
 
 
236
EffectsHandler::EffectsHandler(CompositingType type)
 
237
    : compositing_type(type)
 
238
{
 
239
    if (compositing_type == NoCompositing)
 
240
        return;
 
241
    KWin::effects = this;
 
242
}
 
243
 
 
244
EffectsHandler::~EffectsHandler()
 
245
{
 
246
    // All effects should already be unloaded by Impl dtor
 
247
    assert(loaded_effects.count() == 0);
 
248
}
 
249
 
 
250
Window EffectsHandler::createInputWindow(Effect* e, const QRect& r, const QCursor& cursor)
 
251
{
 
252
    return createInputWindow(e, r.x(), r.y(), r.width(), r.height(), cursor);
 
253
}
 
254
 
 
255
Window EffectsHandler::createFullScreenInputWindow(Effect* e, const QCursor& cursor)
 
256
{
 
257
    return createInputWindow(e, 0, 0, displayWidth(), displayHeight(), cursor);
 
258
}
 
259
 
 
260
CompositingType EffectsHandler::compositingType() const
 
261
{
 
262
    return compositing_type;
 
263
}
 
264
 
 
265
void EffectsHandler::sendReloadMessage(const QString& effectname)
 
266
{
 
267
    QDBusMessage message = QDBusMessage::createMethodCall("org.kde.kwin", "/KWin", "org.kde.KWin", "reconfigureEffect");
 
268
    message << QString("kwin4_effect_" + effectname);
 
269
    QDBusConnection::sessionBus().send(message);
 
270
}
 
271
 
 
272
KConfigGroup EffectsHandler::effectConfig(const QString& effectname)
 
273
{
 
274
    KSharedConfig::Ptr kwinconfig = KSharedConfig::openConfig("kwinrc", KConfig::NoGlobals);
 
275
    return kwinconfig->group("Effect-" + effectname);
 
276
}
 
277
 
 
278
EffectsHandler* effects = 0;
 
279
 
 
280
 
 
281
//****************************************
 
282
// EffectWindow
 
283
//****************************************
 
284
 
 
285
EffectWindow::EffectWindow()
 
286
{
 
287
}
 
288
 
 
289
EffectWindow::~EffectWindow()
 
290
{
 
291
}
 
292
 
 
293
bool EffectWindow::isOnCurrentActivity() const
 
294
{
 
295
    return isOnActivity(effects->currentActivity());
 
296
}
 
297
 
 
298
bool EffectWindow::isOnCurrentDesktop() const
 
299
{
 
300
    return isOnDesktop(effects->currentDesktop());
 
301
}
 
302
 
 
303
bool EffectWindow::isOnDesktop(int d) const
 
304
{
 
305
    return desktop() == d || isOnAllDesktops();
 
306
}
 
307
 
 
308
bool EffectWindow::hasDecoration() const
 
309
{
 
310
    return contentsRect() != QRect(0, 0, width(), height());
 
311
}
 
312
 
 
313
 
 
314
//****************************************
 
315
// EffectWindowGroup
 
316
//****************************************
 
317
 
 
318
EffectWindowGroup::~EffectWindowGroup()
 
319
{
 
320
}
 
321
 
 
322
//****************************************
 
323
// GlobalShortcutsEditor
 
324
//****************************************
 
325
 
 
326
GlobalShortcutsEditor::GlobalShortcutsEditor(QWidget *parent) :
 
327
    KShortcutsEditor(parent, GlobalAction)
 
328
{
 
329
}
 
330
 
 
331
/***************************************************************
 
332
 WindowQuad
 
333
***************************************************************/
 
334
 
 
335
WindowQuad WindowQuad::makeSubQuad(double x1, double y1, double x2, double y2) const
 
336
{
 
337
    assert(x1 < x2 && y1 < y2 && x1 >= left() && x2 <= right() && y1 >= top() && y2 <= bottom());
 
338
#ifndef NDEBUG
 
339
    if (isTransformed())
 
340
        kFatal(1212) << "Splitting quads is allowed only in pre-paint calls!" ;
 
341
#endif
 
342
    WindowQuad ret(*this);
 
343
    // vertices are clockwise starting from topleft
 
344
    ret.verts[ 0 ].px = x1;
 
345
    ret.verts[ 3 ].px = x1;
 
346
    ret.verts[ 1 ].px = x2;
 
347
    ret.verts[ 2 ].px = x2;
 
348
    ret.verts[ 0 ].py = y1;
 
349
    ret.verts[ 1 ].py = y1;
 
350
    ret.verts[ 2 ].py = y2;
 
351
    ret.verts[ 3 ].py = y2;
 
352
    // original x/y are supposed to be the same, no transforming is done here
 
353
    ret.verts[ 0 ].ox = x1;
 
354
    ret.verts[ 3 ].ox = x1;
 
355
    ret.verts[ 1 ].ox = x2;
 
356
    ret.verts[ 2 ].ox = x2;
 
357
    ret.verts[ 0 ].oy = y1;
 
358
    ret.verts[ 1 ].oy = y1;
 
359
    ret.verts[ 2 ].oy = y2;
 
360
    ret.verts[ 3 ].oy = y2;
 
361
    double my_tleft = verts[ 0 ].tx;
 
362
    double my_tright = verts[ 2 ].tx;
 
363
    double my_ttop = verts[ 0 ].ty;
 
364
    double my_tbottom = verts[ 2 ].ty;
 
365
    double tleft = (x1 - left()) / (right() - left()) * (my_tright - my_tleft) + my_tleft;
 
366
    double tright = (x2 - left()) / (right() - left()) * (my_tright - my_tleft) + my_tleft;
 
367
    double ttop = (y1 - top()) / (bottom() - top()) * (my_tbottom - my_ttop) + my_ttop;
 
368
    double tbottom = (y2 - top()) / (bottom() - top()) * (my_tbottom - my_ttop) + my_ttop;
 
369
    ret.verts[ 0 ].tx = tleft;
 
370
    ret.verts[ 3 ].tx = tleft;
 
371
    ret.verts[ 1 ].tx = tright;
 
372
    ret.verts[ 2 ].tx = tright;
 
373
    ret.verts[ 0 ].ty = ttop;
 
374
    ret.verts[ 1 ].ty = ttop;
 
375
    ret.verts[ 2 ].ty = tbottom;
 
376
    ret.verts[ 3 ].ty = tbottom;
 
377
    return ret;
 
378
}
 
379
 
 
380
bool WindowQuad::smoothNeeded() const
 
381
{
 
382
    // smoothing is needed if the width or height of the quad does not match the original size
 
383
    double width = verts[ 1 ].ox - verts[ 0 ].ox;
 
384
    double height = verts[ 2 ].oy - verts[ 1 ].oy;
 
385
    return(verts[ 1 ].px - verts[ 0 ].px != width || verts[ 2 ].px - verts[ 3 ].px != width
 
386
           || verts[ 2 ].py - verts[ 1 ].py != height || verts[ 3 ].py - verts[ 0 ].py != height);
 
387
}
 
388
 
 
389
/***************************************************************
 
390
 WindowQuadList
 
391
***************************************************************/
 
392
 
 
393
WindowQuadList WindowQuadList::splitAtX(double x) const
 
394
{
 
395
    WindowQuadList ret;
 
396
    foreach (const WindowQuad & quad, *this) {
 
397
#ifndef NDEBUG
 
398
        if (quad.isTransformed())
 
399
            kFatal(1212) << "Splitting quads is allowed only in pre-paint calls!" ;
 
400
#endif
 
401
        bool wholeleft = true;
 
402
        bool wholeright = true;
 
403
        for (int i = 0;
 
404
                i < 4;
 
405
                ++i) {
 
406
            if (quad[ i ].x() < x)
 
407
                wholeright = false;
 
408
            if (quad[ i ].x() > x)
 
409
                wholeleft = false;
 
410
        }
 
411
        if (wholeleft || wholeright) { // is whole in one split part
 
412
            ret.append(quad);
 
413
            continue;
 
414
        }
 
415
        if (quad.left() == quad.right()) { // quad has no size
 
416
            ret.append(quad);
 
417
            continue;
 
418
        }
 
419
        ret.append(quad.makeSubQuad(quad.left(), quad.top(), x, quad.bottom()));
 
420
        ret.append(quad.makeSubQuad(x, quad.top(), quad.right(), quad.bottom()));
 
421
    }
 
422
    return ret;
 
423
}
 
424
 
 
425
WindowQuadList WindowQuadList::splitAtY(double y) const
 
426
{
 
427
    WindowQuadList ret;
 
428
    foreach (const WindowQuad & quad, *this) {
 
429
#ifndef NDEBUG
 
430
        if (quad.isTransformed())
 
431
            kFatal(1212) << "Splitting quads is allowed only in pre-paint calls!" ;
 
432
#endif
 
433
        bool wholetop = true;
 
434
        bool wholebottom = true;
 
435
        for (int i = 0;
 
436
                i < 4;
 
437
                ++i) {
 
438
            if (quad[ i ].y() < y)
 
439
                wholebottom = false;
 
440
            if (quad[ i ].y() > y)
 
441
                wholetop = false;
 
442
        }
 
443
        if (wholetop || wholebottom) { // is whole in one split part
 
444
            ret.append(quad);
 
445
            continue;
 
446
        }
 
447
        if (quad.top() == quad.bottom()) { // quad has no size
 
448
            ret.append(quad);
 
449
            continue;
 
450
        }
 
451
        ret.append(quad.makeSubQuad(quad.left(), quad.top(), quad.right(), y));
 
452
        ret.append(quad.makeSubQuad(quad.left(), y, quad.right(), quad.bottom()));
 
453
    }
 
454
    return ret;
 
455
}
 
456
 
 
457
WindowQuadList WindowQuadList::makeGrid(int maxquadsize) const
 
458
{
 
459
    if (empty())
 
460
        return *this;
 
461
    // find the bounding rectangle
 
462
    double left = first().left();
 
463
    double right = first().right();
 
464
    double top = first().top();
 
465
    double bottom = first().bottom();
 
466
    foreach (const WindowQuad & quad, *this) {
 
467
#ifndef NDEBUG
 
468
        if (quad.isTransformed())
 
469
            kFatal(1212) << "Splitting quads is allowed only in pre-paint calls!" ;
 
470
#endif
 
471
        left = qMin(left, quad.left());
 
472
        right = qMax(right, quad.right());
 
473
        top = qMin(top, quad.top());
 
474
        bottom = qMax(bottom, quad.bottom());
 
475
    }
 
476
    WindowQuadList ret;
 
477
    for (double x = left;
 
478
            x < right;
 
479
            x += maxquadsize) {
 
480
        for (double y = top;
 
481
                y < bottom;
 
482
                y += maxquadsize) {
 
483
            foreach (const WindowQuad & quad, *this) {
 
484
                if (QRectF(QPointF(quad.left(), quad.top()), QPointF(quad.right(), quad.bottom()))
 
485
                        .intersects(QRectF(x, y, maxquadsize, maxquadsize))) {
 
486
                    ret.append(quad.makeSubQuad(qMax(x, quad.left()), qMax(y, quad.top()),
 
487
                                                qMin(quad.right(), x + maxquadsize), qMin(quad.bottom(), y + maxquadsize)));
 
488
                }
 
489
            }
 
490
        }
 
491
    }
 
492
    return ret;
 
493
}
 
494
 
 
495
WindowQuadList WindowQuadList::makeRegularGrid(int xSubdivisions, int ySubdivisions) const
 
496
{
 
497
    if (empty())
 
498
        return *this;
 
499
    // find the bounding rectangle
 
500
    double left = first().left();
 
501
    double right = first().right();
 
502
    double top = first().top();
 
503
    double bottom = first().bottom();
 
504
    foreach (const WindowQuad & quad, *this) {
 
505
#ifndef NDEBUG
 
506
        if (quad.isTransformed())
 
507
            kFatal(1212) << "Splitting quads is allowed only in pre-paint calls!" ;
 
508
#endif
 
509
        left = qMin(left, quad.left());
 
510
        right = qMax(right, quad.right());
 
511
        top = qMin(top, quad.top());
 
512
        bottom = qMax(bottom, quad.bottom());
 
513
    }
 
514
 
 
515
    double xincrement = (right - left) / xSubdivisions;
 
516
    double yincrement = (bottom - top) / ySubdivisions;
 
517
    WindowQuadList ret;
 
518
    for (double y = top;
 
519
            y < bottom;
 
520
            y += yincrement) {
 
521
        for (double x = left;
 
522
                x < right;
 
523
                x +=  xincrement) {
 
524
            foreach (const WindowQuad & quad, *this) {
 
525
                if (QRectF(QPointF(quad.left(), quad.top()), QPointF(quad.right(), quad.bottom()))
 
526
                        .intersects(QRectF(x, y, xincrement, yincrement))) {
 
527
                    ret.append(quad.makeSubQuad(qMax(x, quad.left()), qMax(y, quad.top()),
 
528
                                                qMin(quad.right(), x + xincrement), qMin(quad.bottom(), y + yincrement)));
 
529
                }
 
530
            }
 
531
        }
 
532
    }
 
533
    return ret;
 
534
}
 
535
 
 
536
void WindowQuadList::makeArrays(float** vertices, float** texcoords, const QSizeF& size, bool yInverted) const
 
537
{
 
538
    *vertices = new float[ count() * 6 * 2 ];
 
539
    *texcoords = new float[ count() * 6 * 2 ];
 
540
    float* vpos = *vertices;
 
541
    float* tpos = *texcoords;
 
542
    for (int i = 0;
 
543
            i < count();
 
544
            ++i) {
 
545
        *vpos++ = at(i)[ 1 ].x();
 
546
        *vpos++ = at(i)[ 1 ].y();
 
547
        *vpos++ = at(i)[ 0 ].x();
 
548
        *vpos++ = at(i)[ 0 ].y();
 
549
        *vpos++ = at(i)[ 3 ].x();
 
550
        *vpos++ = at(i)[ 3 ].y();
 
551
        *vpos++ = at(i)[ 3 ].x();
 
552
        *vpos++ = at(i)[ 3 ].y();
 
553
        *vpos++ = at(i)[ 2 ].x();
 
554
        *vpos++ = at(i)[ 2 ].y();
 
555
        *vpos++ = at(i)[ 1 ].x();
 
556
        *vpos++ = at(i)[ 1 ].y();
 
557
 
 
558
        if (yInverted) {
 
559
            *tpos++ = at(i)[ 1 ].tx / size.width();
 
560
            *tpos++ = at(i)[ 1 ].ty / size.height();
 
561
            *tpos++ = at(i)[ 0 ].tx / size.width();
 
562
            *tpos++ = at(i)[ 0 ].ty / size.height();
 
563
            *tpos++ = at(i)[ 3 ].tx / size.width();
 
564
            *tpos++ = at(i)[ 3 ].ty / size.height();
 
565
            *tpos++ = at(i)[ 3 ].tx / size.width();
 
566
            *tpos++ = at(i)[ 3 ].ty / size.height();
 
567
            *tpos++ = at(i)[ 2 ].tx / size.width();
 
568
            *tpos++ = at(i)[ 2 ].ty / size.height();
 
569
            *tpos++ = at(i)[ 1 ].tx / size.width();
 
570
            *tpos++ = at(i)[ 1 ].ty / size.height();
 
571
        } else {
 
572
            *tpos++ = at(i)[ 1 ].tx / size.width();
 
573
            *tpos++ = 1.0f - at(i)[ 1 ].ty / size.height();
 
574
            *tpos++ = at(i)[ 0 ].tx / size.width();
 
575
            *tpos++ = 1.0f - at(i)[ 0 ].ty / size.height();
 
576
            *tpos++ = at(i)[ 3 ].tx / size.width();
 
577
            *tpos++ = 1.0f - at(i)[ 3 ].ty / size.height();
 
578
            *tpos++ = at(i)[ 3 ].tx / size.width();
 
579
            *tpos++ = 1.0f - at(i)[ 3 ].ty / size.height();
 
580
            *tpos++ = at(i)[ 2 ].tx / size.width();
 
581
            *tpos++ = 1.0f - at(i)[ 2 ].ty / size.height();
 
582
            *tpos++ = at(i)[ 1 ].tx / size.width();
 
583
            *tpos++ = 1.0f - at(i)[ 1 ].ty / size.height();
 
584
        }
 
585
    }
 
586
}
 
587
 
 
588
WindowQuadList WindowQuadList::select(WindowQuadType type) const
 
589
{
 
590
    foreach (const WindowQuad & q, *this) {
 
591
        if (q.type() != type) { // something else than ones to select, make a copy and filter
 
592
            WindowQuadList ret;
 
593
            foreach (const WindowQuad & q, *this) {
 
594
                if (q.type() == type)
 
595
                    ret.append(q);
 
596
            }
 
597
            return ret;
 
598
        }
 
599
    }
 
600
    return *this; // nothing to filter out
 
601
}
 
602
 
 
603
WindowQuadList WindowQuadList::filterOut(WindowQuadType type) const
 
604
{
 
605
    foreach (const WindowQuad & q, *this) {
 
606
        if (q.type() == type) { // something to filter out, make a copy and filter
 
607
            WindowQuadList ret;
 
608
            foreach (const WindowQuad & q, *this) {
 
609
                if (q.type() != type)
 
610
                    ret.append(q);
 
611
            }
 
612
            return ret;
 
613
        }
 
614
    }
 
615
    return *this; // nothing to filter out
 
616
}
 
617
 
 
618
bool WindowQuadList::smoothNeeded() const
 
619
{
 
620
    foreach (const WindowQuad & q, *this)
 
621
    if (q.smoothNeeded())
 
622
        return true;
 
623
    return false;
 
624
}
 
625
 
 
626
bool WindowQuadList::isTransformed() const
 
627
{
 
628
    foreach (const WindowQuad & q, *this)
 
629
    if (q.isTransformed())
 
630
        return true;
 
631
    return false;
 
632
}
 
633
 
 
634
/***************************************************************
 
635
 PaintClipper
 
636
***************************************************************/
 
637
 
 
638
QStack< QRegion >* PaintClipper::areas = NULL;
 
639
 
 
640
PaintClipper::PaintClipper(const QRegion& allowed_area)
 
641
    : area(allowed_area)
 
642
{
 
643
    push(area);
 
644
}
 
645
 
 
646
PaintClipper::~PaintClipper()
 
647
{
 
648
    pop(area);
 
649
}
 
650
 
 
651
void PaintClipper::push(const QRegion& allowed_area)
 
652
{
 
653
    if (allowed_area == infiniteRegion())  // don't push these
 
654
        return;
 
655
    if (areas == NULL)
 
656
        areas = new QStack< QRegion >;
 
657
    areas->push(allowed_area);
 
658
}
 
659
 
 
660
void PaintClipper::pop(const QRegion& allowed_area)
 
661
{
 
662
    if (allowed_area == infiniteRegion())
 
663
        return;
 
664
    Q_ASSERT(areas != NULL);
 
665
    Q_ASSERT(areas->top() == allowed_area);
 
666
    areas->pop();
 
667
    if (areas->isEmpty()) {
 
668
        delete areas;
 
669
        areas = NULL;
 
670
    }
 
671
}
 
672
 
 
673
bool PaintClipper::clip()
 
674
{
 
675
    return areas != NULL;
 
676
}
 
677
 
 
678
QRegion PaintClipper::paintArea()
 
679
{
 
680
    assert(areas != NULL);   // can be called only with clip() == true
 
681
    QRegion ret = QRegion(0, 0, displayWidth(), displayHeight());
 
682
    foreach (const QRegion & r, *areas)
 
683
    ret &= r;
 
684
    return ret;
 
685
}
 
686
 
 
687
struct PaintClipper::Iterator::Data {
 
688
    Data() : index(0) {}
 
689
    int index;
 
690
    QVector< QRect > rects;
 
691
};
 
692
 
 
693
PaintClipper::Iterator::Iterator()
 
694
    : data(new Data)
 
695
{
 
696
    if (clip() && effects->compositingType() == OpenGLCompositing) {
 
697
        data->rects = paintArea().rects();
 
698
        data->index = -1;
 
699
        next(); // move to the first one
 
700
    }
 
701
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
 
702
    if (clip() && effects->compositingType() == XRenderCompositing) {
 
703
        XserverRegion region = toXserverRegion(paintArea());
 
704
        XFixesSetPictureClipRegion(display(), effects->xrenderBufferPicture(), 0, 0, region);
 
705
        XFixesDestroyRegion(display(), region);   // it's ref-counted
 
706
    }
 
707
#endif
 
708
}
 
709
 
 
710
PaintClipper::Iterator::~Iterator()
 
711
{
 
712
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
 
713
    if (clip() && effects->compositingType() == XRenderCompositing)
 
714
        XFixesSetPictureClipRegion(display(), effects->xrenderBufferPicture(), 0, 0, None);
 
715
#endif
 
716
    delete data;
 
717
}
 
718
 
 
719
bool PaintClipper::Iterator::isDone()
 
720
{
 
721
    if (!clip())
 
722
        return data->index == 1; // run once
 
723
    if (effects->compositingType() == OpenGLCompositing)
 
724
        return data->index >= data->rects.count(); // run once per each area
 
725
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
 
726
    if (effects->compositingType() == XRenderCompositing)
 
727
        return data->index == 1; // run once
 
728
#endif
 
729
    abort();
 
730
}
 
731
 
 
732
void PaintClipper::Iterator::next()
 
733
{
 
734
    data->index++;
 
735
}
 
736
 
 
737
QRect PaintClipper::Iterator::boundingRect() const
 
738
{
 
739
    if (!clip())
 
740
        return infiniteRegion();
 
741
    if (effects->compositingType() == OpenGLCompositing)
 
742
        return data->rects[ data->index ];
 
743
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
 
744
    if (effects->compositingType() == XRenderCompositing)
 
745
        return paintArea().boundingRect();
 
746
#endif
 
747
    abort();
 
748
    return infiniteRegion();
 
749
}
 
750
 
 
751
/***************************************************************
 
752
 Motion1D
 
753
***************************************************************/
 
754
 
 
755
Motion1D::Motion1D(double initial, double strength, double smoothness)
 
756
    : Motion<double>(initial, strength, smoothness)
 
757
{
 
758
}
 
759
 
 
760
Motion1D::Motion1D(const Motion1D &other)
 
761
    : Motion<double>(other)
 
762
{
 
763
}
 
764
 
 
765
Motion1D::~Motion1D()
 
766
{
 
767
}
 
768
 
 
769
/***************************************************************
 
770
 Motion2D
 
771
***************************************************************/
 
772
 
 
773
Motion2D::Motion2D(QPointF initial, double strength, double smoothness)
 
774
    : Motion<QPointF>(initial, strength, smoothness)
 
775
{
 
776
}
 
777
 
 
778
Motion2D::Motion2D(const Motion2D &other)
 
779
    : Motion<QPointF>(other)
 
780
{
 
781
}
 
782
 
 
783
Motion2D::~Motion2D()
 
784
{
 
785
}
 
786
 
 
787
/***************************************************************
 
788
 WindowMotionManager
 
789
***************************************************************/
 
790
 
 
791
WindowMotionManager::WindowMotionManager(bool useGlobalAnimationModifier)
 
792
    :   m_useGlobalAnimationModifier(useGlobalAnimationModifier)
 
793
 
 
794
{
 
795
    // TODO: Allow developer to modify motion attributes
 
796
} // TODO: What happens when the window moves by an external force?
 
797
 
 
798
WindowMotionManager::~WindowMotionManager()
 
799
{
 
800
}
 
801
 
 
802
void WindowMotionManager::manage(EffectWindow *w)
 
803
{
 
804
    if (m_managedWindows.contains(w))
 
805
        return;
 
806
 
 
807
    double strength = 0.08;
 
808
    double smoothness = 4.0;
 
809
    if (m_useGlobalAnimationModifier && effects->animationTimeFactor()) {
 
810
        // If the factor is == 0 then we just skip the calculation completely
 
811
        strength = 0.08 / effects->animationTimeFactor();
 
812
        smoothness = effects->animationTimeFactor() * 4.0;
 
813
    }
 
814
 
 
815
    WindowMotion &motion = m_managedWindows[ w ];
 
816
    motion.translation.setStrength(strength);
 
817
    motion.translation.setSmoothness(smoothness);
 
818
    motion.scale.setStrength(strength * 1.33);
 
819
    motion.scale.setSmoothness(smoothness / 2.0);
 
820
 
 
821
    motion.translation.setValue(w->pos());
 
822
    motion.scale.setValue(QPointF(1.0, 1.0));
 
823
}
 
824
 
 
825
void WindowMotionManager::unmanage(EffectWindow *w)
 
826
{
 
827
    m_movingWindowsSet.remove(w);
 
828
    m_managedWindows.remove(w);
 
829
}
 
830
 
 
831
void WindowMotionManager::unmanageAll()
 
832
{
 
833
    m_managedWindows.clear();
 
834
    m_movingWindowsSet.clear();
 
835
}
 
836
 
 
837
void WindowMotionManager::calculate(int time)
 
838
{
 
839
    if (!effects->animationTimeFactor()) {
 
840
        // Just skip it completely if the user wants no animation
 
841
        m_movingWindowsSet.clear();
 
842
        QHash<EffectWindow*, WindowMotion>::iterator it = m_managedWindows.begin();
 
843
        for (; it != m_managedWindows.end(); ++it) {
 
844
            WindowMotion *motion = &it.value();
 
845
            motion->translation.finish();
 
846
            motion->scale.finish();
 
847
        }
 
848
    }
 
849
 
 
850
    QHash<EffectWindow*, WindowMotion>::iterator it = m_managedWindows.begin();
 
851
    for (; it != m_managedWindows.end(); ++it) {
 
852
        WindowMotion *motion = &it.value();
 
853
        int stopped = 0;
 
854
 
 
855
        // TODO: What happens when distance() == 0 but we are still moving fast?
 
856
        // TODO: Motion needs to be calculated from the window's center
 
857
 
 
858
        Motion2D *trans = &motion->translation;
 
859
        if (trans->distance().isNull())
 
860
            ++stopped;
 
861
        else {
 
862
            // Still moving
 
863
            trans->calculate(time);
 
864
            const short fx = trans->target().x() <= trans->startValue().x() ? -1 : 1;
 
865
            const short fy = trans->target().y() <= trans->startValue().y() ? -1 : 1;
 
866
            if (trans->distance().x()*fx/0.5 < 1.0 && trans->velocity().x()*fx/0.2 < 1.0 &&
 
867
                trans->distance().y()*fy/0.5 < 1.0 && trans->velocity().y()*fy/0.2 < 1.0) {
 
868
                // Hide tiny oscillations
 
869
                motion->translation.finish();
 
870
                ++stopped;
 
871
            }
 
872
        }
 
873
 
 
874
        Motion2D *scale = &motion->scale;
 
875
        if (scale->distance().isNull())
 
876
            ++stopped;
 
877
        else {
 
878
            // Still scaling
 
879
            scale->calculate(time);
 
880
            const short fx = scale->target().x() < 1.0 ? -1 : 1;
 
881
            const short fy = scale->target().y() < 1.0 ? -1 : 1;
 
882
            if (scale->distance().x()*fx/0.001 < 1.0 && scale->velocity().x()*fx/0.05 < 1.0 &&
 
883
                scale->distance().y()*fy/0.001 < 1.0 && scale->velocity().y()*fy/0.05 < 1.0) {
 
884
                // Hide tiny oscillations
 
885
                motion->scale.finish();
 
886
                ++stopped;
 
887
            }
 
888
        }
 
889
 
 
890
        // We just finished this window's motion
 
891
        if (stopped == 2)
 
892
            m_movingWindowsSet.remove(it.key());
 
893
    }
 
894
}
 
895
 
 
896
void WindowMotionManager::reset()
 
897
{
 
898
    QHash<EffectWindow*, WindowMotion>::iterator it = m_managedWindows.begin();
 
899
    for (; it != m_managedWindows.end(); ++it) {
 
900
        WindowMotion *motion = &it.value();
 
901
        EffectWindow *window = it.key();
 
902
        motion->translation.setTarget(window->pos());
 
903
        motion->translation.finish();
 
904
        motion->scale.setTarget(QPointF(1.0, 1.0));
 
905
        motion->scale.finish();
 
906
    }
 
907
}
 
908
 
 
909
void WindowMotionManager::reset(EffectWindow *w)
 
910
{
 
911
    QHash<EffectWindow*, WindowMotion>::iterator it = m_managedWindows.find(w);
 
912
    if (it == m_managedWindows.end())
 
913
        return;
 
914
 
 
915
    WindowMotion *motion = &it.value();
 
916
    motion->translation.setTarget(w->pos());
 
917
    motion->translation.finish();
 
918
    motion->scale.setTarget(QPointF(1.0, 1.0));
 
919
    motion->scale.finish();
 
920
}
 
921
 
 
922
void WindowMotionManager::apply(EffectWindow *w, WindowPaintData &data)
 
923
{
 
924
    QHash<EffectWindow*, WindowMotion>::iterator it = m_managedWindows.find(w);
 
925
    if (it == m_managedWindows.end())
 
926
        return;
 
927
 
 
928
    // TODO: Take into account existing scale so that we can work with multiple managers (E.g. Present windows + grid)
 
929
    WindowMotion *motion = &it.value();
 
930
    data.xTranslate += motion->translation.value().x() - w->x();
 
931
    data.yTranslate += motion->translation.value().y() - w->y();
 
932
    data.xScale *= motion->scale.value().x();
 
933
    data.yScale *= motion->scale.value().y();
 
934
}
 
935
 
 
936
void WindowMotionManager::moveWindow(EffectWindow *w, QPoint target, double scale, double yScale)
 
937
{
 
938
    QHash<EffectWindow*, WindowMotion>::iterator it = m_managedWindows.find(w);
 
939
    if (it == m_managedWindows.end())
 
940
        abort(); // Notify the effect author that they did something wrong
 
941
 
 
942
    WindowMotion *motion = &it.value();
 
943
 
 
944
    if (yScale == 0.0)
 
945
        yScale = scale;
 
946
    QPointF scalePoint(scale, yScale);
 
947
 
 
948
    if (motion->translation.value() == target && motion->scale.value() == scalePoint)
 
949
        return; // Window already at that position
 
950
 
 
951
    motion->translation.setTarget(target);
 
952
    motion->scale.setTarget(scalePoint);
 
953
 
 
954
    m_movingWindowsSet << w;
 
955
}
 
956
 
 
957
QRectF WindowMotionManager::transformedGeometry(EffectWindow *w) const
 
958
{
 
959
    QHash<EffectWindow*, WindowMotion>::const_iterator it = m_managedWindows.constFind(w);
 
960
    if (it == m_managedWindows.end())
 
961
        return w->geometry();
 
962
 
 
963
    const WindowMotion *motion = &it.value();
 
964
    QRectF geometry(w->geometry());
 
965
 
 
966
    // TODO: Take into account existing scale so that we can work with multiple managers (E.g. Present windows + grid)
 
967
    geometry.moveTo(motion->translation.value());
 
968
    geometry.setWidth(geometry.width() * motion->scale.value().x());
 
969
    geometry.setHeight(geometry.height() * motion->scale.value().y());
 
970
 
 
971
    return geometry;
 
972
}
 
973
 
 
974
void WindowMotionManager::setTransformedGeometry(EffectWindow *w, const QRectF &geometry)
 
975
{
 
976
    QHash<EffectWindow*, WindowMotion>::iterator it = m_managedWindows.find(w);
 
977
    if (it == m_managedWindows.end())
 
978
        return;
 
979
    WindowMotion *motion = &it.value();
 
980
    motion->translation.setValue(geometry.topLeft());
 
981
    motion->scale.setValue(QPointF(geometry.width() / qreal(w->width()), geometry.height() / qreal(w->height())));
 
982
}
 
983
 
 
984
QRectF WindowMotionManager::targetGeometry(EffectWindow *w) const
 
985
{
 
986
    QHash<EffectWindow*, WindowMotion>::const_iterator it = m_managedWindows.constFind(w);
 
987
    if (it == m_managedWindows.end())
 
988
        return w->geometry();
 
989
 
 
990
    const WindowMotion *motion = &it.value();
 
991
    QRectF geometry(w->geometry());
 
992
 
 
993
    // TODO: Take into account existing scale so that we can work with multiple managers (E.g. Present windows + grid)
 
994
    geometry.moveTo(motion->translation.target());
 
995
    geometry.setWidth(geometry.width() * motion->scale.target().x());
 
996
    geometry.setHeight(geometry.height() * motion->scale.target().y());
 
997
 
 
998
    return geometry;
 
999
}
 
1000
 
 
1001
EffectWindow* WindowMotionManager::windowAtPoint(QPoint point, bool useStackingOrder) const
 
1002
{
 
1003
    Q_UNUSED(useStackingOrder);
 
1004
    // TODO: Stacking order uses EffectsHandler::stackingOrder() then filters by m_managedWindows
 
1005
    QHash< EffectWindow*, WindowMotion >::ConstIterator it = m_managedWindows.constBegin();
 
1006
    while (it != m_managedWindows.constEnd()) {
 
1007
        if (transformedGeometry(it.key()).contains(point))
 
1008
            return it.key();
 
1009
        ++it;
 
1010
    }
 
1011
 
 
1012
    return NULL;
 
1013
}
 
1014
 
 
1015
/***************************************************************
 
1016
 EffectFramePrivate
 
1017
***************************************************************/
 
1018
class EffectFramePrivate
 
1019
{
 
1020
public:
 
1021
    EffectFramePrivate();
 
1022
    ~EffectFramePrivate();
 
1023
 
 
1024
    bool crossFading;
 
1025
    qreal crossFadeProgress;
 
1026
};
 
1027
 
 
1028
EffectFramePrivate::EffectFramePrivate()
 
1029
    : crossFading(false)
 
1030
    , crossFadeProgress(1.0)
 
1031
{
 
1032
}
 
1033
 
 
1034
EffectFramePrivate::~EffectFramePrivate()
 
1035
{
 
1036
}
 
1037
 
 
1038
/***************************************************************
 
1039
 EffectFrame
 
1040
***************************************************************/
 
1041
EffectFrame::EffectFrame()
 
1042
    : d(new EffectFramePrivate)
 
1043
{
 
1044
}
 
1045
 
 
1046
EffectFrame::~EffectFrame()
 
1047
{
 
1048
    delete d;
 
1049
}
 
1050
 
 
1051
qreal EffectFrame::crossFadeProgress() const
 
1052
{
 
1053
    return d->crossFadeProgress;
 
1054
}
 
1055
 
 
1056
void EffectFrame::setCrossFadeProgress(qreal progress)
 
1057
{
 
1058
    d->crossFadeProgress = progress;
 
1059
}
 
1060
 
 
1061
bool EffectFrame::isCrossFade() const
 
1062
{
 
1063
    return d->crossFading;
 
1064
}
 
1065
 
 
1066
void EffectFrame::enableCrossFade(bool enable)
 
1067
{
 
1068
    d->crossFading = enable;
 
1069
}
 
1070
 
 
1071
} // namespace
 
1072
 
 
1073
#include "kwineffects.moc"