[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>&amp;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&amp;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&amp;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