not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kwin / effects / magiclamp.cpp
blob04e3ac0b2e117c61d27b44f59827345099874e0a
1 /********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
5 Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.com>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *********************************************************************/
21 // based on minimize animation by Rivo Laks <rivolaks@hot.ee>
23 #include "magiclamp.h"
24 #include <kwinconfig.h>
25 #include <kconfiggroup.h>
27 namespace KWin
30 KWIN_EFFECT( magiclamp, MagicLampEffect )
32 MagicLampEffect::MagicLampEffect()
34 mActiveAnimations = 0;
35 reconfigure( ReconfigureAll );
38 void MagicLampEffect::reconfigure( ReconfigureFlags )
40 KConfigGroup conf = effects->effectConfig( "MagicLamp" );
41 mAnimationDuration = animationTime( conf, "AnimationDuration", 250 );
44 void MagicLampEffect::prePaintScreen( ScreenPrePaintData& data, int time )
46 mActiveAnimations = mTimeLineWindows.count();
47 if( mActiveAnimations > 0 )
48 // We need to mark the screen windows as transformed. Otherwise the
49 // whole screen won't be repainted, resulting in artefacts
50 data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
52 effects->prePaintScreen(data, time);
55 void MagicLampEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
57 if( mTimeLineWindows.contains( w ))
59 if( w->isMinimized() )
61 mTimeLineWindows[w].addTime(time);
62 if( mTimeLineWindows[w].progress() >= 1.0f )
63 mTimeLineWindows.remove( w );
65 else
67 mTimeLineWindows[w].removeTime(time);
68 if( mTimeLineWindows[w].progress() <= 0.0f )
69 mTimeLineWindows.remove( w );
72 // Schedule window for transformation if the animation is still in
73 // progress
74 if( mTimeLineWindows.contains( w ))
76 // We'll transform this window
77 data.setTransformed();
78 data.quads = data.quads.makeGrid( 40 );
79 w->enablePainting( EffectWindow::PAINT_DISABLED_BY_MINIMIZE );
83 effects->prePaintWindow( w, data, time );
86 void MagicLampEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
88 if( mTimeLineWindows.contains( w ))
90 // 0 = not minimized, 1 = fully minimized
91 float progress = mTimeLineWindows[w].value();
93 QRect geo = w->geometry();
94 QRect icon = w->iconGeometry();
95 // If there's no icon geometry, minimize to the center of the screen
96 if( !icon.isValid() )
97 icon = QRect( displayWidth() / 2, displayHeight(), 0, 0 );
99 QRect area = effects->clientArea( PlacementArea, w );
100 IconPosition position = Bottom;
101 // top
102 if( icon.y() + icon.height() <= area.y() )
104 position = Top;
106 // bottom
107 if( icon.y() >= area.y()+area.height() )
109 position = Bottom;
111 // left
112 if( icon.x() + icon.width() <= area.x() )
114 position = Left;
116 // right
117 if( icon.x() >= area.x()+ area.width() )
119 position = Right;
122 WindowQuadList newQuads;
123 foreach( WindowQuad quad, data.quads )
125 if( position == Top || position == Bottom )
127 // quadFactor defines how fast a quad is vertically moved: y coordinates near to window top are slowed down
128 // it is used as quadFactor^3/windowHeight^3
129 // quadFactor is the y position of the quad but is changed towards becomming the window height
130 // by that the factor becomes 1 and has no influence any more
131 float quadFactor;
132 // how far has a quad to be moved? Distance between icon and window multiplied by the progress and by the quadFactor
133 float yOffsetTop;
134 float yOffsetBottom;
135 // top and bottom progress is the factor which defines how far the x values have to be changed
136 // factor is the current moved y value diveded by the distance between icon and window
137 float topProgress;
138 float bottomProgress;
139 if( position == Bottom )
141 quadFactor = quad[0].y() + (geo.height() - quad[0].y())*progress;
142 yOffsetTop = (icon.y() + quad[0].y() - geo.y())*progress*
143 ((quadFactor*quadFactor*quadFactor)/(geo.height()*geo.height()*geo.height()));
144 quadFactor = quad[2].y() + (geo.height() - quad[2].y())*progress;
145 yOffsetBottom = (icon.y() + quad[2].y() - geo.y())*progress*
146 ((quadFactor*quadFactor*quadFactor)/(geo.height()*geo.height()*geo.height()));
147 topProgress = qMin( yOffsetTop/(icon.y()+icon.height() - geo.y()-(float)(quad[0].y()/geo.height()*geo.height())), 1.0f );
148 bottomProgress = qMin( yOffsetBottom/(icon.y()+icon.height() - geo.y()-(float)(quad[2].y()/geo.height()*geo.height())), 1.0f );
150 else
152 quadFactor = geo.height() - quad[0].y() + (quad[0].y())*progress;
153 yOffsetTop = (geo.y() - icon.height() + geo.height() + quad[0].y() - icon.y())*progress*
154 ((quadFactor*quadFactor*quadFactor)/(geo.height()*geo.height()*geo.height()));
155 quadFactor = geo.height() - quad[2].y() + (quad[2].y())*progress;
156 yOffsetBottom = (geo.y() - icon.height() + geo.height() + quad[2].y() - icon.y())*progress*
157 ((quadFactor*quadFactor*quadFactor)/(geo.height()*geo.height()*geo.height()));
158 topProgress = qMin( yOffsetTop/(geo.y() - icon.height() + geo.height() - icon.y() -
159 (float)((geo.height()-quad[0].y())/geo.height()*geo.height())), 1.0f );
160 bottomProgress = qMin( yOffsetBottom/(geo.y() - icon.height() + geo.height() - icon.y() -
161 (float)((geo.height()-quad[2].y())/geo.height()*geo.height())), 1.0f );
163 if( position == Top )
165 yOffsetTop *= -1;
166 yOffsetBottom *= -1;
168 if( topProgress < 0 )
169 topProgress *= -1;
170 if( bottomProgress < 0 )
171 bottomProgress *= -1;
173 // x values are moved towards the center of the icon
174 quad[0].setX( (icon.x() + icon.width()*(quad[0].x()/geo.width()) - (quad[0].x() + geo.x()))*topProgress + quad[0].x() );
175 quad[1].setX( (icon.x() + icon.width()*(quad[1].x()/geo.width()) - (quad[1].x() + geo.x()))*topProgress + quad[1].x() );
176 quad[2].setX( (icon.x() + icon.width()*(quad[2].x()/geo.width()) - (quad[2].x() + geo.x()))*bottomProgress + quad[2].x() );
177 quad[3].setX( (icon.x() + icon.width()*(quad[3].x()/geo.width()) - (quad[3].x() + geo.x()))*bottomProgress + quad[3].x() );
179 quad[0].setY( quad[0].y() + yOffsetTop );
180 quad[1].setY( quad[1].y() + yOffsetTop );
181 quad[2].setY( quad[2].y() + yOffsetBottom );
182 quad[3].setY( quad[3].y() + yOffsetBottom );
184 else
186 float quadFactor;
187 float xOffsetLeft;
188 float xOffsetRight;
189 float leftProgress;
190 float rightProgress;
191 if( position == Right )
193 quadFactor = quad[0].x() + (geo.width() - quad[0].x())*progress;
194 xOffsetLeft = (icon.x() + quad[0].x() - geo.x())*progress*
195 ((quadFactor*quadFactor*quadFactor)/(geo.width()*geo.width()*geo.width()));
196 quadFactor = quad[1].x() + (geo.width() - quad[1].x())*progress;
197 xOffsetRight = (icon.x() + quad[1].x() - geo.x())*progress*
198 ((quadFactor*quadFactor*quadFactor)/(geo.width()*geo.width()*geo.width()));
199 leftProgress = qMin( xOffsetLeft/(icon.x()+icon.width() - geo.x()-(float)(quad[0].x()/geo.width()*geo.width())), 1.0f );
200 rightProgress = qMin( xOffsetRight/(icon.x()+icon.width() - geo.x()-(float)(quad[1].x()/geo.width()*geo.width())), 1.0f );
202 else
204 quadFactor = geo.width() - quad[0].x() + (quad[0].x())*progress;
205 xOffsetLeft = (geo.x() - icon.width() + geo.width() + quad[0].x() - icon.x())*progress*
206 ((quadFactor*quadFactor*quadFactor)/(geo.width()*geo.width()*geo.width()));
207 quadFactor = geo.width() - quad[1].x() + (quad[1].x())*progress;
208 xOffsetRight = (geo.x() - icon.width() + geo.width() + quad[1].x() - icon.x())*progress*
209 ((quadFactor*quadFactor*quadFactor)/(geo.width()*geo.width()*geo.width()));
210 leftProgress = qMin( xOffsetLeft/(geo.x() - icon.width() + geo.width() - icon.x() -
211 (float)((geo.width()-quad[0].x())/geo.width()*geo.width())), 1.0f );
212 rightProgress = qMin( xOffsetRight/(geo.x() - icon.width() + geo.width() - icon.x() -
213 (float)((geo.width()-quad[1].x())/geo.width()*geo.width())), 1.0f );
215 if( position == Left )
217 xOffsetLeft *= -1;
218 xOffsetRight *= -1;
220 if( leftProgress < 0 )
221 leftProgress *= -1;
222 if( rightProgress < 0 )
223 rightProgress *= -1;
225 quad[0].setY( (icon.y() + icon.height()*(quad[0].y()/geo.height()) - (quad[0].y() + geo.y()))*leftProgress + quad[0].y() );
226 quad[1].setY( (icon.y() + icon.height()*(quad[1].y()/geo.height()) - (quad[1].y() + geo.y()))*rightProgress + quad[1].y() );
227 quad[2].setY( (icon.y() + icon.height()*(quad[2].y()/geo.height()) - (quad[2].y() + geo.y()))*rightProgress + quad[2].y() );
228 quad[3].setY( (icon.y() + icon.height()*(quad[3].y()/geo.height()) - (quad[3].y() + geo.y()))*leftProgress + quad[3].y() );
230 quad[0].setX( quad[0].x() + xOffsetLeft );
231 quad[1].setX( quad[1].x() + xOffsetRight );
232 quad[2].setX( quad[2].x() + xOffsetRight );
233 quad[3].setX( quad[3].x() + xOffsetLeft );
235 newQuads.append( quad );
237 data.quads = newQuads;
240 // Call the next effect.
241 effects->paintWindow( w, mask, region, data );
244 void MagicLampEffect::postPaintScreen()
246 if( mActiveAnimations > 0 )
247 // Repaint the workspace so that everything would be repainted next time
248 effects->addRepaintFull();
249 mActiveAnimations = mTimeLineWindows.count();
251 // Call the next effect.
252 effects->postPaintScreen();
255 void MagicLampEffect::windowMinimized( EffectWindow* w )
257 mTimeLineWindows[w].setCurveShape(TimeLine::LinearCurve);
258 mTimeLineWindows[w].setDuration( mAnimationDuration );
259 mTimeLineWindows[w].setProgress(0.0f);
262 void MagicLampEffect::windowUnminimized( EffectWindow* w )
264 mTimeLineWindows[w].setCurveShape(TimeLine::LinearCurve);
265 mTimeLineWindows[w].setDuration( mAnimationDuration );
266 mTimeLineWindows[w].setProgress(1.0f);
269 } // namespace