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

« back to all changes in this revision

Viewing changes to kwin/effects/slide/slide.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

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) 2007 Lubos Lunak <l.lunak@kde.org>
 
6
Copyright (C) 2008 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 "slide.h"
 
23
 
 
24
#include <math.h>
 
25
 
 
26
namespace KWin
 
27
{
 
28
 
 
29
KWIN_EFFECT(slide, SlideEffect)
 
30
 
 
31
SlideEffect::SlideEffect()
 
32
    : slide(false)
 
33
{
 
34
    connect(effects, SIGNAL(desktopChanged(int,int)), this, SLOT(slotDesktopChanged(int,int)));
 
35
    mTimeLine.setCurveShape(QTimeLine::EaseInOutCurve);
 
36
    reconfigure(ReconfigureAll);
 
37
}
 
38
 
 
39
void SlideEffect::reconfigure(ReconfigureFlags)
 
40
{
 
41
    mTimeLine.setDuration(animationTime(250));
 
42
}
 
43
 
 
44
void SlideEffect::prePaintScreen(ScreenPrePaintData& data, int time)
 
45
{
 
46
    if (slide) {
 
47
        mTimeLine.setCurrentTime(mTimeLine.currentTime() + time);
 
48
 
 
49
        // PAINT_SCREEN_BACKGROUND_FIRST is needed because screen will be actually painted more than once,
 
50
        // so with normal screen painting second screen paint would erase parts of the first paint
 
51
        if (mTimeLine.currentValue() != 1)
 
52
            data.mask |= PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_BACKGROUND_FIRST;
 
53
        else {
 
54
            slide = false;
 
55
            mTimeLine.setCurrentTime(0);
 
56
            effects->setActiveFullScreenEffect(NULL);
 
57
        }
 
58
    }
 
59
    effects->prePaintScreen(data, time);
 
60
}
 
61
 
 
62
void SlideEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time)
 
63
{
 
64
    if (slide) {
 
65
        if (w->isOnAllDesktops()) {
 
66
            if (slide_painting_sticky)
 
67
                data.setTransformed();
 
68
            else
 
69
                w->disablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
 
70
        } else if (w->isOnDesktop(painting_desktop))
 
71
            w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
 
72
        else
 
73
            w->disablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
 
74
    }
 
75
    effects->prePaintWindow(w, data, time);
 
76
}
 
77
 
 
78
void SlideEffect::paintScreen(int mask, QRegion region, ScreenPaintData& data)
 
79
{
 
80
    if (mTimeLine.currentValue() == 0) {
 
81
        effects->paintScreen(mask, region, data);
 
82
        return;
 
83
    }
 
84
 
 
85
    /*
 
86
     Transformations are done by remembering starting position of the change and the progress
 
87
     of it, the destination is computed from the current desktop. Positions of desktops
 
88
     are done using their topleft corner.
 
89
    */
 
90
    QPoint destPos = desktopRect(effects->currentDesktop()).topLeft();
 
91
    QPoint diffPos = destPos - slide_start_pos;
 
92
    int w = 0;
 
93
    int h = 0;
 
94
    if (effects->optionRollOverDesktops()) {
 
95
        w = effects->workspaceWidth();
 
96
        h = effects->workspaceHeight();
 
97
        // wrap around if shorter
 
98
        if (diffPos.x() > 0 && diffPos.x() > w / 2)
 
99
            diffPos.setX(diffPos.x() - w);
 
100
        if (diffPos.x() < 0 && abs(diffPos.x()) > w / 2)
 
101
            diffPos.setX(diffPos.x() + w);
 
102
        if (diffPos.y() > 0 && diffPos.y() > h / 2)
 
103
            diffPos.setY(diffPos.y() - h);
 
104
        if (diffPos.y() < 0 && abs(diffPos.y()) > h / 2)
 
105
            diffPos.setY(diffPos.y() + h);
 
106
    }
 
107
    QPoint currentPos = slide_start_pos + mTimeLine.currentValue() * diffPos;
 
108
    QSize displaySize(displayWidth(), displayHeight());
 
109
    QRegion currentRegion = QRect(currentPos, displaySize);
 
110
    if (effects->optionRollOverDesktops()) {
 
111
        currentRegion |= (currentRegion & QRect(-w, 0, w, h)).translated(w, 0);
 
112
        currentRegion |= (currentRegion & QRect(0, -h, w, h)).translated(0, h);
 
113
        currentRegion |= (currentRegion & QRect(w, 0, w, h)).translated(-w, 0);
 
114
        currentRegion |= (currentRegion & QRect(0, h, w, h)).translated(0, -h);
 
115
    }
 
116
    bool do_sticky = true;
 
117
    for (int desktop = 1;
 
118
            desktop <= effects->numberOfDesktops();
 
119
            ++desktop) {
 
120
        QRect rect = desktopRect(desktop);
 
121
        if (currentRegion.contains(rect)) {  // part of the desktop needs painting
 
122
            painting_desktop = desktop;
 
123
            slide_painting_sticky = do_sticky;
 
124
            slide_painting_diff = rect.topLeft() - currentPos;
 
125
            if (effects->optionRollOverDesktops()) {
 
126
                if (slide_painting_diff.x() > displayWidth())
 
127
                    slide_painting_diff.setX(slide_painting_diff.x() - w);
 
128
                if (slide_painting_diff.x() < -displayWidth())
 
129
                    slide_painting_diff.setX(slide_painting_diff.x() + w);
 
130
                if (slide_painting_diff.y() > displayHeight())
 
131
                    slide_painting_diff.setY(slide_painting_diff.y() - h);
 
132
                if (slide_painting_diff.y() < -displayHeight())
 
133
                    slide_painting_diff.setY(slide_painting_diff.y() + h);
 
134
            }
 
135
            do_sticky = false; // paint on-all-desktop windows only once
 
136
            ScreenPaintData d = data;
 
137
            d.xTranslate += slide_painting_diff.x();
 
138
            d.yTranslate += slide_painting_diff.y();
 
139
            // TODO mask parts that are not visible?
 
140
            effects->paintScreen(mask, region, d);
 
141
        }
 
142
    }
 
143
}
 
144
 
 
145
void SlideEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data)
 
146
{
 
147
    if (slide) {
 
148
        // don't move windows on all desktops (compensate screen transformation)
 
149
        if (w->isOnAllDesktops()) { // TODO also fix 'Workspace::movingClient'
 
150
            data.xTranslate -= slide_painting_diff.x();
 
151
            data.yTranslate -= slide_painting_diff.y();
 
152
        }
 
153
    }
 
154
    effects->paintWindow(w, mask, region, data);
 
155
}
 
156
 
 
157
void SlideEffect::postPaintScreen()
 
158
{
 
159
    if (slide)
 
160
        effects->addRepaintFull();
 
161
    effects->postPaintScreen();
 
162
}
 
163
 
 
164
// Gives a position of the given desktop when all desktops are arranged in a grid
 
165
QRect SlideEffect::desktopRect(int desktop) const
 
166
{
 
167
    QRect rect(0, 0, displayWidth(), displayHeight());
 
168
    rect.translate(effects->desktopCoords(desktop));
 
169
    return rect;
 
170
}
 
171
 
 
172
void SlideEffect::slotDesktopChanged(int old, int current)
 
173
{
 
174
    if (effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this)
 
175
        return;
 
176
 
 
177
    if (slide) { // old slide still in progress
 
178
        QPoint diffPos = desktopRect(old).topLeft() - slide_start_pos;
 
179
        int w = 0;
 
180
        int h = 0;
 
181
        if (effects->optionRollOverDesktops()) {
 
182
            w = effects->workspaceWidth();
 
183
            h = effects->workspaceHeight();
 
184
            // wrap around if shorter
 
185
            if (diffPos.x() > 0 && diffPos.x() > w / 2)
 
186
                diffPos.setX(diffPos.x() - w);
 
187
            if (diffPos.x() < 0 && abs(diffPos.x()) > w / 2)
 
188
                diffPos.setX(diffPos.x() + w);
 
189
            if (diffPos.y() > 0 && diffPos.y() > h / 2)
 
190
                diffPos.setY(diffPos.y() - h);
 
191
            if (diffPos.y() < 0 && abs(diffPos.y()) > h / 2)
 
192
                diffPos.setY(diffPos.y() + h);
 
193
        }
 
194
        QPoint currentPos = slide_start_pos + mTimeLine.currentValue() * diffPos;
 
195
        QRegion currentRegion = QRect(currentPos, QSize(displayWidth(), displayHeight()));
 
196
        if (effects->optionRollOverDesktops()) {
 
197
            currentRegion |= (currentRegion & QRect(-w, 0, w, h)).translated(w, 0);
 
198
            currentRegion |= (currentRegion & QRect(0, -h, w, h)).translated(0, h);
 
199
            currentRegion |= (currentRegion & QRect(w, 0, w, h)).translated(-w, 0);
 
200
            currentRegion |= (currentRegion & QRect(0, h, w, h)).translated(0, -h);
 
201
        }
 
202
        QRect rect = desktopRect(current);
 
203
        if (currentRegion.contains(rect)) {
 
204
            // current position is in new current desktop (e.g. quickly changing back),
 
205
            // don't do full progress
 
206
            if (abs(currentPos.x() - rect.x()) > abs(currentPos.y() - rect.y()))
 
207
                mTimeLine.setCurrentTime((1.0 - abs(currentPos.x() - rect.x()) / double(displayWidth()))*(qreal)mTimeLine.currentValue());
 
208
            else
 
209
                mTimeLine.setCurrentTime((1.0 - abs(currentPos.y() - rect.y()) / double(displayHeight()))*(qreal)mTimeLine.currentValue());
 
210
        } else // current position is not on current desktop, do full progress
 
211
            mTimeLine.setCurrentTime(0);
 
212
        diffPos = rect.topLeft() - currentPos;
 
213
        if (mTimeLine.currentValue() <= 0) {
 
214
            // Compute starting point for this new move (given current and end positions)
 
215
            slide_start_pos = rect.topLeft() - diffPos * 1 / (1 - mTimeLine.currentValue());
 
216
        } else {
 
217
            // at the end, stop
 
218
            slide = false;
 
219
            mTimeLine.setCurrentTime(0);
 
220
            effects->setActiveFullScreenEffect(NULL);
 
221
        }
 
222
    } else {
 
223
        if (effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this)
 
224
            return;
 
225
        mTimeLine.setCurrentTime(0);
 
226
        slide_start_pos = desktopRect(old).topLeft();
 
227
        slide = true;
 
228
        effects->setActiveFullScreenEffect(this);
 
229
    }
 
230
    effects->addRepaintFull();
 
231
}
 
232
 
 
233
} // namespace
 
234
 
 
235
#include "slide.moc"