[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kwin
Subject:    WobblyEffect update
From:       cedric <cedric.borgese () gmail ! com>
Date:       2008-03-15 18:44:25
Message-ID: 200803152147.43871.cedric.borgese () gmail ! com
[Download RAW message or body]

I attach a new patch for the wobbly effect, the changelog is :

- source moved to effet/ directory and files are renamed ("demo_" prefix was 
removed from the file names)

- no more the annoying bug when the effect finishes

- no more bugs when resizing the window (yes, it was buggy)

what is missing to get a functionnal first version of the effect :

- someting the effect doesn't finish and stale in a bad state (the window is 
deformed)
- do a "real" config dialog with config options that mean something for the 
user (sliders that control the "wobblyness" or "inetia" of the moved window)

what will be nice to have but not mandatory :

- maximise effect, I take a look in the Effect class, it has a (un)minimise 
virtual function but not a (un)maximise one.

- interaction with edge attraction.

- slip out the bezier part of the code in another file to use it with other 
effects.

I can add it to svn now if you think it is usefull enough, but I don't feel it 
should be enabled by default at least until I fixed the 2 main points.

["wobbly.diff" (text/x-diff)]

Index: effects/wobblywindows.h
===================================================================
--- effects/wobblywindows.h	(révision 0)
+++ effects/wobblywindows.h	(révision 0)
@@ -0,0 +1,128 @@
+/*****************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2008 Cédric Borgese <cedric.borgese@gmail.com>
+
+You can Freely distribute this program under the GNU General Public
+License. See the file "COPYING" for the exact licensing terms.
+******************************************************************/
+
+#ifndef WOBBLYWINDOWS_H
+#define WOBBLYWINDOWS_H
+
+// Include with base class for effects.
+#include <kwineffects.h>
+
+namespace KWin
+{
+
+/**
+ * Effect which wobble windows
+ **/
+class WobblyWindowsEffect : public Effect
+{
+    public:
+
+        enum GridFilter
+        {
+            NoFilter,
+            FourRingLinearMean,
+            MeanWithMean,
+            MeanWithMedian
+        };
+
+
+        WobblyWindowsEffect();
+        virtual ~WobblyWindowsEffect();
+
+        virtual void prePaintScreen( ScreenPrePaintData& data, int time );
+        virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int \
time ); +        virtual void paintWindow( EffectWindow* w, int mask, QRegion region, \
WindowPaintData& data ); +        virtual void postPaintScreen();
+        virtual void windowUserMovedResized( EffectWindow* c, bool first, bool last \
); +        virtual void windowClosed( EffectWindow* c );
+
+        // Wobbly model parameters
+        void setRaideur(qreal raideur);
+        void setAmortissement(qreal amortissement);
+        void setVelocityThreshold(qreal velocityThreshold);
+        void setMoveFactor(qreal factor);
+
+        void setVelocityFilter(GridFilter filter);
+        void setAccelerationFilter(GridFilter filter);
+        GridFilter velocityFilter() const;
+        GridFilter accelerationFilter() const;
+
+        struct Pair
+        {
+            qreal x;
+            qreal y;
+        };
+
+    private:
+
+        bool updateWindowWobblyDatas(EffectWindow* w, qreal time);
+
+        struct WindowWobblyInfos
+        {
+            Pair* origin;
+            Pair* position;
+            Pair* velocity;
+            Pair* acceleration;
+            Pair* buffer;
+
+            // if true, the point is constraint to its "normal" destination
+            // given by the window position.
+            // if false, the point is free (i.e. use the physics system to move it)
+            bool* constraint;
+
+            unsigned int width;
+            unsigned int height;
+            unsigned int count;
+
+            Pair* bezierSurface;
+            unsigned int bezierWidth;
+            unsigned int bezierHeight;
+            unsigned int bezierCount;
+
+            bool onConstrain;
+        };
+
+        QHash< const EffectWindow*,  WindowWobblyInfos > windows;
+
+        QRect m_updateRegion;
+
+        qreal m_raideur;
+        qreal m_amortissement;
+        qreal m_move_factor;
+
+        // the default tesselation for windows
+        // use qreal instead of int as I really often need
+        // these values as real to do divisions.
+        qreal m_xTesselation;
+        qreal m_yTesselation;
+
+        GridFilter m_velocityFilter;
+        GridFilter m_accelerationFilter;
+
+        qreal m_minVelocity;
+        qreal m_maxVelocity;
+        qreal m_stopVelocity;
+        qreal m_minAcceleration;
+        qreal m_maxAcceleration;
+        qreal m_stopAcceleration;
+
+        void initWobblyInfo(WindowWobblyInfos& wwi, QRect geometry) const;
+        void freeWobblyInfo(WindowWobblyInfos& wwi) const;
+
+        WobblyWindowsEffect::Pair computeBezierPoint(const WindowWobblyInfos& wwi, \
Pair point) const; +
+        static void fourRingLinearMean(Pair** datas, WindowWobblyInfos& wwi);
+        static void meanWithMean(Pair** datas, WindowWobblyInfos& wwi);
+        static void meanWithMedian(Pair** datas, WindowWobblyInfos& wwi);
+};
+
+} // namespace KWin
+
+#endif // WOBBLYWINDOWS_H
Index: effects/wobblywindows_config.ui
===================================================================
--- effects/wobblywindows_config.ui	(révision 0)
+++ effects/wobblywindows_config.ui	(révision 0)
@@ -0,0 +1,642 @@
+<ui version="4.0" >
+ <class>KWin::WobblyWindowsEffectConfigForm</class>
+ <widget class="QWidget" name="KWin::WobblyWindowsEffectConfigForm" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>553</width>
+    <height>383</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>WobblyWindows</string>
+  </property>
+  <layout class="QGridLayout" >
+   <item row="0" column="0" >
+    <widget class="QTabWidget" name="tabWidget" >
+     <property name="currentIndex" >
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="tab" >
+      <attribute name="title" >
+       <string>Grid Parameters</string>
+      </attribute>
+      <layout class="QGridLayout" >
+       <item row="0" column="0" >
+        <widget class="QGroupBox" name="groupBox" >
+         <property name="sizePolicy" >
+          <sizepolicy vsizetype="Maximum" hsizetype="Preferred" >
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="title" >
+          <string>Grid Minimal Tesselation</string>
+         </property>
+         <layout class="QGridLayout" >
+          <item row="0" column="0" >
+           <widget class="QLabel" name="label" >
+            <property name="text" >
+             <string>Horizontal Nodes :</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1" >
+           <widget class="QSpinBox" name="spHNodes" >
+            <property name="minimum" >
+             <number>2</number>
+            </property>
+            <property name="value" >
+             <number>20</number>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0" >
+           <widget class="QLabel" name="label_2" >
+            <property name="text" >
+             <string>Vertical Nodes :</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1" >
+           <widget class="QSpinBox" name="spVNodes" >
+            <property name="minimum" >
+             <number>2</number>
+            </property>
+            <property name="value" >
+             <number>20</number>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item rowspan="2" row="0" column="1" >
+        <widget class="QGroupBox" name="groupBox_4" >
+         <property name="sizePolicy" >
+          <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="title" >
+          <string>Grid Parameters</string>
+         </property>
+         <layout class="QGridLayout" >
+          <item row="0" column="0" >
+           <widget class="QLabel" name="label_3" >
+            <property name="text" >
+             <string>Raideur :</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1" >
+           <spacer>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" >
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item row="0" column="2" >
+           <widget class="QDoubleSpinBox" name="spRaideur" >
+            <property name="maximum" >
+             <double>2.000000000000000</double>
+            </property>
+            <property name="singleStep" >
+             <double>0.020000000000000</double>
+            </property>
+            <property name="value" >
+             <double>0.500000000000000</double>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0" colspan="3" >
+           <widget class="QSlider" name="slRaideur" >
+            <property name="maximum" >
+             <number>100</number>
+            </property>
+            <property name="value" >
+             <number>25</number>
+            </property>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0" colspan="3" >
+           <widget class="Line" name="line" >
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="0" >
+           <widget class="QLabel" name="label_4" >
+            <property name="text" >
+             <string>Amortissement :</string>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="1" >
+           <spacer>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" >
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item row="3" column="2" >
+           <widget class="QDoubleSpinBox" name="spAmortissement" >
+            <property name="maximum" >
+             <double>1.000000000000000</double>
+            </property>
+            <property name="singleStep" >
+             <double>0.010000000000000</double>
+            </property>
+            <property name="value" >
+             <double>0.940000000000000</double>
+            </property>
+           </widget>
+          </item>
+          <item row="4" column="0" colspan="3" >
+           <widget class="QSlider" name="slAmortissement" >
+            <property name="maximum" >
+             <number>100</number>
+            </property>
+            <property name="value" >
+             <number>94</number>
+            </property>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="0" colspan="3" >
+           <widget class="Line" name="line_4" >
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+          <item row="6" column="0" >
+           <widget class="QLabel" name="label_6" >
+            <property name="text" >
+             <string>Move Factor :</string>
+            </property>
+           </widget>
+          </item>
+          <item row="6" column="1" >
+           <spacer>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" >
+             <size>
+              <width>16</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item row="6" column="2" >
+           <widget class="QDoubleSpinBox" name="spMovFactor" >
+            <property name="maximum" >
+             <double>1.000000000000000</double>
+            </property>
+            <property name="singleStep" >
+             <double>0.010000000000000</double>
+            </property>
+            <property name="value" >
+             <double>0.010000000000000</double>
+            </property>
+           </widget>
+          </item>
+          <item row="7" column="0" colspan="3" >
+           <widget class="QSlider" name="slMovFactor" >
+            <property name="maximum" >
+             <number>100</number>
+            </property>
+            <property name="value" >
+             <number>1</number>
+            </property>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="1" column="0" >
+        <widget class="QGroupBox" name="groupBox_5" >
+         <property name="sizePolicy" >
+          <sizepolicy vsizetype="Maximum" hsizetype="Preferred" >
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="title" >
+          <string>Grid Filter</string>
+         </property>
+         <layout class="QVBoxLayout" >
+          <item>
+           <widget class="QComboBox" name="cbGridFilter" >
+            <item>
+             <property name="text" >
+              <string>Velocity</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>Acceleration</string>
+             </property>
+            </item>
+           </widget>
+          </item>
+          <item>
+           <widget class="QRadioButton" name="rbNone" >
+            <property name="text" >
+             <string>None</string>
+            </property>
+            <property name="checked" >
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QRadioButton" name="rbRingMean" >
+            <property name="text" >
+             <string>Ring Mean</string>
+            </property>
+            <property name="checked" >
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QRadioButton" name="rbMeanMean" >
+            <property name="text" >
+             <string>Mean With Mean</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QRadioButton" name="rbMeanMedian" >
+            <property name="text" >
+             <string>Mean With Median</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="tab_2" >
+      <attribute name="title" >
+       <string>Thresholds</string>
+      </attribute>
+      <layout class="QGridLayout" >
+       <item row="0" column="0" >
+        <widget class="QGroupBox" name="groupBox_2" >
+         <property name="title" >
+          <string>Velocity</string>
+         </property>
+         <layout class="QGridLayout" >
+          <item row="0" column="0" >
+           <widget class="QLabel" name="label_5" >
+            <property name="text" >
+             <string>Min Velocity</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1" >
+           <spacer>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" >
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item row="0" column="2" colspan="2" >
+           <widget class="QDoubleSpinBox" name="spMinVel" >
+            <property name="maximum" >
+             <double>1.000000000000000</double>
+            </property>
+            <property name="singleStep" >
+             <double>0.010000000000000</double>
+            </property>
+            <property name="value" >
+             <double>0.500000000000000</double>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0" colspan="4" >
+           <widget class="QSlider" name="slMinVel" >
+            <property name="maximum" >
+             <number>100</number>
+            </property>
+            <property name="value" >
+             <number>50</number>
+            </property>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0" colspan="4" >
+           <widget class="Line" name="line_2" >
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="0" >
+           <widget class="QLabel" name="label_7" >
+            <property name="text" >
+             <string>Max Velocity</string>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="1" colspan="2" >
+           <spacer>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" >
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item row="3" column="3" >
+           <widget class="QDoubleSpinBox" name="spMaxVel" >
+            <property name="maximum" >
+             <double>1000.000000000000000</double>
+            </property>
+            <property name="singleStep" >
+             <double>10.000000000000000</double>
+            </property>
+            <property name="value" >
+             <double>500.000000000000000</double>
+            </property>
+           </widget>
+          </item>
+          <item row="4" column="0" colspan="4" >
+           <widget class="QSlider" name="slMaxVel" >
+            <property name="maximum" >
+             <number>100</number>
+            </property>
+            <property name="value" >
+             <number>50</number>
+            </property>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="0" colspan="4" >
+           <widget class="Line" name="line_3" >
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+          <item row="6" column="0" >
+           <widget class="QLabel" name="label_10" >
+            <property name="text" >
+             <string>Velocity Stop</string>
+            </property>
+           </widget>
+          </item>
+          <item row="6" column="1" colspan="2" >
+           <spacer>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" >
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item row="6" column="3" >
+           <widget class="QDoubleSpinBox" name="spStopVel" >
+            <property name="maximum" >
+             <double>10.000000000000000</double>
+            </property>
+            <property name="singleStep" >
+             <double>0.100000000000000</double>
+            </property>
+            <property name="value" >
+             <double>3.000000000000000</double>
+            </property>
+           </widget>
+          </item>
+          <item row="7" column="0" colspan="4" >
+           <widget class="QSlider" name="slStopVel" >
+            <property name="maximum" >
+             <number>100</number>
+            </property>
+            <property name="value" >
+             <number>30</number>
+            </property>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="0" column="1" >
+        <widget class="QGroupBox" name="groupBox_3" >
+         <property name="title" >
+          <string>Acceleration</string>
+         </property>
+         <layout class="QGridLayout" >
+          <item row="0" column="0" >
+           <widget class="QLabel" name="label_8" >
+            <property name="text" >
+             <string>Min Acceleration</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1" colspan="2" >
+           <spacer>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" >
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item row="0" column="3" >
+           <widget class="QDoubleSpinBox" name="spMinAcc" >
+            <property name="maximum" >
+             <double>1.000000000000000</double>
+            </property>
+            <property name="singleStep" >
+             <double>0.010000000000000</double>
+            </property>
+            <property name="value" >
+             <double>0.100000000000000</double>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0" colspan="4" >
+           <widget class="QSlider" name="slMinAcc" >
+            <property name="maximum" >
+             <number>100</number>
+            </property>
+            <property name="value" >
+             <number>10</number>
+            </property>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0" colspan="4" >
+           <widget class="Line" name="line_5" >
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="0" colspan="2" >
+           <widget class="QLabel" name="label_9" >
+            <property name="text" >
+             <string>Max Acceleration</string>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="2" >
+           <spacer>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" >
+             <size>
+              <width>21</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item row="3" column="3" >
+           <widget class="QDoubleSpinBox" name="spMaxAcc" >
+            <property name="maximum" >
+             <double>1000.000000000000000</double>
+            </property>
+            <property name="singleStep" >
+             <double>10.000000000000000</double>
+            </property>
+            <property name="value" >
+             <double>500.000000000000000</double>
+            </property>
+           </widget>
+          </item>
+          <item row="4" column="0" colspan="4" >
+           <widget class="QSlider" name="slMaxAcc" >
+            <property name="maximum" >
+             <number>100</number>
+            </property>
+            <property name="value" >
+             <number>50</number>
+            </property>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="0" colspan="4" >
+           <widget class="Line" name="line_6" >
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+          <item row="6" column="0" colspan="2" >
+           <widget class="QLabel" name="label_11" >
+            <property name="text" >
+             <string>Acceleration Stop</string>
+            </property>
+           </widget>
+          </item>
+          <item row="6" column="2" >
+           <spacer>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" >
+             <size>
+              <width>21</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item row="6" column="3" >
+           <widget class="QDoubleSpinBox" name="spStopAcc" >
+            <property name="maximum" >
+             <double>10.000000000000000</double>
+            </property>
+            <property name="singleStep" >
+             <double>0.100000000000000</double>
+            </property>
+            <property name="value" >
+             <double>8.000000000000000</double>
+            </property>
+           </widget>
+          </item>
+          <item row="7" column="0" colspan="4" >
+           <widget class="QSlider" name="slStopAcc" >
+            <property name="maximum" >
+             <number>100</number>
+            </property>
+            <property name="value" >
+             <number>80</number>
+            </property>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
Index: effects/wobblywindows_config.cpp
===================================================================
--- effects/wobblywindows_config.cpp	(révision 0)
+++ effects/wobblywindows_config.cpp	(révision 0)
@@ -0,0 +1,503 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+ Copyright (C) 2008 Cédric Borgese <cedric.borgese@gmail.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 "wobblywindows_config.h"
+#include "wobblywindows_constants.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
+{
+
+WobblyWindowsEffectConfig::WobblyWindowsEffectConfig(QWidget* parent, const \
QVariantList& args) : +KCModule(EffectFactory::componentData(), parent, args)
+{
+    m_ui.setupUi(this);
+
+    connect(m_ui.spRaideur, SIGNAL(valueChanged(double)), this, \
SLOT(slotSpRaideur(double))); +    connect(m_ui.slRaideur, SIGNAL(sliderMoved(int)), \
this, SLOT(slotSlRaideur(int))); +    connect(m_ui.spAmortissement, \
SIGNAL(valueChanged(double)), this, SLOT(slotSpAmortissement(double))); +    \
connect(m_ui.slAmortissement, SIGNAL(sliderMoved(int)), this, \
SLOT(slotSlAmortissement(int))); +    connect(m_ui.spMovFactor, \
SIGNAL(valueChanged(double)), this, SLOT(slotSpMovFactor(double))); +    \
connect(m_ui.slMovFactor, SIGNAL(sliderMoved(int)), this, \
SLOT(slotSlMovFactor(int))); +
+    connect(m_ui.cbGridFilter, SIGNAL(activated(int)), this, \
SLOT(slotGridParameterSelected(int))); +
+    connect(m_ui.rbNone, SIGNAL(toggled(bool)), this, SLOT(slotRbNone(bool)));
+    connect(m_ui.rbRingMean, SIGNAL(toggled(bool)), this, \
SLOT(slotRbRingMean(bool))); +    connect(m_ui.rbMeanMean, SIGNAL(toggled(bool)), \
this, SLOT(slotRbMeanMean(bool))); +    connect(m_ui.rbMeanMedian, \
SIGNAL(toggled(bool)), this, SLOT(slotRbMeanMedian(bool))); +
+    connect(m_ui.spMinVel, SIGNAL(valueChanged(double)), this, \
SLOT(slotSpMinVel(double))); +    connect(m_ui.slMinVel, SIGNAL(sliderMoved(int)), \
this, SLOT(slotSlMinVel(int))); +    connect(m_ui.spMaxVel, \
SIGNAL(valueChanged(double)), this, SLOT(slotSpMaxVel(double))); +    \
connect(m_ui.slMaxVel, SIGNAL(sliderMoved(int)), this, SLOT(slotSlMaxVel(int))); +    \
connect(m_ui.spStopVel, SIGNAL(valueChanged(double)), this, \
SLOT(slotSpStopVel(double))); +    connect(m_ui.slStopVel, SIGNAL(sliderMoved(int)), \
this, SLOT(slotSlStopVel(int))); +    connect(m_ui.spMinAcc, \
SIGNAL(valueChanged(double)), this, SLOT(slotSpMinAcc(double))); +    \
connect(m_ui.slMinAcc, SIGNAL(sliderMoved(int)), this, SLOT(slotSlMinAcc(int))); +    \
connect(m_ui.spMaxAcc, SIGNAL(valueChanged(double)), this, \
SLOT(slotSpMaxAcc(double))); +    connect(m_ui.slMaxAcc, SIGNAL(sliderMoved(int)), \
this, SLOT(slotSlMaxAcc(int))); +    connect(m_ui.spStopAcc, \
SIGNAL(valueChanged(double)), this, SLOT(slotSpStopAcc(double))); +    \
connect(m_ui.slStopAcc, SIGNAL(sliderMoved(int)), this, SLOT(slotSlStopAcc(int))); +
+    load();
+}
+
+WobblyWindowsEffectConfig::~WobblyWindowsEffectConfig()
+{
+}
+
+void WobblyWindowsEffectConfig::load()
+{
+    KCModule::load();
+
+    KConfigGroup conf = EffectsHandler::effectConfig("Wobbly");
+    qreal raideur = conf.readEntry("Raideur", RAIDEUR);
+    qreal amortissement = conf.readEntry("Amortissement", AMORTISSEMENT);
+    qreal move_factor = conf.readEntry("MoveFactor", MOVEFACTOR);
+
+    m_ui.spRaideur->setValue(raideur);
+    m_ui.slRaideur->setSliderPosition(raideur*50);    
+
+    m_ui.spAmortissement->setValue(amortissement);
+    m_ui.slAmortissement->setSliderPosition(amortissement*100);
+
+    m_ui.spMovFactor->setValue(move_factor);
+    m_ui.slMovFactor->setValue(move_factor*100);
+
+    int xTesselation = conf.readEntry("XTesselation", XTESSELATION);
+    int yTesselation = conf.readEntry("YTesselation", YTESSELATION);
+
+    m_ui.spHNodes->setValue(xTesselation);
+    m_ui.spVNodes->setValue(yTesselation);
+
+    //squareRootMasterAcceleration = conf.readEntry("SquareRootMasterAcceleration", \
false); +
+    QString velFilter = conf.readEntry("VelocityFilter", VELOCITYFILTER);
+    if (velFilter == "NoFilter")
+    {
+        velocityFilter = NoFilter;
+    }
+    else if (velFilter == "FourRingLinearMean")
+    {
+        velocityFilter = FourRingLinearMean;
+    }
+    else if (velFilter == "MeanWithMean")
+    {
+        velocityFilter = MeanWithMean;
+    }
+    else if (velFilter == "MeanWithMedian")
+    {
+        velocityFilter = MeanWithMedian;
+    }
+    else
+    {
+        velocityFilter = FourRingLinearMean;
+        kDebug() << "Unknown config value for VelocityFilter : " << velFilter;
+    }
+
+
+    QString accFilter = conf.readEntry("AccelerationFilter", ACCELERATIONFILTER);
+    if (accFilter == "NoFilter")
+    {
+        accelerationFilter = NoFilter;
+    }
+    else if (accFilter == "FourRingLinearMean")
+    {
+        accelerationFilter = FourRingLinearMean;
+    }
+    else if (accFilter == "MeanWithMean")
+    {
+        accelerationFilter = MeanWithMean;
+    }
+    else if (accFilter == "MeanWithMedian")
+    {
+        accelerationFilter = MeanWithMedian;
+    }
+    else
+    {
+        accelerationFilter = NoFilter;
+        kDebug() << "Unknown config value for accelerationFilter : " << accFilter;
+    }
+
+    qreal minVel = conf.readEntry("MinVelocity", MINVELOCITY);
+    qreal maxVel = conf.readEntry("MaxVelocity", MAXVELOCITY);
+    qreal stopVel = conf.readEntry("StopVelocity", STOPVELOCITY);
+    qreal minAcc = conf.readEntry("MinAcceleration", MINACCELERATION);
+    qreal maxAcc = conf.readEntry("MaxAcceleration", MAXACCELERATION);
+    qreal stopAcc = conf.readEntry("StopAcceleration", STOPACCELERATION);
+
+    m_ui.spMinVel->setValue(minVel);
+    m_ui.slMinVel->setSliderPosition(minVel*100);
+    m_ui.spMaxVel->setValue(maxVel);
+    m_ui.slMaxVel->setSliderPosition(maxVel/10);
+    m_ui.spStopVel->setValue(stopVel);
+    m_ui.slStopVel->setSliderPosition(stopVel*10);
+    m_ui.spMinAcc->setValue(minAcc);
+    m_ui.slMinAcc->setSliderPosition(minAcc*100);
+    m_ui.spMaxAcc->setValue(maxAcc);
+    m_ui.slMaxAcc->setSliderPosition(maxAcc/10);
+    m_ui.spStopAcc->setValue(stopAcc);
+    m_ui.slStopAcc->setSliderPosition(stopAcc*10);
+
+    emit changed(false);
+}
+
+void WobblyWindowsEffectConfig::save()
+{
+    KConfigGroup conf = EffectsHandler::effectConfig("Wobbly");
+
+    conf.writeEntry("Raideur", m_ui.spRaideur->value());
+    conf.writeEntry("Amortissement", m_ui.spAmortissement->value());
+    conf.writeEntry("MoveFactor", m_ui.spMovFactor->value());
+
+    conf.writeEntry("XTesselation", m_ui.spHNodes->value());
+    conf.writeEntry("YTesselation", m_ui.spVNodes->value());
+
+    switch (velocityFilter)
+    {
+    case NoFilter:
+        conf.writeEntry("VelocityFilter", "NoFilter");
+        break;
+
+    case FourRingLinearMean:
+        conf.writeEntry("VelocityFilter", "FourRingLinearMean");
+        break;
+
+    case MeanWithMean:
+        conf.writeEntry("VelocityFilter", "MeanWithMean");
+        break;
+
+    case MeanWithMedian:
+        conf.writeEntry("VelocityFilter", "MeanWithMedian");
+        break;
+    }
+
+    switch (accelerationFilter)
+    {
+    case NoFilter:
+        conf.writeEntry("AccelerationFilter", "NoFilter");
+        break;
+
+    case FourRingLinearMean:
+        conf.writeEntry("AccelerationFilter", "FourRingLinearMean");
+        break;
+
+    case MeanWithMean:
+        conf.writeEntry("AccelerationFilter", "MeanWithMean");
+        break;
+
+    case MeanWithMedian:
+        conf.writeEntry("AccelerationFilter", "MeanWithMedian");
+        break;
+   }
+
+    conf.writeEntry("MinVelocity", m_ui.spMinVel->value());
+    conf.writeEntry("MaxVelocity", m_ui.spMaxVel->value());
+    conf.writeEntry("StopVelocity", m_ui.spStopVel->value());
+    conf.writeEntry("MinAcceleration", m_ui.spMinAcc->value());
+    conf.writeEntry("MaxAcceleration", m_ui.spMaxAcc->value());
+    conf.writeEntry("StopAcceleration", m_ui.spStopAcc->value());
+
+    conf.sync();
+
+    emit changed(false);
+    EffectsHandler::sendReloadMessage("wobblywindows");
+}
+
+void WobblyWindowsEffectConfig::defaults()
+{
+    m_ui.spRaideur->setValue(RAIDEUR);
+    m_ui.slRaideur->setSliderPosition(RAIDEUR*50);    
+
+    m_ui.spAmortissement->setValue(AMORTISSEMENT);
+    m_ui.slAmortissement->setSliderPosition(AMORTISSEMENT*100);
+
+    m_ui.spMovFactor->setValue(MOVEFACTOR);
+    m_ui.slMovFactor->setValue(MOVEFACTOR*100);
+
+    m_ui.spHNodes->setValue(XTESSELATION);
+    m_ui.spVNodes->setValue(YTESSELATION);
+
+    velocityFilter = FourRingLinearMean;
+    accelerationFilter = NoFilter;
+    slotGridParameterSelected(m_ui.cbGridFilter->currentIndex());
+
+    m_ui.spMinVel->setValue(MINVELOCITY);
+    m_ui.slMinVel->setSliderPosition(MINVELOCITY*100);
+
+    m_ui.spMaxVel->setValue(MAXVELOCITY);
+    m_ui.slMaxVel->setSliderPosition(MAXVELOCITY/10);
+
+    m_ui.spStopVel->setValue(STOPVELOCITY);
+    m_ui.slStopVel->setSliderPosition(STOPVELOCITY*10);
+
+    m_ui.spMinAcc->setValue(MINACCELERATION);
+    m_ui.slMinAcc->setSliderPosition(MINACCELERATION*100);
+
+    m_ui.spMaxAcc->setValue(MAXACCELERATION);
+    m_ui.slMaxAcc->setSliderPosition(MAXACCELERATION/10);
+
+    m_ui.spStopAcc->setValue(STOPACCELERATION);
+    m_ui.slStopAcc->setSliderPosition(STOPACCELERATION*10);
+
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSpRaideur(double value)
+{
+    m_ui.slRaideur->setSliderPosition(value*50);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSlRaideur(int value)
+{
+    m_ui.spRaideur->setValue(value/50.0);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSpAmortissement(double value)
+{
+    m_ui.slAmortissement->setSliderPosition(value*100);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSlAmortissement(int value)
+{
+    m_ui.spAmortissement->setValue(qreal(value)/100.0);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSpMovFactor(double value)
+{
+    m_ui.slMovFactor->setValue(value*100);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSlMovFactor(int value)
+{
+    m_ui.spMovFactor->setValue(qreal(value)/100.0);
+    emit changed(true);
+}
+
+// filters
+
+void WobblyWindowsEffectConfig::slotRbNone(bool toggled)
+{
+    if (toggled)
+    {
+        if (m_ui.cbGridFilter->currentIndex() == 0) // velocity
+        {
+            velocityFilter = NoFilter;
+        }
+        else if (m_ui.cbGridFilter->currentIndex() == 1) // acceleration
+        {
+            accelerationFilter = NoFilter;
+        }
+    }
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotRbRingMean(bool toggled)
+{
+    if (toggled)
+    {
+        if (m_ui.cbGridFilter->currentIndex() == 0) // velocity
+        {
+            velocityFilter = FourRingLinearMean;
+        }
+        else if (m_ui.cbGridFilter->currentIndex() == 1) // acceleration
+        {
+            accelerationFilter = FourRingLinearMean;
+        }
+    }
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotRbMeanMean(bool toggled)
+{
+    if (toggled)
+    {
+        if (m_ui.cbGridFilter->currentIndex() == 0) // velocity
+        {
+            velocityFilter = MeanWithMean;
+        }
+        else if (m_ui.cbGridFilter->currentIndex() == 1) // acceleration
+        {
+            accelerationFilter = MeanWithMean;
+        }
+    }
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotRbMeanMedian(bool toggled)
+{
+    if (toggled)
+    {
+        if (m_ui.cbGridFilter->currentIndex() == 0) // velocity
+        {
+            velocityFilter = MeanWithMedian;
+        }
+        else if (m_ui.cbGridFilter->currentIndex() == 1) // acceleration
+        {
+            accelerationFilter = MeanWithMedian;
+        }
+    }
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotGridParameterSelected(int index)
+{
+    if (index == 0) // velocity
+    {
+        switch (velocityFilter)
+        {
+        case NoFilter:
+            m_ui.rbNone->setChecked(true);
+            break;
+
+        case FourRingLinearMean:
+            m_ui.rbRingMean->setChecked(true);
+            break;
+
+        case MeanWithMean:
+            m_ui.rbMeanMean->setChecked(true);
+            break;
+
+        case MeanWithMedian:
+            m_ui.rbMeanMedian->setChecked(true);
+            break;
+        }
+    }
+    else if (index == 1) // acceleration
+    {
+        switch (accelerationFilter)
+        {
+        case NoFilter:
+            m_ui.rbNone->setChecked(true);
+            break;
+
+        case FourRingLinearMean:
+            m_ui.rbRingMean->setChecked(true);
+            break;
+
+        case MeanWithMean:
+            m_ui.rbMeanMean->setChecked(true);
+            break;
+
+        case MeanWithMedian:
+            m_ui.rbMeanMedian->setChecked(true);
+            break;
+       }
+    }
+    emit changed(true);
+}
+
+// thresholds
+
+void WobblyWindowsEffectConfig::slotSpMinVel(double value)
+{
+    m_ui.slMinVel->setSliderPosition(value*100);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSlMinVel(int value)
+{
+    m_ui.spMinVel->setValue(qreal(value)/100.0);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSpMaxVel(double value)
+{
+    m_ui.slMaxVel->setSliderPosition(value/10);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSlMaxVel(int value)
+{
+    m_ui.spMaxVel->setValue(value*10.0);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSpStopVel(double value)
+{
+    m_ui.slStopVel->setSliderPosition(value*10);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSlStopVel(int value)
+{
+    m_ui.spStopVel->setValue(value/10.0);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSpMinAcc(double value)
+{
+    m_ui.slMinAcc->setSliderPosition(value*100);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSlMinAcc(int value)
+{
+    m_ui.spMinAcc->setValue(value/100.0);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSpMaxAcc(double value)
+{
+    m_ui.slMaxAcc->setSliderPosition(value/10);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSlMaxAcc(int value)
+{
+    m_ui.spMaxAcc->setValue(value*10.0);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSpStopAcc(double value)
+{
+    m_ui.slStopAcc->setSliderPosition(value*10);
+    emit changed(true);
+}
+
+void WobblyWindowsEffectConfig::slotSlStopAcc(int value)
+{
+    m_ui.spStopAcc->setValue(value/10.0);
+    emit changed(true);
+}
+
+
+} // namespace
+
+#include "wobblywindows_config.moc"
Index: effects/wobblywindows.desktop
===================================================================
--- effects/wobblywindows.desktop	(révision 0)
+++ effects/wobblywindows.desktop	(révision 0)
@@ -0,0 +1,17 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Wobbly Windows
+Icon=kwin-effect-wavywindows
+
+Type=Service
+ServiceTypes=KWin/Effect
+X-KDE-PluginInfo-Author=Cédric Borgese
+X-KDE-PluginInfo-Email=cedric.borgese@gmail.com
+X-KDE-PluginInfo-Name=kwin4_effect_wobblywindows
+X-KDE-PluginInfo-Version=0.0.1
+X-KDE-PluginInfo-Category=Appearance
+X-KDE-PluginInfo-Depends=
+X-KDE-PluginInfo-License=GPL
+X-KDE-PluginInfo-EnabledByDefault=false
+X-KDE-Library=kwin4_effect_builtins
+X-KDE-Ordering=80
\ No newline at end of file
Index: effects/wobblywindows_config.desktop
===================================================================
--- effects/wobblywindows_config.desktop	(révision 0)
+++ effects/wobblywindows_config.desktop	(révision 0)
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Type=Service
+X-KDE-ServiceTypes=KCModule
+
+X-KDE-Library=kcm_kwin4_effect_tests
+X-KDE-ParentComponents=kwin4_effect_wobblywindows
+X-KDE-PluginKeyword=wobblywindows
+
+Name=Wobbly Windows
+
Index: effects/wobblywindows_config.h
===================================================================
--- effects/wobblywindows_config.h	(révision 0)
+++ effects/wobblywindows_config.h	(révision 0)
@@ -0,0 +1,93 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+ Copyright (C) 2008 Cédric Borgese <cedric.borgese@gmail.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_WOBBLY_CONFIG_H
+#define KWIN_WOBBLY_CONFIG_H
+
+#define KDE3_SUPPORT
+#include <kcmodule.h>
+#undef KDE3_SUPPORT
+
+#include "ui_wobblywindows_config.h"
+
+class KActionCollection;
+
+namespace KWin
+{
+
+class WobblyWindowsEffectConfig : public KCModule
+{
+    Q_OBJECT
+public:
+    explicit WobblyWindowsEffectConfig(QWidget* parent = 0, const QVariantList& args \
= QVariantList()); +    ~WobblyWindowsEffectConfig();
+
+public slots:
+    virtual void save();
+    virtual void load();
+    virtual void defaults();
+
+private:
+    enum GridFilter
+    {
+        NoFilter,
+        FourRingLinearMean,
+        MeanWithMean,
+        MeanWithMedian
+    };
+
+private slots:
+
+    void slotSpRaideur(double);
+    void slotSlRaideur(int);
+    void slotSpAmortissement(double);
+    void slotSlAmortissement(int);
+    void slotSpMovFactor(double);
+    void slotSlMovFactor(int);
+
+    void slotGridParameterSelected(int);
+    void slotRbNone(bool);
+    void slotRbRingMean(bool);
+    void slotRbMeanMean(bool);
+    void slotRbMeanMedian(bool);
+
+    void slotSpMinVel(double);
+    void slotSlMinVel(int);
+    void slotSpMaxVel(double);
+    void slotSlMaxVel(int);
+    void slotSpStopVel(double);
+    void slotSlStopVel(int);
+    void slotSpMinAcc(double);
+    void slotSlMinAcc(int);
+    void slotSpMaxAcc(double);
+    void slotSlMaxAcc(int);
+    void slotSpStopAcc(double);
+    void slotSlStopAcc(int);
+
+private:
+    Ui::WobblyWindowsEffectConfigForm m_ui;
+
+    GridFilter velocityFilter;
+    GridFilter accelerationFilter;
+};
+
+} // namespace
+
+#endif
Index: effects/wobblywindows_constants.h
===================================================================
--- effects/wobblywindows_constants.h	(révision 0)
+++ effects/wobblywindows_constants.h	(révision 0)
@@ -0,0 +1,38 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+ Copyright (C) 2008 Cédric Borgese <cedric.borgese@gmail.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 <QtGlobal>
+
+static const qreal RAIDEUR = 0.5;
+static const qreal AMORTISSEMENT = 0.93;
+static const qreal MOVEFACTOR = 0.01;
+
+static const int XTESSELATION = 20;
+static const int YTESSELATION = 20;
+
+static const qreal MINVELOCITY = 0.8;
+static const qreal MAXVELOCITY = 1000.0;
+static const qreal STOPVELOCITY = 8.0;
+static const qreal MINACCELERATION = 0.2;
+static const qreal MAXACCELERATION = 1000.0;
+static const qreal STOPACCELERATION = 15.0;
+
+static const char* VELOCITYFILTER = "FourRingLinearMean";
+static const char* ACCELERATIONFILTER = "NoFilter";
Index: effects/wobblywindows.cpp
===================================================================
--- effects/wobblywindows.cpp	(révision 0)
+++ effects/wobblywindows.cpp	(révision 0)
@@ -0,0 +1,1130 @@
+/*****************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2008 Cédric Borgese <cedric.borgese@gmail.com>
+
+You can Freely distribute this program under the GNU General Public
+License. See the file "COPYING" for the exact licensing terms.
+******************************************************************/
+
+
+#include "wobblywindows.h"
+#include "wobblywindows_constants.h"
+
+#include <kdebug.h>
+#include <kconfiggroup.h>
+#include <math.h>
+
+#define USE_ASSERT
+#ifdef USE_ASSERT
+#define ASSERT1 assert
+#else
+#define ASSERT1
+#endif
+
+//#define COMPUTE_STATS
+
+// if you enable it and run kwin in a terminal from the session it manages,
+// be sure to redirect the output of kwin in a file or
+// you'll propably get deadlocks.
+//#define VERBOSE_MODE
+
+#if defined COMPUTE_STATS and not defined VERBOSE_MODE
+#   warning "You enable COMPUTE_STATS without VERBOSE_MODE, computed stats will not \
be printed." +#endif
+
+namespace KWin
+{
+
+KWIN_EFFECT(wobblywindows, WobblyWindowsEffect)
+
+WobblyWindowsEffect::WobblyWindowsEffect()
+{
+    KConfigGroup conf = effects->effectConfig("Wobbly");
+
+    m_raideur = conf.readEntry("Raideur", RAIDEUR);
+    m_amortissement = conf.readEntry("Amortissement", AMORTISSEMENT);
+    m_move_factor = conf.readEntry("MoveFactor", MOVEFACTOR);
+
+    m_xTesselation = conf.readEntry("XTesselation", XTESSELATION);
+    m_yTesselation = conf.readEntry("YTesselation", YTESSELATION);
+
+    m_minVelocity = conf.readEntry("MinVelocity", MINVELOCITY);
+    m_maxVelocity = conf.readEntry("MaxVelocity", MAXVELOCITY);
+    m_stopVelocity = conf.readEntry("StopVelocity", STOPVELOCITY);
+    m_minAcceleration = conf.readEntry("MinAcceleration", MINACCELERATION);
+    m_maxAcceleration = conf.readEntry("MaxAcceleration", MAXACCELERATION);
+    m_stopAcceleration = conf.readEntry("StopAcceleration", STOPACCELERATION);
+
+    QString velFilter = conf.readEntry("VelocityFilter", VELOCITYFILTER);
+    if (velFilter == "NoFilter")
+    {
+        m_velocityFilter = NoFilter;
+    }
+    else if (velFilter == "FourRingLinearMean")
+    {
+        m_velocityFilter = FourRingLinearMean;
+    }
+    else if (velFilter == "MeanWithMean")
+    {
+        m_velocityFilter = MeanWithMean;
+    }
+    else if (velFilter == "MeanWithMedian")
+    {
+        m_velocityFilter = MeanWithMedian;
+    }
+    else
+    {
+        m_velocityFilter = FourRingLinearMean;
+        kDebug() << "Unknown config value for VelocityFilter : " << velFilter;
+    }
+
+
+    QString accFilter = conf.readEntry("AccelerationFilter", ACCELERATIONFILTER);
+    if (accFilter == "NoFilter")
+    {
+        m_accelerationFilter = NoFilter;
+    }
+    else if (accFilter == "FourRingLinearMean")
+    {
+        m_accelerationFilter = FourRingLinearMean;
+    }
+    else if (accFilter == "MeanWithMean")
+    {
+        m_accelerationFilter = MeanWithMean;
+    }
+    else if (accFilter == "MeanWithMedian")
+    {
+        m_accelerationFilter = MeanWithMedian;
+    }
+    else
+    {
+        m_accelerationFilter = NoFilter;
+        kDebug() << "Unknown config value for accelerationFilter : " << accFilter;
+    }
+
+#if defined VERBOSE_MODE
+    kDebug() << "Parameters :\n" <<
+        "grid(" << m_raideur << ", " << m_amortissement << ", " << m_move_factor << \
")\n" << +        "velocity(" << m_minVelocity << ", " << m_maxVelocity << ", " << \
m_stopVelocity << ")\n" << +        "acceleration(" << m_minAcceleration << ", " << \
m_maxAcceleration << ", " << m_stopAcceleration << ")\n" << +        "tesselation(" \
<< m_xTesselation <<  ", " << m_yTesselation << ")"; +#endif
+}
+
+WobblyWindowsEffect::~WobblyWindowsEffect()
+{
+    if (windows.empty())
+    {
+        // we should be empty at this point...
+        // emit a warning and clean the list.
+        kDebug() << "Windows list not empty. Left items : " << windows.count();
+        QHash< const EffectWindow*,  WindowWobblyInfos >::iterator i;
+        for (i = windows.begin(); i != windows.end(); ++i)
+        {
+            freeWobblyInfo(i.value());
+        }
+    }
+}
+void WobblyWindowsEffect::setVelocityThreshold(qreal m_minVelocity)
+{
+    this->m_minVelocity = m_minVelocity;
+}
+
+void WobblyWindowsEffect::setMoveFactor(qreal factor)
+{
+    m_move_factor = factor;
+}
+
+void WobblyWindowsEffect::setRaideur(qreal m_raideur)
+{
+    this->m_raideur = m_raideur;
+}
+
+void WobblyWindowsEffect::setVelocityFilter(GridFilter filter)
+{
+    m_velocityFilter = filter;
+}
+
+void WobblyWindowsEffect::setAccelerationFilter(GridFilter filter)
+{
+    m_accelerationFilter = filter;
+}
+
+WobblyWindowsEffect::GridFilter WobblyWindowsEffect::velocityFilter() const
+{
+    return m_velocityFilter;
+}
+
+WobblyWindowsEffect::GridFilter WobblyWindowsEffect::accelerationFilter() const
+{
+    return m_accelerationFilter;
+}
+
+void WobblyWindowsEffect::setAmortissement(qreal m_amortissement)
+{
+    this->m_amortissement = m_amortissement;
+}
+
+void WobblyWindowsEffect::prePaintScreen(ScreenPrePaintData& data, int time)
+{
+    // We need to mark the screen windows as transformed. Otherwise the whole
+    // screen won't be repainted, resulting in artefacts.
+    // Could we just set a subset of the screen to be repainted ?
+    if (windows.count() != 0)
+    {
+        data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
+    }
+
+    // this set the QRect invalid.
+    m_updateRegion.setWidth(0);
+
+    effects->prePaintScreen(data, time);
+}
+const qreal maxTime = 10.0;
+void WobblyWindowsEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, \
int time) +{
+    if (windows.contains(w))
+    {
+        data.setTransformed();
+        data.quads = data.quads.makeRegularGrid(m_xTesselation, m_yTesselation);
+        bool stop = false;
+        qreal updateTime = time;
+
+        while (!stop && (updateTime > maxTime))
+        {
+#if defined VERBOSE_MODE
+            kDebug() << "loop time " << updateTime << " / " << time;
+#endif
+            stop = !updateWindowWobblyDatas(w, maxTime);
+            updateTime -= maxTime;
+        }
+        if (!stop && updateTime > 0)
+        {
+            updateWindowWobblyDatas(w, updateTime);
+        }
+    }
+
+    effects->prePaintWindow(w, data, time);
+}
+
+void WobblyWindowsEffect::paintWindow(EffectWindow* w, int mask, QRegion region, \
WindowPaintData& data) +{
+    if(windows.contains(w))
+    {
+        WindowWobblyInfos& wwi = windows[w];
+        int tx = w->geometry().x();
+        int ty = w->geometry().y();
+        for (int i = 0; i < data.quads.count(); ++i)
+        {
+            for(int j = 0; j < 4; ++j)
+            {
+                WindowVertex& v = data.quads[i][j];
+                Pair oldPos = {tx + v.x(), ty + v.y()};
+                Pair newPos = computeBezierPoint(wwi, oldPos);
+                v.move(newPos.x - tx, newPos.y - ty);
+            }
+        }
+    }
+
+    // Call the next effect.
+    effects->paintWindow(w, mask, region, data);
+}
+
+void WobblyWindowsEffect::postPaintScreen()
+{
+    if (!windows.isEmpty())
+    {
+        effects->addRepaint(m_updateRegion);
+    }
+
+    // Call the next effect.
+    effects->postPaintScreen();
+}
+
+void WobblyWindowsEffect::windowUserMovedResized(EffectWindow* w, bool first, bool \
last) +{
+    if (first && !w->isSpecialWindow())
+    {
+        if (!windows.contains(w))
+        {
+            WindowWobblyInfos new_wwi;
+            initWobblyInfo(new_wwi, w->geometry());
+            windows[w] = new_wwi;
+        }
+
+        WindowWobblyInfos& wwi = windows[w];
+        wwi.onConstrain = true;
+        const QRectF& rect = w->geometry();
+
+        qreal x_increment = rect.width() / (wwi.width-1.0);
+        qreal y_increment = rect.height() / (wwi.height-1.0);
+
+        Pair picked = {cursorPos().x(), cursorPos().y()};
+//         wwi.mDestination.x = rect.x();
+//         wwi.mDestination.y = rect.y();
+        int indx = (picked.x - rect.x()) / x_increment;
+        int indy = (picked.y - rect.y()) / y_increment;
+        int pickedPointIndex = indy*wwi.width + indx;
+        if (pickedPointIndex < 0)
+        {
+            kDebug() << "Picked index == " << pickedPointIndex << " with (" << \
cursorPos().x() << "," << cursorPos().y() << ")"; +            pickedPointIndex = 0;
+        }
+        else if (static_cast<unsigned int>(pickedPointIndex) > wwi.count - 1)
+        {
+            kDebug() << "Picked index == " << pickedPointIndex << " with (" << \
cursorPos().x() << "," << cursorPos().y() << ")"; +            pickedPointIndex = \
wwi.count - 1; +        }
+#if defined VERBOSE_MODE
+        kDebug() << "Original Picked point -- x : " << picked.x << " - y : " << \
picked.y; +#endif
+        wwi.constraint[pickedPointIndex] = true;
+    }
+    else if (last)
+    {
+        if (windows.contains(w))
+        {
+            WindowWobblyInfos& wwi = windows[w];
+            wwi.onConstrain = false;
+        }
+    }
+}
+
+void WobblyWindowsEffect::windowClosed(EffectWindow* w)
+{
+    if(windows.contains(w))
+    {
+        WindowWobblyInfos& wwi = windows[w];
+        freeWobblyInfo(wwi);
+        windows.remove(w);
+    }
+}
+
+void WobblyWindowsEffect::initWobblyInfo(WindowWobblyInfos& wwi, QRect geometry) \
const +{
+    wwi.count = 4*4;
+    wwi.width = 4;
+    wwi.height = 4;
+
+    wwi.bezierWidth = m_xTesselation;
+    wwi.bezierHeight = m_yTesselation;
+    wwi.bezierCount = m_xTesselation * m_yTesselation;
+
+    wwi.origin = new Pair[wwi.count];
+    wwi.position = new Pair[wwi.count];
+    wwi.velocity = new Pair[wwi.count];
+    wwi.acceleration = new Pair[wwi.count];
+    wwi.buffer = new Pair[wwi.count];
+    wwi.constraint = new bool[wwi.count];
+
+    wwi.bezierSurface = new Pair[wwi.bezierCount];
+
+    wwi.onConstrain = true;
+
+    qreal x = geometry.x(), y = geometry.y();
+    qreal width = geometry.width(), height = geometry.height();
+
+    Pair initValue = {x, y};
+    static const Pair nullPair = {0.0, 0.0};
+
+    qreal x_increment = width / (wwi.width-1.0);
+    qreal y_increment = height / (wwi.height-1.0);
+
+    for (unsigned int j=0; j<4; ++j)
+    {
+        for (unsigned int i=0; i<4; ++i)
+        {
+            unsigned int idx = j*4 + i;
+            wwi.origin[idx] = initValue;
+            wwi.position[idx] = initValue;
+            wwi.velocity[idx] = nullPair;
+            wwi.constraint[idx] = false;
+            if (i != 4-2) // x grid count - 2, i.e. not the last point
+            {
+                initValue.x += x_increment;
+            }
+            else
+            {
+                initValue.x = width + x;
+            }
+            initValue.x = initValue.x;
+        }
+        initValue.x = x;
+        initValue.x = initValue.x;
+        if (j != 4-2) // y grid count - 2, i.e. not the last point
+        {
+            initValue.y += y_increment;
+        }
+        else
+        {
+            initValue.y = height + y;
+        }
+        initValue.y = initValue.y;
+    }
+}
+
+void WobblyWindowsEffect::freeWobblyInfo(WindowWobblyInfos& wwi) const
+{
+    delete wwi.origin;
+    delete wwi.position;
+    delete wwi.velocity;
+    delete wwi.acceleration;
+    delete wwi.buffer;
+    delete wwi.constraint;
+
+    delete wwi.bezierSurface;
+}
+
+WobblyWindowsEffect::Pair WobblyWindowsEffect::computeBezierPoint(const \
WindowWobblyInfos& wwi, Pair point) const +{
+    // compute the input value
+    Pair topleft = wwi.origin[0];
+    Pair bottomright = wwi.origin[wwi.count-1];
+
+    ASSERT1(point.x >= topleft.x);
+    ASSERT1(point.y >= topleft.y);
+    ASSERT1(point.x <= bottomright.x);
+    ASSERT1(point.y <= bottomright.y);
+
+    qreal tx = (point.x - topleft.x) / (bottomright.x - topleft.x);
+    qreal ty = (point.y - topleft.y) / (bottomright.y - topleft.y);
+
+    ASSERT1(tx >= 0);
+    ASSERT1(tx <= 1);
+    ASSERT1(ty >= 0);
+    ASSERT1(ty <= 1);
+
+    // compute polinomial coeff
+
+    qreal px[4];
+    px[0] = (1-tx)*(1-tx)*(1-tx);
+    px[1] = 3*(1-tx)*(1-tx)*tx;
+    px[2] = 3*(1-tx)*tx*tx;
+    px[3] = tx*tx*tx;
+
+    qreal py[4];
+    py[0] = (1-ty)*(1-ty)*(1-ty);
+    py[1] = 3*(1-ty)*(1-ty)*ty;
+    py[2] = 3*(1-ty)*ty*ty;
+    py[3] = ty*ty*ty;
+
+    Pair res = {0.0, 0.0};
+
+    for (unsigned int j = 0; j < 4; ++j)
+    {
+        for (unsigned int i = 0; i < 4; ++i)
+        {
+            // this assume the grid is 4*4
+            res.x += px[i] * py[j] * wwi.position[i + j * wwi.width].x;
+            res.y += px[i] * py[j] * wwi.position[i + j * wwi.width].y;
+        }
+    }
+
+    return res;
+}
+namespace
+{
+
+static inline void fixVectorBounds(WobblyWindowsEffect::Pair& vec, qreal min, qreal \
max) +{
+    if (fabs(vec.x) < min)
+    {
+        vec.x = 0.0;
+    }
+    else if (fabs(vec.x) > max)
+    {
+        if (vec.x > 0.0)
+        {
+            vec.x = max;
+        }
+        else
+        {
+            vec.x = -max;
+        }
+    }
+
+    if (fabs(vec.y) < min)
+    {
+        vec.y = 0.0;
+    }
+    else if (fabs(vec.y) > max)
+    {
+        if (vec.y > 0.0)
+        {
+            vec.y = max;
+        }
+        else
+        {
+            vec.y = -max;
+        }
+    }
+}
+
+static inline void computeVectorBounds(WobblyWindowsEffect::Pair& vec, \
WobblyWindowsEffect::Pair& bound) +{
+    if (fabs(vec.x) < bound.x)
+    {
+        bound.x = fabs(vec.x);
+    }
+    else if (fabs(vec.x) > bound.y)
+    {
+        bound.y = fabs(vec.x);
+    }
+    if (fabs(vec.y) < bound.x)
+    {
+        bound.x = fabs(vec.y);
+    }
+    else if (fabs(vec.y) > bound.y)
+    {
+        bound.y = fabs(vec.y);
+    }
+}
+
+} // close the anonymous namespace
+
+bool WobblyWindowsEffect::updateWindowWobblyDatas(EffectWindow* w, qreal time)
+{
+    const QRectF& rect = w->geometry();
+    WindowWobblyInfos& wwi = windows[w];
+
+    qreal x_length = rect.width() / (wwi.width-1.0);
+    qreal y_length = rect.height() / (wwi.height-1.0);
+
+#if defined VERBOSE_MODE
+    kDebug() << "time " << time;
+    kDebug() << "increment x " << x_length << " // y" <<  y_length;
+#endif
+
+    Pair origine = {rect.x(), rect.y()};
+
+    for (unsigned int j=0; j<wwi.height; ++j)
+    {
+        for (unsigned int i=0; i<wwi.width; ++i)
+        {
+            wwi.origin[wwi.width*j + i] = origine;
+            if (i != wwi.width-2)
+            {
+                origine.x += x_length;
+            }
+            else
+            {
+                origine.x = rect.width() + rect.x();
+            }
+         }
+        origine.x = rect.x();
+        if (j != wwi.height-2)
+        {
+            origine.y += y_length;
+        }
+        else
+        {
+            origine.y = rect.height() + rect.y();
+        }
+    }
+
+    Pair neibourgs[4];
+    Pair acceleration;
+
+    qreal acc_sum = 0.0;
+    qreal vel_sum = 0.0;
+
+    // compute acceleration, velocity and position for each point
+
+    // for corners
+
+    // top-left
+
+    if (wwi.constraint[0])
+    {
+        Pair window_pos = wwi.origin[0];
+        Pair current_pos = wwi.position[0];
+        Pair move = {window_pos.x - current_pos.x, window_pos.y - current_pos.y};
+        Pair accel = {move.x*m_raideur, move.y*m_raideur};
+        wwi.acceleration[0] = accel;
+    }
+    else
+    {
+        Pair& pos = wwi.position[0];
+        neibourgs[0] = wwi.position[1];
+        neibourgs[1] = wwi.position[wwi.width];
+
+        acceleration.x = ((neibourgs[0].x - pos.x) - x_length)*m_raideur + \
(neibourgs[1].x - pos.x)*m_raideur; +        acceleration.y = ((neibourgs[1].y - \
pos.y) - y_length)*m_raideur + (neibourgs[0].y - pos.y)*m_raideur; +
+        acceleration.x /= 2;
+        acceleration.y /= 2;
+
+        wwi.acceleration[0] = acceleration;
+    }
+
+    // top-right
+
+    if (wwi.constraint[wwi.width-1])
+    {
+        Pair window_pos = wwi.origin[wwi.width-1];
+        Pair current_pos = wwi.position[wwi.width-1];
+        Pair move = {window_pos.x - current_pos.x, window_pos.y - current_pos.y};
+        Pair accel = {move.x*m_raideur, move.y*m_raideur};
+        wwi.acceleration[wwi.width-1] = accel;
+    }
+    else
+    {
+        Pair& pos = wwi.position[wwi.width-1];
+        neibourgs[0] = wwi.position[wwi.width-2];
+        neibourgs[1] = wwi.position[2*wwi.width-1];
+
+        acceleration.x = (x_length - (pos.x - neibourgs[0].x))*m_raideur + \
(neibourgs[1].x - pos.x)*m_raideur; +        acceleration.y = ((neibourgs[1].y - \
pos.y) - y_length)*m_raideur + (neibourgs[0].y - pos.y)*m_raideur; +
+        acceleration.x /= 2;
+        acceleration.y /= 2;
+
+        wwi.acceleration[wwi.width-1] = acceleration;
+    }
+
+    // bottom-left
+
+    if (wwi.constraint[wwi.width*(wwi.height-1)])
+    {
+        Pair window_pos = wwi.origin[wwi.width*(wwi.height-1)];
+        Pair current_pos = wwi.position[wwi.width*(wwi.height-1)];
+        Pair move = {window_pos.x - current_pos.x, window_pos.y - current_pos.y};
+        Pair accel = {move.x*m_raideur, move.y*m_raideur};
+        wwi.acceleration[wwi.width*(wwi.height-1)] = accel;
+    }
+    else
+    {
+        Pair& pos = wwi.position[wwi.width*(wwi.height-1)];
+        neibourgs[0] = wwi.position[wwi.width*(wwi.height-1)+1];
+        neibourgs[1] = wwi.position[wwi.width*(wwi.height-2)];
+
+        acceleration.x = ((neibourgs[0].x - pos.x) - x_length)*m_raideur + \
(neibourgs[1].x - pos.x)*m_raideur; +        acceleration.y = (y_length - (pos.y - \
neibourgs[1].y))*m_raideur + (neibourgs[0].y - pos.y)*m_raideur; +
+        acceleration.x /= 2;
+        acceleration.y /= 2;
+
+        wwi.acceleration[wwi.width*(wwi.height-1)] = acceleration;
+    }
+
+    // bottom-right
+
+    if (wwi.constraint[wwi.count-1])
+    {
+        Pair window_pos = wwi.origin[wwi.count-1];
+        Pair current_pos = wwi.position[wwi.count-1];
+        Pair move = {window_pos.x - current_pos.x, window_pos.y - current_pos.y};
+        Pair accel = {move.x*m_raideur, move.y*m_raideur};
+        wwi.acceleration[wwi.count-1] = accel;
+    }
+    else
+    {
+        Pair& pos = wwi.position[wwi.count-1];
+        neibourgs[0] = wwi.position[wwi.count-2];
+        neibourgs[1] = wwi.position[wwi.width*(wwi.height-1)-1];
+
+        acceleration.x = (x_length - (pos.x - neibourgs[0].x))*m_raideur + \
(neibourgs[1].x - pos.x)*m_raideur; +        acceleration.y = (y_length - (pos.y - \
neibourgs[1].y))*m_raideur + (neibourgs[0].y - pos.y)*m_raideur; +
+        acceleration.x /= 2;
+        acceleration.y /= 2;
+
+        wwi.acceleration[wwi.count-1] = acceleration;
+    }
+
+
+    // for borders
+
+    // top border
+    for (unsigned int i=1; i<wwi.width-1; ++i)
+    {
+        if (wwi.constraint[i])
+        {
+            Pair window_pos = wwi.origin[i];
+            Pair current_pos = wwi.position[i];
+            Pair move = {window_pos.x - current_pos.x, window_pos.y - \
current_pos.y}; +            Pair accel = {move.x*m_raideur, move.y*m_raideur};
+            wwi.acceleration[i] = accel;
+        }
+        else
+        {
+            Pair& pos = wwi.position[i];
+            neibourgs[0] = wwi.position[i-1];
+            neibourgs[1] = wwi.position[i+1];
+            neibourgs[2] = wwi.position[i+wwi.width];
+
+            acceleration.x = (x_length - (pos.x - neibourgs[0].x))*m_raideur + \
((neibourgs[1].x - pos.x) - x_length)*m_raideur + (neibourgs[2].x - pos.x)*m_raideur; \
+            acceleration.y = ((neibourgs[2].y - pos.y) - y_length)*m_raideur + \
(neibourgs[0].y - pos.y)*m_raideur + (neibourgs[1].y - pos.y)*m_raideur; +
+            acceleration.x /= 3;
+            acceleration.y /= 3;
+
+            wwi.acceleration[i] = acceleration;
+        }
+    }
+
+    // bottom border
+    for (unsigned int i=wwi.width*(wwi.height-1)+1; i<wwi.count-1; ++i)
+    {
+        if (wwi.constraint[i])
+        {
+            Pair window_pos = wwi.origin[i];
+            Pair current_pos = wwi.position[i];
+            Pair move = {window_pos.x - current_pos.x, window_pos.y - \
current_pos.y}; +            Pair accel = {move.x*m_raideur, move.y*m_raideur};
+            wwi.acceleration[i] = accel;
+        }
+        else
+        {
+            Pair& pos = wwi.position[i];
+            neibourgs[0] = wwi.position[i-1];
+            neibourgs[1] = wwi.position[i+1];
+            neibourgs[2] = wwi.position[i-wwi.width];
+
+            acceleration.x = (x_length - (pos.x - neibourgs[0].x))*m_raideur + \
((neibourgs[1].x - pos.x) - x_length)*m_raideur + (neibourgs[2].x - pos.x)*m_raideur; \
+            acceleration.y = (y_length - (pos.y - neibourgs[2].y))*m_raideur + \
(neibourgs[0].y - pos.y)*m_raideur + (neibourgs[1].y - pos.y)*m_raideur; +
+            acceleration.x /= 3;
+            acceleration.y /= 3;
+
+            wwi.acceleration[i] = acceleration;
+        }
+    }
+
+    // left border
+    for (unsigned int i=wwi.width; i<wwi.width*(wwi.height-1); i+=wwi.width)
+    {
+        if (wwi.constraint[i])
+        {
+            Pair window_pos = wwi.origin[i];
+            Pair current_pos = wwi.position[i];
+            Pair move = {window_pos.x - current_pos.x, window_pos.y - \
current_pos.y}; +            Pair accel = {move.x*m_raideur, move.y*m_raideur};
+            wwi.acceleration[i] = accel;
+        }
+        else
+        {
+            Pair& pos = wwi.position[i];
+            neibourgs[0] = wwi.position[i+1];
+            neibourgs[1] = wwi.position[i-wwi.width];
+            neibourgs[2] = wwi.position[i+wwi.width];
+
+            acceleration.x = ((neibourgs[0].x - pos.x) - x_length)*m_raideur + \
(neibourgs[1].x - pos.x)*m_raideur + (neibourgs[2].x - pos.x)*m_raideur; +            \
acceleration.y = (y_length - (pos.y - neibourgs[1].y))*m_raideur + ((neibourgs[2].y - \
pos.y) - y_length)*m_raideur + (neibourgs[0].y - pos.y)*m_raideur; +
+            acceleration.x /= 3;
+            acceleration.y /= 3;
+
+            wwi.acceleration[i] = acceleration;
+        }
+    }
+
+    // right border
+    for (unsigned int i=2*wwi.width-1; i<wwi.count-1; i+=wwi.width)
+    {
+        if (wwi.constraint[i])
+        {
+            Pair window_pos = wwi.origin[i];
+            Pair current_pos = wwi.position[i];
+            Pair move = {window_pos.x - current_pos.x, window_pos.y - \
current_pos.y}; +            Pair accel = {move.x*m_raideur, move.y*m_raideur};
+            wwi.acceleration[i] = accel;
+        }
+        else
+        {
+            Pair& pos = wwi.position[i];
+            neibourgs[0] = wwi.position[i-1];
+            neibourgs[1] = wwi.position[i-wwi.width];
+            neibourgs[2] = wwi.position[i+wwi.width];
+
+            acceleration.x = (x_length - (pos.x - neibourgs[0].x))*m_raideur + \
(neibourgs[1].x - pos.x)*m_raideur + (neibourgs[2].x - pos.x)*m_raideur; +            \
acceleration.y = (y_length - (pos.y - neibourgs[1].y))*m_raideur + ((neibourgs[2].y - \
pos.y) - y_length)*m_raideur + (neibourgs[0].y - pos.y)*m_raideur; +
+            acceleration.x /= 3;
+            acceleration.y /= 3;
+
+            wwi.acceleration[i] = acceleration;
+        }
+    }
+
+    // for the inner points
+    for (unsigned int j=1; j<wwi.height-1; ++j)
+    {
+        for (unsigned int i=1; i<wwi.width-1; ++i)
+        {
+            unsigned int index = i+j*wwi.width;
+
+            if (wwi.constraint[index])
+            {
+            Pair window_pos = wwi.origin[index];
+            Pair current_pos = wwi.position[index];
+            Pair move = {window_pos.x - current_pos.x, window_pos.y - \
current_pos.y}; +            Pair accel = {move.x*m_raideur, move.y*m_raideur};
+            wwi.acceleration[index] = accel;
+            }
+            else
+            {
+                Pair& pos = wwi.position[index];
+                neibourgs[0] = wwi.position[index-1];
+                neibourgs[1] = wwi.position[index+1];
+                neibourgs[2] = wwi.position[index-wwi.width];
+                neibourgs[3] = wwi.position[index+wwi.width];
+
+                acceleration.x = ((neibourgs[0].x - pos.x) - x_length)*m_raideur +
+                                 (x_length - (pos.x - neibourgs[1].x))*m_raideur +
+                                 (neibourgs[2].x - pos.x)*m_raideur +
+                                 (neibourgs[3].x - pos.x)*m_raideur;
+                acceleration.y = (y_length - (pos.y - neibourgs[2].y))*m_raideur +
+                                 ((neibourgs[3].y - pos.y) - y_length)*m_raideur +
+                                 (neibourgs[0].y - pos.y)*m_raideur +
+                                 (neibourgs[1].y - pos.y)*m_raideur;
+
+                acceleration.x /= 4;
+                acceleration.y /= 4;
+
+                wwi.acceleration[index] = acceleration;
+            }
+        }
+    }
+
+    switch (m_accelerationFilter)
+    {
+    case NoFilter:
+        break;
+
+    case FourRingLinearMean:
+        fourRingLinearMean(&wwi.acceleration, wwi);
+        break;
+
+    case MeanWithMean:
+        meanWithMean(&wwi.acceleration, wwi);
+        break;
+
+    case MeanWithMedian:
+        meanWithMedian(&wwi.acceleration, wwi);
+        break;
+
+    default:
+        ASSERT1(false);
+    }
+
+#if defined COMPUTE_STATS
+    Pair accBound = {maxAcceleration, minAcceleration};
+    Pair velBound = {maxVelocity, minVelocity};
+#endif
+
+    // compute the new velocity of each vertex.
+    for (unsigned int i = 0; i < wwi.count; ++i)
+    {
+        Pair acc = wwi.acceleration[i];
+        fixVectorBounds(acc, m_minAcceleration, m_maxAcceleration);
+
+#if defined COMPUTE_STATS
+        computeVectorBounds(acc, accBound);
+#endif
+
+        Pair& vel = wwi.velocity[i];
+        vel.x = acc.x*time + vel.x*m_amortissement;
+        vel.y = acc.y*time + vel.y*m_amortissement;
+
+        acc_sum += fabs(acc.x) + fabs(acc.y);
+    }
+
+
+    switch (m_velocityFilter)
+    {
+    case NoFilter:
+        break;
+
+    case FourRingLinearMean:
+        fourRingLinearMean(&wwi.velocity, wwi);
+        break;
+
+    case MeanWithMean:
+        meanWithMean(&wwi.velocity, wwi);
+        break;
+
+    case MeanWithMedian:
+        meanWithMedian(&wwi.velocity, wwi);
+        break;
+
+    default:
+        ASSERT1(false);
+    }
+
+    Pair topLeftCorner = {-10000.0, -10000.0};
+    Pair bottomRightCorner = {10000.0, 10000.0};
+
+    // compute the new pos of each vertex.
+    for (unsigned int i = 0; i < wwi.count; ++i)
+    {
+        Pair& pos = wwi.position[i];
+        Pair& vel = wwi.velocity[i];
+
+        fixVectorBounds(vel, m_minVelocity, m_maxVelocity);
+#if defined COMPUTE_STATS
+        computeVectorBounds(vel, velBound);
+#endif
+
+        pos.x += vel.x*time*m_move_factor;
+        pos.y += vel.y*time*m_move_factor;
+
+        if (pos.x < topLeftCorner.x)
+        {
+            topLeftCorner.x = pos.x;
+        }
+        if (pos.x > bottomRightCorner.x)
+        {
+            bottomRightCorner.x = pos.x;
+        }
+        if (pos.y < topLeftCorner.y)
+        {
+            topLeftCorner.y = pos.y;
+        }
+        if (pos.y > bottomRightCorner.y)
+        {
+            bottomRightCorner.y = pos.y;
+        }
+
+        vel_sum += fabs(vel.x) + fabs(vel.y);
+
+#if defined VERBOSE_MODE
+        if (fixedIndex == i)
+        {
+            kDebug() << "Fixed item ** vel : " << vel.x << "," << vel.y << " ** move \
: " << vel.x*time << "," << vel.y*time; +        }
+#endif
+    }
+
+#if defined VERBOSE_MODE
+#   if defined COMPUTE_STATS
+        kDebug() << "Acceleration bounds (" << accBound.x << ", " << accBound.y << \
")"; +        kDebug() << "Velocity bounds (" << velBound.x << ", " << velBound.y << \
")"; +#   endif
+    kDebug() << "sum_acc : " << acc_sum << "  ***  sum_vel :" << vel_sum;
+#endif
+
+    if (!wwi.onConstrain && acc_sum < m_stopAcceleration && vel_sum < \
m_stopVelocity) +    {
+        freeWobblyInfo(wwi);
+        windows.remove(w);
+        return false;
+    }
+
+    QRect windowRect(topLeftCorner.x, topLeftCorner.y,
+        bottomRightCorner.x - topLeftCorner.x, bottomRightCorner.y - \
topLeftCorner.y); +    if (m_updateRegion.isValid())
+    {
+        m_updateRegion = m_updateRegion.united(windowRect);
+    }
+    else
+    {
+        m_updateRegion = windowRect;
+    }
+
+    return true;
+}
+
+void WobblyWindowsEffect::fourRingLinearMean(Pair** datas_pointer, \
WindowWobblyInfos& wwi) +{
+    Pair* datas = *datas_pointer;
+    Pair neibourgs[4];
+
+    // for corners
+
+    // top-left
+    {
+        Pair& res = wwi.buffer[0];
+        Pair vit = datas[0];
+        neibourgs[0] = datas[1];
+        neibourgs[1] = datas[wwi.width];
+
+        res.x = (neibourgs[0].x + neibourgs[1].x + 2.0*vit.x) / 4.0;
+        res.y = (neibourgs[0].y + neibourgs[1].y + 2.0*vit.y) / 4.0;
+    }
+
+
+    // top-right
+    {
+        Pair& res = wwi.buffer[wwi.width-1];
+        Pair vit = datas[wwi.width-1];
+        neibourgs[0] = datas[wwi.width-2];
+        neibourgs[1] = datas[2*wwi.width-1];
+
+        res.x = (neibourgs[0].x + neibourgs[1].x + 2.0*vit.x) / 4.0;
+        res.y = (neibourgs[0].y + neibourgs[1].y + 2.0*vit.y) / 4.0;
+    }
+
+
+    // bottom-left
+    {
+        Pair& res = wwi.buffer[wwi.width*(wwi.height-1)];
+        Pair vit = datas[wwi.width*(wwi.height-1)];
+        neibourgs[0] = datas[wwi.width*(wwi.height-1)+1];
+        neibourgs[1] = datas[wwi.width*(wwi.height-2)];
+
+        res.x = (neibourgs[0].x + neibourgs[1].x + 2.0*vit.x) / 4.0;
+        res.y = (neibourgs[0].y + neibourgs[1].y + 2.0*vit.y) / 4.0;
+    }
+
+
+    // bottom-right
+    {
+        Pair& res = wwi.buffer[wwi.count-1];
+        Pair vit = datas[wwi.count-1];
+        neibourgs[0] = datas[wwi.count-2];
+        neibourgs[1] = datas[wwi.width*(wwi.height-1)-1];
+
+        res.x = (neibourgs[0].x + neibourgs[1].x + 2.0*vit.x) / 4.0;
+        res.y = (neibourgs[0].y + neibourgs[1].y + 2.0*vit.y) / 4.0;
+    }
+
+
+    // for borders
+
+    // top border
+    for (unsigned int i=1; i<wwi.width-1; ++i)
+    {
+        Pair& res = wwi.buffer[i];
+        Pair vit = datas[i];
+        neibourgs[0] = datas[i-1];
+        neibourgs[1] = datas[i+1];
+        neibourgs[2] = datas[i+wwi.width];
+
+        res.x = (neibourgs[0].x + neibourgs[1].x + neibourgs[2].x + 3.0*vit.x) / \
6.0; +        res.y = (neibourgs[0].y + neibourgs[1].y + neibourgs[2].y + 3.0*vit.y) \
/ 6.0; +    }
+
+    // bottom border
+    for (unsigned int i=wwi.width*(wwi.height-1)+1; i<wwi.count-1; ++i)
+    {
+        Pair& res = wwi.buffer[i];
+        Pair vit = datas[i];
+        neibourgs[0] = datas[i-1];
+        neibourgs[1] = datas[i+1];
+        neibourgs[2] = datas[i-wwi.width];
+
+        res.x = (neibourgs[0].x + neibourgs[1].x + neibourgs[2].x + 3.0*vit.x) / \
6.0; +        res.y = (neibourgs[0].y + neibourgs[1].y + neibourgs[2].y + 3.0*vit.y) \
/ 6.0; +    }
+
+    // left border
+    for (unsigned int i=wwi.width; i<wwi.width*(wwi.height-1); i+=wwi.width)
+    {
+        Pair& res = wwi.buffer[i];
+        Pair vit = datas[i];
+        neibourgs[0] = datas[i+1];
+        neibourgs[1] = datas[i-wwi.width];
+        neibourgs[2] = datas[i+wwi.width];
+
+        res.x = (neibourgs[0].x + neibourgs[1].x + neibourgs[2].x + 3.0*vit.x) / \
6.0; +        res.y = (neibourgs[0].y + neibourgs[1].y + neibourgs[2].y + 3.0*vit.y) \
/ 6.0; +    }
+
+    // right border
+    for (unsigned int i=2*wwi.width-1; i<wwi.count-1; i+=wwi.width)
+    {
+        Pair& res = wwi.buffer[i];
+        Pair vit = datas[i];
+        neibourgs[0] = datas[i-1];
+        neibourgs[1] = datas[i-wwi.width];
+        neibourgs[2] = datas[i+wwi.width];
+
+        res.x = (neibourgs[0].x + neibourgs[1].x + neibourgs[2].x + 3.0*vit.x) / \
6.0; +        res.y = (neibourgs[0].y + neibourgs[1].y + neibourgs[2].y + 3.0*vit.y) \
/ 6.0; +    }
+
+    // for the inner points
+    for (unsigned int j=1; j<wwi.height-1; ++j)
+    {
+        for (unsigned int i=1; i<wwi.width-1; ++i)
+        {
+            unsigned int index = i+j*wwi.width;
+
+            Pair& res = wwi.buffer[index];
+            Pair& vit = datas[index];
+            neibourgs[0] = datas[index-1];
+            neibourgs[1] = datas[index+1];
+            neibourgs[2] = datas[index-wwi.width];
+            neibourgs[3] = datas[index+wwi.width];
+
+            res.x = (neibourgs[0].x + neibourgs[1].x + neibourgs[2].x + \
neibourgs[3].x + 4.0*vit.x) / 8.0; +            res.y = (neibourgs[0].y + \
neibourgs[1].y + neibourgs[2].y + neibourgs[3].y + 4.0*vit.y) / 8.0; +        }
+    }
+
+    Pair* tmp = datas;
+    *datas_pointer = wwi.buffer;
+    wwi.buffer = tmp;
+}
+
+void WobblyWindowsEffect::meanWithMean(Pair** datas_pointer, WindowWobblyInfos& wwi)
+{
+    Pair* datas = *datas_pointer;
+
+    Pair mean = {0.0, 0.0};
+    for (unsigned int i = 0; i < wwi.count; ++i)
+    {
+        mean.x += datas[i].x;
+        mean.y += datas[i].y;
+    }
+
+    mean.x /= wwi.count;
+    mean.y /= wwi.count;
+
+    for (unsigned int i = 0; i < wwi.count; ++i)
+    {
+        wwi.buffer[i].x = (datas[i].x + mean.x) / 2.0;
+        wwi.buffer[i].y = (datas[i].y + mean.y) / 2.0;
+    }
+
+    Pair* tmp = datas;
+    *datas_pointer = wwi.buffer;
+    wwi.buffer = tmp;
+}
+
+void WobblyWindowsEffect::meanWithMedian(Pair** datas_pointer, WindowWobblyInfos& \
wwi) +{
+    Pair* datas = *datas_pointer;
+
+    qreal xmin = datas[0].x, ymin = datas[0].y;
+    qreal xmax = datas[0].x, ymax = datas[0].y;
+    for (unsigned int i = 1; i < wwi.count; ++i)
+    {
+        if (datas[i].x < xmin)
+        {
+            xmin = datas[i].x;
+        }
+        if (datas[i].x > xmax)
+        {
+            xmax = datas[i].x;
+        }
+
+        if (datas[i].y < ymin)
+        {
+            ymin = datas[i].y;
+        }
+        if (datas[i].y > ymax)
+        {
+            ymax = datas[i].y;
+        }
+    }
+
+    Pair median = {(xmin + xmax)/2.0, (ymin + ymax)/2.0};
+
+    for (unsigned int i = 0; i < wwi.count; ++i)
+    {
+        wwi.buffer[i].x = (datas[i].x + median.x) / 2.0;
+        wwi.buffer[i].y = (datas[i].y + median.y) / 2.0;
+    }
+
+    Pair* tmp = datas;
+    *datas_pointer = wwi.buffer;
+    wwi.buffer = tmp;
+}
+
+
+} // namespace KWin
+
Index: effects/CMakeLists.txt
===================================================================
--- effects/CMakeLists.txt	(révision 785951)
+++ effects/CMakeLists.txt	(copie de travail)
@@ -108,6 +108,7 @@
         sharpen.cpp
         snow.cpp
         trackmouse.cpp
+        wobblywindows.cpp
         )
     install( FILES
         blur.desktop
@@ -122,6 +123,7 @@
         sharpen.desktop
         snow.desktop
         trackmouse.desktop
+        wobblywindows.desktop
         DESTINATION ${SERVICES_INSTALL_DIR}/kwin )
     install( FILES
         data/trackmouse.png
@@ -160,6 +162,8 @@
         snow_config.cpp
         snow_config.ui
         trackmouse_config.cpp
+        wobblywindows_config.cpp
+        wobblywindows_config.ui
         )
     install( FILES
         coverswitch_config.desktop
@@ -172,6 +176,7 @@
         showfps_config.desktop
         snow_config.desktop
         trackmouse_config.desktop
+        wobblywindows_config.desktop
         DESTINATION ${SERVICES_INSTALL_DIR}/kwin )
 endif(KWIN_HAVE_OPENGL_COMPOSITING)
 
Index: effects/configs_builtins.cpp
===================================================================
--- effects/configs_builtins.cpp	(révision 785951)
+++ effects/configs_builtins.cpp	(copie de travail)
@@ -39,6 +39,7 @@
 #include "sharpen_config.h"
 #include "snow_config.h"
 #include "trackmouse_config.h"
+#include "wobblywindows_config.h"
 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
 #include "showfps_config.h"
 #endif
@@ -71,6 +72,7 @@
     registerPlugin<KWin::SnowEffectConfig>("snow"); \
     registerPlugin<KWin::TrackMouseEffectConfig>("trackmouse"); \
     registerPlugin<KWin::ShowFpsEffectConfig> ("showfps"); \
+    registerPlugin<KWin::WobblyWindowsEffectConfig> ("wobblywindows"); \
 
 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
 K_PLUGIN_FACTORY_DEFINITION(EffectFactory,



_______________________________________________
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