Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / kwin / effects / snow.cpp
blob8efe401f90e17aec6cfb172633234c851e1488ce
1 /********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
5 Copyright (C) 2007 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 #include "snow.h"
23 #include <kwinconfig.h>
25 #include <kaction.h>
26 #include <kactioncollection.h>
27 #include <kconfiggroup.h>
28 #include <kglobal.h>
29 #include <klocale.h>
30 #include <kstandarddirs.h>
32 #include <kdebug.h>
33 #include <QApplication>
34 #include <QDesktopWidget>
36 #include <ctime>
38 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
39 #include <GL/gl.h>
40 #endif
43 namespace KWin
46 KWIN_EFFECT( snow, SnowEffect )
48 SnowEffect::SnowEffect()
49 : texture( NULL )
50 , flakes( NULL )
51 , active( false)
53 srandom( std::time( NULL ) );
54 lastFlakeTime = QTime::currentTime();
55 nextFlakeMillis = 0;
56 KConfigGroup conf = effects->effectConfig("Snow");
57 mNumberFlakes = conf.readEntry("Number", 50);
58 mMinFlakeSize = conf.readEntry("MinFlakes", 10);
59 mMaxFlakeSize = conf.readEntry("MaxFlakes", 50);
61 KActionCollection* actionCollection = new KActionCollection( this );
62 KAction* a = static_cast< KAction* >( actionCollection->addAction( "Snow" ));
63 a->setText( i18n("Snow" ));
64 a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::META + Qt::Key_F12 ));
65 connect( a, SIGNAL( triggered( bool )), this, SLOT( toggle()));
68 SnowEffect::~SnowEffect()
70 delete texture;
71 delete flakes;
74 void SnowEffect::prePaintScreen( ScreenPrePaintData& data, int time )
76 if ( active )
78 if (! flakes )
80 flakes = new QList<QRect>();
81 lastFlakeTime.start();
83 int count = flakes->count();
84 for (int i=0; i<count; i++)
86 // move flake to bottom. Therefore pop the flake, change y and push
87 // flake back to QVector
88 QRect flake = flakes->first();
89 flakes->pop_front();
90 int size = flake.height();
91 int y = flake.y();
92 // if flake has reached bottom, don't push it back
93 if ( y >= QApplication::desktop()->geometry().bottom() )
95 continue;
97 int speed;
98 float factor = (float)(size-mMinFlakeSize) / (float)(mMaxFlakeSize-mMinFlakeSize);
99 if (factor >= 0.5) speed = 2;
100 else speed = 1;
101 flake.setY(y + speed);
102 flake.setHeight(size);
103 flakes->append(flake);
105 // if number of active snowflakes is smaller than maximum number
106 // create a random new snowflake
107 if ( ( lastFlakeTime.elapsed() >= nextFlakeMillis ) && flakes->count() < mNumberFlakes)
109 int size = 0;
110 while ( size < mMinFlakeSize )
111 size = random() % mMaxFlakeSize;
112 QRect flake = QRect( random() % (QApplication::desktop()->geometry().right() - size), -1 * size, size, size );
113 flakes->append( flake );
115 // calculation of next time of snowflake
116 // depends on the time the flow needs to get to the bottom (screen size)
117 // and the fps
118 int speed;
119 float factor = (float)(size-mMinFlakeSize) / (float)(mMaxFlakeSize-mMinFlakeSize);
120 if (factor >= 0.5) speed = 4;
121 else speed = 2;
122 long next = ((1000/(time+5))*(Effect::displayHeight()/speed))/mNumberFlakes;
123 nextFlakeMillis = next;
124 lastFlakeTime.restart();
127 effects->prePaintScreen( data, time );
130 void SnowEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
132 effects->paintScreen( mask, region, data ); // paint normal screen
133 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
134 if( active )
136 if(! texture ) loadTexture();
137 if( texture )
139 glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT );
140 texture->bind();
141 glEnable( GL_BLEND );
142 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
143 for (int i=0; i<flakes->count(); i++)
145 texture->render( region, flakes->at(i));
147 texture->unbind();
148 glPopAttrib();
151 #endif
154 void SnowEffect::postPaintScreen()
156 if( active )
158 effects->addRepaintFull();
160 effects->postPaintScreen();
163 void SnowEffect::toggle()
165 active = !active;
166 if (!active) flakes->clear();
167 effects->addRepaintFull();
170 void SnowEffect::loadTexture()
172 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
173 QString file = KGlobal::dirs()->findResource( "appdata", "snowflake.png" );
174 if( file.isEmpty())
175 return;
176 texture = new GLTexture( file );
177 #endif
181 } // namespace