[prev in list] [next in list] [prev in thread] [next in thread]
List: kwin
Subject: Re: Snow Effect for Kwin
From: Martin Graesslin <ubuntu () martin-graesslin ! com>
Date: 2007-12-28 11:41:17
Message-ID: 200712281241.22533.ubuntu () martin-graesslin ! com
[Download RAW message or body]
[Attachment #2 (multipart/signed)]
[Attachment #4 (multipart/mixed)]
> - we usually use Qt Designer to create GUI these days (we have GUI
I included an ui-file. So it is consistent.
>
> - #include <config-X11.h> is #include <kwinconfig.h> and HAVE_OPENGL is
> KWIN_HAVE_OPENGL_COMPOSITING now (this is very recent, from yesterday)
changed
>
> - translations in .desktop files are done by translators separately and are
> merged in automatically, so things like "Name[de]=Schnee" will be
> overwritten anyway
Good to know for the next time ;-) Removed those lines.
>
> - please make X-Ordering only 90, to allow system effects after it
changed
>
> - maybe you want to clear the list of flakes in toggle() to make the effect
> start anew when activated again
I added this point.
>
> That's it, I guess, I cannot see anything more. Taking the picture from
> Compiz Fusion should be okay, it is GPLv2+ just like KWin.
So I hope it is OK, now. Here's the code again ;-)
Best regards
Martin Gräßlin
["snow.diff" (text/x-diff)]
Index: snow_config.h
===================================================================
--- snow_config.h (Revision 0)
+++ snow_config.h (Revision 0)
@@ -0,0 +1,61 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+ Copyright (C) 2007 Martin Gräßlin <ubuntu@martin-graesslin.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+
+#ifndef KWIN_SNOW_CONFIG_H
+#define KWIN_SNOW_CONFIG_H
+
+#define KDE3_SUPPORT
+#include <kcmodule.h>
+#undef KDE3_SUPPORT
+
+#include "ui_snow_config.h"
+
+class KActionCollection;
+
+namespace KWin
+{
+
+class SnowEffectConfigForm : public QWidget, public Ui::SnowEffectConfigForm
+{
+ Q_OBJECT
+ public:
+ explicit SnowEffectConfigForm(QWidget* parent);
+};
+
+class SnowEffectConfig : public KCModule
+ {
+ Q_OBJECT
+ public:
+ explicit SnowEffectConfig(QWidget* parent = 0, const QVariantList& args = \
QVariantList()); + ~SnowEffectConfig();
+
+ public slots:
+ virtual void save();
+ virtual void load();
+ virtual void defaults();
+
+ private:
+ SnowEffectConfigForm* m_ui;
+ KActionCollection* m_actionCollection;
+ };
+
+} // namespace
+
+#endif
Index: snow_config.cpp
===================================================================
--- snow_config.cpp (Revision 0)
+++ snow_config.cpp (Revision 0)
@@ -0,0 +1,124 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+ Copyright (C) 2007 Martin Gräßlin <ubuntu@martin-graesslin.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+#include "snow_config.h"
+#include <kwineffects.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <KActionCollection>
+#include <kaction.h>
+#include <KGlobalAccel>
+#include <kconfiggroup.h>
+
+#include <QGridLayout>
+#ifndef KDE_USE_FINAL
+KWIN_EFFECT_CONFIG_FACTORY
+#endif
+namespace KWin
+{
+
+SnowEffectConfigForm::SnowEffectConfigForm(QWidget* parent) : QWidget(parent)
+{
+ setupUi(this);
+}
+
+SnowEffectConfig::SnowEffectConfig(QWidget* parent, const QVariantList& args) :
+ KCModule(EffectFactory::componentData(), parent, args)
+ {
+ kDebug() ;
+
+ m_ui = new SnowEffectConfigForm(this);
+
+ QGridLayout* layout = new QGridLayout(this);
+
+ layout->addWidget(m_ui, 0, 0);
+
+ connect(m_ui->editor, SIGNAL(keyChange()), this, SLOT(changed()));
+ connect(m_ui->numberFlakes, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+ connect(m_ui->minSizeFlake, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+ connect(m_ui->maxSizeFlake, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+
+ KGlobalAccel::self()->overrideMainComponentData(componentData());
+ m_actionCollection = new KActionCollection( this, componentData() );
+ m_actionCollection->setConfigGroup("Snow");
+ m_actionCollection->setConfigGlobal(true);
+
+ KAction* a = (KAction*)m_actionCollection->addAction( "Snow" );
+ a->setText( i18n("Toggle Snow on the desktop" ));
+ a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::META + Qt::Key_F12 ));
+
+ load();
+ }
+
+SnowEffectConfig::~SnowEffectConfig()
+ {
+ kDebug() ;
+ }
+
+void SnowEffectConfig::load()
+ {
+ kDebug() ;
+ KCModule::load();
+
+ KConfigGroup conf = EffectsHandler::effectConfig("Snow");
+
+ int number = conf.readEntry("Number", 50);
+ int minFlake = conf.readEntry("MinFlakes", 10);
+ int maxFlake = conf.readEntry("MaxFlakes", 50);
+ m_ui->numberFlakes->setValue( number );
+ m_ui->minSizeFlake->setValue( minFlake );
+ m_ui->maxSizeFlake->setValue( maxFlake );
+
+ m_actionCollection->readSettings();
+ m_ui->editor->addCollection(m_actionCollection);
+
+ emit changed(false);
+ }
+
+void SnowEffectConfig::save()
+ {
+ kDebug() ;
+
+ KConfigGroup conf = EffectsHandler::effectConfig("Snow");
+ conf.writeEntry("Number", m_ui->numberFlakes->value());
+ conf.writeEntry("MinFlakes", m_ui->minSizeFlake->value());
+ conf.writeEntry("MaxFlakes", m_ui->maxSizeFlake->value());
+
+ m_actionCollection->writeSettings();
+
+ conf.sync();
+
+ emit changed(false);
+ EffectsHandler::sendReloadMessage( "snow" );
+ }
+
+void SnowEffectConfig::defaults()
+ {
+ kDebug() ;
+ m_ui->numberFlakes->setValue( 50 );
+ m_ui->minSizeFlake->setValue( 10 );
+ m_ui->maxSizeFlake->setValue( 50 );
+ emit changed(true);
+ }
+
+
+} // namespace
+
+#include "snow_config.moc"
Index: snow.cpp
===================================================================
--- snow.cpp (Revision 0)
+++ snow.cpp (Revision 0)
@@ -0,0 +1,181 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+ Copyright (C) 2007 Martin Gräßlin <ubuntu@martin-graesslin.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+
+#include "snow.h"
+
+#include <kwinconfig.h>
+
+#include <kaction.h>
+#include <kactioncollection.h>
+#include <kconfiggroup.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+
+#include <kdebug.h>
+#include <QApplication>
+#include <QDesktopWidget>
+
+#include <ctime>
+
+#ifdef KWIN_HAVE_OPENGL_COMPOSITING
+#include <GL/gl.h>
+#endif
+
+
+namespace KWin
+{
+
+KWIN_EFFECT( snow, SnowEffect )
+
+SnowEffect::SnowEffect()
+ : texture( NULL )
+ , flakes( NULL )
+ , active( false)
+ {
+ srandom( std::time( NULL ) );
+ lastFlakeTime = QTime::currentTime();
+ nextFlakeMillis = 0;
+ KConfigGroup conf = effects->effectConfig("Snow");
+ mNumberFlakes = conf.readEntry("Number", 50);
+ mMinFlakeSize = conf.readEntry("MinFlakes", 10);
+ mMaxFlakeSize = conf.readEntry("MaxFlakes", 50);
+
+ KActionCollection* actionCollection = new KActionCollection( this );
+ KAction* a = static_cast< KAction* >( actionCollection->addAction( "Snow" ));
+ a->setText( i18n("Snow" ));
+ a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::META + Qt::Key_F12 ));
+ connect( a, SIGNAL( triggered( bool )), this, SLOT( toggle()));
+ }
+
+SnowEffect::~SnowEffect()
+ {
+ delete texture;
+ delete flakes;
+ }
+
+void SnowEffect::prePaintScreen( ScreenPrePaintData& data, int time )
+ {
+ if ( active )
+ {
+ if (! flakes )
+ {
+ flakes = new QList<QRect>();
+ lastFlakeTime.start();
+ }
+ int count = flakes->count();
+ for (int i=0; i<count; i++)
+ {
+ // move flake to bottom. Therefore pop the flake, change y and push
+ // flake back to QVector
+ QRect flake = flakes->first();
+ flakes->pop_front();
+ int size = flake.height();
+ int y = flake.y();
+ // if flake has reached bottom, don't push it back
+ if ( y >= QApplication::desktop()->geometry().bottom() )
+ {
+ continue;
+ }
+ int speed;
+ float factor = (float)(size-mMinFlakeSize) / \
(float)(mMaxFlakeSize-mMinFlakeSize); + if (factor >= 0.5) speed = 2;
+ else speed = 1;
+ flake.setY(y + speed);
+ flake.setHeight(size);
+ flakes->append(flake);
+ }
+ // if number of active snowflakes is smaller than maximum number
+ // create a random new snowflake
+ if ( ( lastFlakeTime.elapsed() >= nextFlakeMillis ) && flakes->count() < \
mNumberFlakes) + {
+ int size = 0;
+ while ( size < mMinFlakeSize )
+ size = random() % mMaxFlakeSize;
+ QRect flake = QRect( random() % \
(QApplication::desktop()->geometry().right() - size), -1 * size, size, size ); + \
flakes->append( flake ); +
+ // calculation of next time of snowflake
+ // depends on the time the flow needs to get to the bottom (screen \
size) + // and the fps
+ int speed;
+ float factor = (float)(size-mMinFlakeSize) / \
(float)(mMaxFlakeSize-mMinFlakeSize); + if (factor >= 0.5) speed = 4;
+ else speed = 2;
+ long next = \
((1000/(time+5))*(Effect::displayHeight()/speed))/mNumberFlakes; + \
nextFlakeMillis = next; + lastFlakeTime.restart();
+ }
+ }
+ effects->prePaintScreen( data, time );
+ }
+
+void SnowEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
+ {
+ effects->paintScreen( mask, region, data ); // paint normal screen
+#ifdef KWIN_HAVE_OPENGL_COMPOSITING
+ if( active )
+ {
+ if(! texture ) loadTexture();
+ if( texture )
+ {
+ glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT );
+ texture->bind();
+ glEnable( GL_BLEND );
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+ for (int i=0; i<flakes->count(); i++)
+ {
+ texture->render( false, region, flakes->at(i));
+ }
+ texture->unbind();
+ glPopAttrib();
+ }
+ }
+#endif
+ }
+
+void SnowEffect::postPaintScreen()
+ {
+ if( active )
+ {
+ effects->addRepaintFull();
+ }
+ effects->postPaintScreen();
+ }
+
+void SnowEffect::toggle()
+ {
+ active = !active;
+ if (!active) flakes->clear();
+ effects->addRepaintFull();
+ }
+
+void SnowEffect::loadTexture()
+ {
+#ifdef KWIN_HAVE_OPENGL_COMPOSITING
+ QString file = KGlobal::dirs()->findResource( "appdata", "snowflake.png" );
+ if( file.isEmpty())
+ return;
+ texture = new GLTexture( file );
+#endif
+ }
+
+
+} // namespace
Index: snow.desktop
===================================================================
--- snow.desktop (Revision 0)
+++ snow.desktop (Revision 0)
@@ -0,0 +1,28 @@
+[Desktop Entry]
+# Name of the effect
+Name=Snow
+Comment=Let it snow on the desktop
+Icon=preferences-system-windows-effect-snow
+
+# This is KWin effect
+Type=Service
+X-KDE-ServiceTypes=KWin/Effect
+# Author and email of the author
+X-KDE-PluginInfo-Author=Martin Gräßlin
+X-KDE-PluginInfo-Email=ubuntu@martin-graesslin.com
+# Internal name of the effect
+X-KDE-PluginInfo-Name=kwin4_effect_snow
+# Category of the effect, for config dialog
+X-KDE-PluginInfo-Category=Misc
+# Version and license
+X-KDE-PluginInfo-Version=0.1.2
+X-KDE-PluginInfo-License=GPL
+# If the effect depends on any other effect(s) to be active, then internal
+# names of those effects can be given here
+X-KDE-PluginInfo-Depends=
+# Whether this effect should be enabled by default
+X-KDE-PluginInfo-EnabledByDefault=false
+# The plugin (library) which contains the effect. One library may contain more \
effects. +X-KDE-Library=kwin4_effect_builtins
+# The order in which this effect is loaded. Lower numbers are loaded first.
+X-Ordering=90
Index: snow.h
===================================================================
--- snow.h (Revision 0)
+++ snow.h (Revision 0)
@@ -0,0 +1,62 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+ Copyright (C) 2007 Martin Gräßlin <ubuntu@martin-graesslin.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+
+
+#ifndef KWIN_SNOW_H
+#define KWIN_SNOW_H
+
+#include <kwineffects.h>
+#include <kwinglutils.h>
+#include <qobject.h>
+
+#include <QList>
+#include <QTime>
+
+namespace KWin
+{
+
+class SnowEffect
+ : public QObject, public Effect
+ {
+ Q_OBJECT
+ public:
+ SnowEffect();
+ virtual ~SnowEffect();
+ virtual void prePaintScreen( ScreenPrePaintData& data, int time );
+ virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
+ virtual void postPaintScreen();
+
+ private slots:
+ void toggle();
+ private:
+ void loadTexture();
+ GLTexture* texture;
+ QList<QRect>* flakes;
+ QTime lastFlakeTime;
+ long nextFlakeMillis;
+ int mNumberFlakes;
+ int mMinFlakeSize;
+ int mMaxFlakeSize;
+ bool active;
+ };
+
+} // namespace
+
+#endif
Index: snow_config.ui
===================================================================
--- snow_config.ui (Revision 0)
+++ snow_config.ui (Revision 0)
@@ -0,0 +1,103 @@
+<ui version="4.0" >
+ <class>KWin::SnowEffectConfigForm</class>
+ <widget class="QWidget" name="KWin::SnowEffectConfigForm" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="title" >
+ <string>Appearance</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>&Number of snowflakes</string>
+ </property>
+ <property name="buddy" >
+ <cstring>numberFlakes</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QSpinBox" name="numberFlakes" >
+ <property name="maximum" >
+ <number>1000</number>
+ </property>
+ <property name="value" >
+ <number>50</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>M&inimum size of snowflake</string>
+ </property>
+ <property name="buddy" >
+ <cstring>minSizeFlake</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QSpinBox" name="minSizeFlake" >
+ <property name="suffix" >
+ <string> px</string>
+ </property>
+ <property name="maximum" >
+ <number>30</number>
+ </property>
+ <property name="value" >
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_3" >
+ <property name="text" >
+ <string>M&aximum size of snowflake</string>
+ </property>
+ <property name="buddy" >
+ <cstring>maxSizeFlake</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QSpinBox" name="maxSizeFlake" >
+ <property name="suffix" >
+ <string> px</string>
+ </property>
+ <property name="maximum" >
+ <number>1000</number>
+ </property>
+ <property name="value" >
+ <number>50</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="KWin::GlobalShortcutsEditor" native="1" name="editor" />
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>KWin::GlobalShortcutsEditor</class>
+ <extends>QWidget</extends>
+ <header location="global" >kwineffects.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
Index: snow_config.desktop
===================================================================
--- snow_config.desktop (Revision 0)
+++ snow_config.desktop (Revision 0)
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Type=Service
+X-KDE-ServiceTypes=KCModule
+
+X-KDE-Library=kcm_kwin4_effect_builtins
+X-KDE-ParentComponents=kwin4_effect_snow
+X-KDE-PluginKeyword=snow
+
+Name=Snow
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt (Revision 753725)
+++ CMakeLists.txt (Arbeitskopie)
@@ -102,6 +102,7 @@
mousemark.cpp
shadow.cpp
sharpen.cpp
+ snow.cpp
trackmouse.cpp
)
install( FILES
@@ -113,6 +114,7 @@
mousemark.desktop
shadow.desktop
sharpen.desktop
+ snow.desktop
trackmouse.desktop
DESTINATION ${SERVICES_INSTALL_DIR}/kwin )
install( FILES
@@ -132,6 +134,7 @@
data/lookingglass.frag
data/lookingglass.vert
data/shadow-texture.png
+ data/snowflake.png
data/circle.png
data/circle-edgy.png
DESTINATION ${DATA_INSTALL_DIR}/kwin )
@@ -144,6 +147,8 @@
mousemark_config.cpp
mousemark_config.ui
sharpen_config.cpp
+ snow_config.cpp
+ snow_config.ui
trackmouse_config.cpp
)
install( FILES
@@ -152,6 +157,7 @@
magnifier_config.desktop
mousemark_config.desktop
sharpen_config.desktop
+ snow_config.desktop
trackmouse_config.desktop
DESTINATION ${SERVICES_INSTALL_DIR}/kwin )
endif(OPENGL_FOUND)
Index: configs_builtins.cpp
===================================================================
--- configs_builtins.cpp (Revision 753725)
+++ configs_builtins.cpp (Arbeitskopie)
@@ -35,6 +35,7 @@
#include "mousemark_config.h"
#include "magnifier_config.h"
#include "sharpen_config.h"
+#include "snow_config.h"
#include "trackmouse_config.h"
#endif
@@ -60,6 +61,7 @@
registerPlugin<KWin::MouseMarkEffectConfig>("mousemark"); \
registerPlugin<KWin::MagnifierEffectConfig>("magnifier"); \
registerPlugin<KWin::SharpenEffectConfig>("sharpen"); \
+ registerPlugin<KWin::SnowEffectConfig>("snow"); \
registerPlugin<KWin::TrackMouseEffectConfig>("trackmouse"); \
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
["signature.asc" (application/pgp-signature)]
_______________________________________________
Kwin mailing list
Kwin@kde.org
https://mail.kde.org/mailman/listinfo/kwin
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic