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

List:       kwin
Subject:    Re: wobbly effect
From:       cedric <cedric.borgese () gmail ! com>
Date:       2008-02-20 22:29:21
Message-ID: 200802202329.21555.cedric.borgese () gmail ! com
[Download RAW message or body]

and the patch...



["kwin.diff" (text/x-patch)]

Index: effects/CMakeLists.txt
===================================================================
--- effects/CMakeLists.txt	(revision 777553)
+++ effects/CMakeLists.txt	(working copy)
@@ -1,5 +1,5 @@
 # Uncomment to have the test effects built
-#add_subdirectory( test )
+add_subdirectory( test )
 
 
 # Adds effect plugin with given name. Sources are given after the name
Index: effects/test/demo_wobblywindows.cpp
===================================================================
--- effects/test/demo_wobblywindows.cpp	(revision 0)
+++ effects/test/demo_wobblywindows.cpp	(revision 0)
@@ -0,0 +1,1153 @@
+/*****************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2007
+
+You can Freely distribute this program under the GNU General Public
+License. See the file "COPYING" for the exact licensing terms.
+******************************************************************/
+
+
+#include "demo_wobblywindows.h"
+#include "demo_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(demo_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_squareRootMasterAcceleration = conf.readEntry("SquareRootMasterAcceleration", \
SQUAREROOTMASTERACCELERATION); +
+    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;
+
+        WindowWobblyInfos& wwi = windows[w];
+        if (wwi.onConstrain)
+        {
+            wwi.mDestination.x = cursorPos().x();
+            wwi.mDestination.y = cursorPos().y();
+        }
+
+        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);
+        // Repaint the workspace so that everything would be repainted next time
+        //effects->addRepaintFull();
+    }
+
+    // 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 = picked;
+        int indx = (picked.x - rect.x()) / x_increment;
+        int indy = (picked.y - rect.y()) / y_increment;
+        wwi.mPickedPointIndex = indy*wwi.width + indx;
+        if (wwi.mPickedPointIndex < 0)
+        {
+            kDebug() << "Picked index == " << wwi.mPickedPointIndex << " with (" << \
cursorPos().x() << "," << cursorPos().y() << ")"; +            wwi.mPickedPointIndex \
= 0; +        }
+        else if (static_cast<unsigned int>(wwi.mPickedPointIndex) > wwi.count - 1)
+        {
+            kDebug() << "Picked index == " << wwi.mPickedPointIndex << " with (" << \
cursorPos().x() << "," << cursorPos().y() << ")"; +            wwi.mPickedPointIndex \
= wwi.count - 1; +        }
+#if defined VERBOSE_MODE
+        kDebug() << "Original Picked point -- x : " << picked.x << " - y : " << \
picked.y; +#endif
+        wwi.mPickedPointTranslation.x = wwi.position[wwi.mPickedPointIndex].x - \
picked.x; +        wwi.mPickedPointTranslation.y = \
wwi.position[wwi.mPickedPointIndex].y - picked.y; +    }
+    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.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;
+            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.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);
+
+    Pair picked = wwi.mDestination;
+
+    Pair pickedTranslation = wwi.mPickedPointTranslation;
+    picked.x += pickedTranslation.x;
+    picked.y += pickedTranslation.y;
+    Pair on_grid_picked = wwi.position[wwi.mPickedPointIndex];
+    Pair move = {picked.x - on_grid_picked.x, picked.y - on_grid_picked.y};
+
+#if defined VERBOSE_MODE
+    kDebug() << "Picked point -- x : " << picked.x << " - y : " << picked.y;
+    kDebug() << "On grid point -- x : " << on_grid_picked.x << " - y : " << \
on_grid_picked.y; +    kDebug() << "Move -- x : " << move.x << " - y : " << move.y;
+
+    kDebug() << "time " << time;
+#endif
+
+    Pair origine = {rect.x(), rect.y()};
+
+#if defined VERBOSE_MODE
+    kDebug() << "increment x " << x_length << " // y" <<  y_length;
+#endif
+
+    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 acc = {move.x*m_raideur, move.y*m_raideur};
+    if (m_squareRootMasterAcceleration)
+    {
+        if (acc.x < 0.0)
+        {
+            acc.x = -sqrt(-acc.x);
+        }
+        else
+        {
+            acc.x = sqrt(acc.x);
+        }
+
+        if (acc.y < 0.0)
+        {
+            acc.y = -sqrt(-acc.y);
+        }
+        else
+        {
+            acc.y = sqrt(acc.y);
+        }
+    }
+
+#if defined VERBOSE_MODE
+    kDebug() << "Master acceleration -- x : " << acc.x << " - y : " << acc.y;
+#endif
+
+    unsigned int fixedIndex = wwi.mPickedPointIndex;
+    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
+
+    // acceleration is acc
+    if (fixedIndex == 0)
+    {
+        wwi.acceleration[0] = acc;
+    }
+    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
+
+    // acceleration is acc
+    if (fixedIndex == wwi.width-1)
+    {
+        wwi.acceleration[wwi.width-1] = acc;
+    }
+    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
+
+    // acceleration is acc
+    if (fixedIndex == wwi.width*(wwi.height-1))
+    {
+        wwi.acceleration[wwi.width*(wwi.height-1)] = acc;
+    }
+    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
+
+    // acceleration is acc
+    if (fixedIndex == wwi.count-1)
+    {
+        wwi.acceleration[wwi.count-1] = acc;
+    }
+    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)
+    {
+        // acceleration is acc
+        if (fixedIndex == i)
+        {
+            wwi.acceleration[i] = acc;
+        }
+        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)
+    {
+        // acceleration is acc
+        if (fixedIndex == i)
+        {
+            wwi.acceleration[i] = acc;
+        }
+        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)
+    {
+        // acceleration is acc
+        if (fixedIndex == i)
+        {
+            wwi.acceleration[i] = acc;
+        }
+        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)
+    {
+        // acceleration is acc
+        if (fixedIndex == i)
+        {
+            wwi.acceleration[i] = acc;
+        }
+        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;
+
+            // acceleration is acc
+            if (fixedIndex == index)
+            {
+                wwi.acceleration[index] = acc;
+            }
+            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
+
Index: effects/test/wobbly_config.ui
===================================================================
--- effects/test/wobbly_config.ui	(revision 0)
+++ effects/test/wobbly_config.ui	(revision 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/test/wobbly_config.cpp
===================================================================
--- effects/test/wobbly_config.cpp	(revision 0)
+++ effects/test/wobbly_config.cpp	(revision 0)
@@ -0,0 +1,503 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+ Copyright (C) 2007
+
+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 "wobbly_config.h"
+#include "demo_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
+K_PLUGIN_FACTORY_DECLARATION(TestEffectFactory)
+#endif
+
+namespace KWin
+{
+
+WobblyEffectConfig::WobblyEffectConfig(QWidget* parent, const QVariantList& args) :
+KCModule(TestEffectFactory::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();
+}
+
+WobblyEffectConfig::~WobblyEffectConfig()
+{
+}
+
+void WobblyEffectConfig::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 WobblyEffectConfig::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("demo_wobblywindows");
+}
+
+void WobblyEffectConfig::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 WobblyEffectConfig::slotSpRaideur(double value)
+{
+    m_ui.slRaideur->setSliderPosition(value*50);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSlRaideur(int value)
+{
+    m_ui.spRaideur->setValue(value/50.0);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSpAmortissement(double value)
+{
+    m_ui.slAmortissement->setSliderPosition(value*100);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSlAmortissement(int value)
+{
+    m_ui.spAmortissement->setValue(qreal(value)/100.0);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSpMovFactor(double value)
+{
+    m_ui.slMovFactor->setValue(value*100);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSlMovFactor(int value)
+{
+    m_ui.spMovFactor->setValue(qreal(value)/100.0);
+    emit changed(true);
+}
+
+// filters
+
+void WobblyEffectConfig::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 WobblyEffectConfig::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 WobblyEffectConfig::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 WobblyEffectConfig::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 WobblyEffectConfig::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 WobblyEffectConfig::slotSpMinVel(double value)
+{
+    m_ui.slMinVel->setSliderPosition(value*100);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSlMinVel(int value)
+{
+    m_ui.spMinVel->setValue(qreal(value)/100.0);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSpMaxVel(double value)
+{
+    m_ui.slMaxVel->setSliderPosition(value/10);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSlMaxVel(int value)
+{
+    m_ui.spMaxVel->setValue(value*10.0);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSpStopVel(double value)
+{
+    m_ui.slStopVel->setSliderPosition(value*10);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSlStopVel(int value)
+{
+    m_ui.spStopVel->setValue(value/10.0);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSpMinAcc(double value)
+{
+    m_ui.slMinAcc->setSliderPosition(value*100);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSlMinAcc(int value)
+{
+    m_ui.spMinAcc->setValue(value/100.0);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSpMaxAcc(double value)
+{
+    m_ui.slMaxAcc->setSliderPosition(value/10);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSlMaxAcc(int value)
+{
+    m_ui.spMaxAcc->setValue(value*10.0);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSpStopAcc(double value)
+{
+    m_ui.slStopAcc->setSliderPosition(value*10);
+    emit changed(true);
+}
+
+void WobblyEffectConfig::slotSlStopAcc(int value)
+{
+    m_ui.spStopAcc->setValue(value/10.0);
+    emit changed(true);
+}
+
+
+} // namespace
+
+#include "wobbly_config.moc"
Index: effects/test/CMakeLists.txt
===================================================================
--- effects/test/CMakeLists.txt	(revision 777553)
+++ effects/test/CMakeLists.txt	(working copy)
@@ -6,8 +6,18 @@
 endmacro(KWIN4_ADD_EFFECT)
 
 macro(KWIN4_ADD_EFFECT_CONFIG name)
-    kde4_add_plugin(kcm_kwin4_effect_${name} ${ARGN})
-    target_link_libraries(kcm_kwin4_effect_${name} kwineffects ${KDE4_KDEUI_LIBS})
+    set(kwin4_effect_ui ) #empty
+    set(kwin4_effect_src ) #empty
+    foreach(file ${ARGN})
+        if(file MATCHES \\.ui)
+            set(kwin4_effect_ui ${kwin4_effect_ui} ${file})
+        else(file MATCHES \\.ui)
+            set(kwin4_effect_src ${kwin4_effect_src} ${file})
+        endif(file MATCHES \\.ui)
+    endforeach(file)
+    kde4_add_ui_files(kwin4_effect_src ${kwin4_effect_ui})
+    kde4_add_plugin(kcm_kwin4_effect_${name} ${kwin4_effect_src})
+    target_link_libraries(kcm_kwin4_effect_${name} kwineffects ${KDE4_KIO_LIBS} \
                ${KDE4_KDEUI_LIBS})
     install(TARGETS kcm_kwin4_effect_${name} DESTINATION ${PLUGIN_INSTALL_DIR})
 endmacro(KWIN4_ADD_EFFECT_CONFIG)
 
@@ -42,6 +52,7 @@
         demo_liquid.cpp
         demo_showpicture.cpp
         demo_wavywindows.cpp
+        demo_wobblywindows.cpp
         test_fbo.cpp
         )
 
@@ -49,6 +60,7 @@
         demo_liquid.desktop
         demo_showpicture.desktop
         demo_wavywindows.desktop
+        demo_wobblywindows.desktop
         test_fbo.desktop
         DESTINATION ${SERVICES_INSTALL_DIR}/kwin )
 
@@ -56,8 +68,19 @@
         data/liquid.frag
         data/liquid.vert
         DESTINATION  ${DATA_INSTALL_DIR}/kwin )
+
+    SET(kwin4_effect_tests_config_sources ${kwin4_effect_tests_config_sources}
+        wobbly_config.ui
+        wobbly_config.cpp
+        config_test.cpp
+        )
+
+    install( FILES
+        wobbly_config.desktop
+        DESTINATION ${SERVICES_INSTALL_DIR}/kwin )
+
 endif(OPENGL_FOUND)
 
 # add the plugin
 KWIN4_ADD_EFFECT(tests ${kwin4_effect_tests_sources})
-
+KWIN4_ADD_EFFECT_CONFIG(tests ${kwin4_effect_tests_config_sources})
Index: effects/test/demo_wobblywindows.desktop
===================================================================
--- effects/test/demo_wobblywindows.desktop	(revision 0)
+++ effects/test/demo_wobblywindows.desktop	(revision 0)
@@ -0,0 +1,16 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Demo Wobbly Windows
+Icon=kwin-effect-wavywindows
+
+Type=Service
+ServiceTypes=KWin/Effect
+X-KDE-PluginInfo-Author=
+X-KDE-PluginInfo-Email=
+X-KDE-PluginInfo-Name=kwin4_effect_demo_wobblywindows
+X-KDE-PluginInfo-Version=0.1.0
+X-KDE-PluginInfo-Category=Demos
+X-KDE-PluginInfo-Depends=
+X-KDE-PluginInfo-License=GPL
+X-KDE-PluginInfo-EnabledByDefault=false
+X-KDE-Library=kwin4_effect_tests
Index: effects/test/config_test.cpp
===================================================================
--- effects/test/config_test.cpp	(revision 0)
+++ effects/test/config_test.cpp	(revision 0)
@@ -0,0 +1,50 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2007 Bernhard Loos <nhuh.put@web.de>
+Copyright (C) 2007 Christian Nitschkowski <christian.nitschkowski@kdemail.net>
+
+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 <kwinconfig.h>
+
+#ifdef KWIN_HAVE_OPENGL_COMPOSITING
+#include "wobbly_config.h"
+#endif
+
+#include <kwineffects.h>
+
+#include <KPluginLoader>
+#ifndef KDE_USE_FINAL
+K_PLUGIN_FACTORY_DECLARATION(TestEffectFactory)
+#endif
+
+#define NON_GL_PLUGINS
+
+#define GL_PLUGINS \
+    registerPlugin<KWin::WobblyEffectConfig>("demo_wobblywindows"); \
+
+#ifdef KWIN_HAVE_OPENGL_COMPOSITING
+K_PLUGIN_FACTORY_DEFINITION(TestEffectFactory,
+    NON_GL_PLUGINS
+    GL_PLUGINS
+    )
+#else
+K_PLUGIN_FACTORY_DEFINITION(TestEffectFactory,
+    NON_GL_PLUGINS
+    )
+#endif
+K_EXPORT_PLUGIN(TestEffectFactory("kwin"))
Index: effects/test/wobbly_config.desktop
===================================================================
--- effects/test/wobbly_config.desktop	(revision 0)
+++ effects/test/wobbly_config.desktop	(revision 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_demo_wobblywindows
+X-KDE-PluginKeyword=demo_wobblywindows
+
+Name=demo_wobblywindows
+
Index: effects/test/demo_wobblywindows_constants.h
===================================================================
--- effects/test/demo_wobblywindows_constants.h	(revision 0)
+++ effects/test/demo_wobblywindows_constants.h	(revision 0)
@@ -0,0 +1,21 @@
+
+#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 bool SQUAREROOTMASTERACCELERATION = false;
+
+static const qreal MINVELOCITY = 0.5;
+static const qreal MAXVELOCITY = 1000.0;
+static const qreal STOPVELOCITY = 5.0;
+static const qreal MINACCELERATION = 0.1;
+static const qreal MAXACCELERATION = 1000.0;
+static const qreal STOPACCELERATION = 10.0;
+
+static const char* VELOCITYFILTER = "FourRingLinearMean";
+static const char* ACCELERATIONFILTER = "NoFilter";
Index: effects/test/demo_wobblywindows.h
===================================================================
--- effects/test/demo_wobblywindows.h	(revision 0)
+++ effects/test/demo_wobblywindows.h	(revision 0)
@@ -0,0 +1,129 @@
+/*****************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2007
+
+You can Freely distribute this program under the GNU General Public
+License. See the file "COPYING" for the exact licensing terms.
+******************************************************************/
+
+#ifndef DEMO_WOBBLYWINDOWS_H
+#define DEMO_WOBBLYWINDOWS_H
+
+// Include with base class for effects.
+#include <kwineffects.h>
+
+namespace KWin
+{
+
+/**
+ * Demo 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;
+
+            unsigned int width;
+            unsigned int height;
+            unsigned int count;
+
+            int mPickedPointIndex;
+            Pair mPickedPointTranslation;
+            Pair mDestination;
+
+            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;
+
+        bool m_squareRootMasterAcceleration;
+
+        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
+
+#endif // DEMO_WOBBLYWINDOWS_H
Index: effects/test/wobbly_config.h
===================================================================
--- effects/test/wobbly_config.h	(revision 0)
+++ effects/test/wobbly_config.h	(revision 0)
@@ -0,0 +1,93 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+ Copyright (C) 2007
+
+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_wobbly_config.h"
+
+class KActionCollection;
+
+namespace KWin
+{
+
+class WobblyEffectConfig : public KCModule
+{
+    Q_OBJECT
+public:
+    explicit WobblyEffectConfig(QWidget* parent = 0, const QVariantList& args = \
QVariantList()); +    ~WobblyEffectConfig();
+
+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: lib/kwineffects.cpp
===================================================================
--- lib/kwineffects.cpp	(revision 777553)
+++ lib/kwineffects.cpp	(working copy)
@@ -613,6 +613,52 @@
     return ret;
     }
 
+WindowQuadList WindowQuadList::makeRegularGrid( int xSubdivisions, int ySubdivisions \
) const +    {
+    if( empty())
+        return *this;
+    // find the bounding rectangle
+    double left = first().left();
+    double right = first().right();
+    double top = first().top();
+    double bottom = first().bottom();
+    foreach( WindowQuad quad, *this )
+        {
+#ifndef NDEBUG
+        if( quad.isTransformed())
+            kFatal( 1212 ) << "Splitting quads is allowed only in pre-paint calls!" \
; +#endif
+        left = qMin( left, quad.left());
+        right = qMax( right, quad.right());
+        top = qMin( top, quad.top());
+        bottom = qMax( bottom, quad.bottom());
+        }
+
+    double xincrement = (right - left) / xSubdivisions;
+    double yincrement = (bottom - top) / ySubdivisions;
+    WindowQuadList ret;
+    for( double y = top;
+         y < bottom;
+         y += yincrement )
+        {
+        for( double x = left;
+             x < right;
+             x +=  xincrement)
+            {
+            foreach( WindowQuad quad, *this )
+                {
+                if( QRectF( QPointF( quad.left(), quad.top()), QPointF( \
quad.right(), quad.bottom())) +                    .intersects( QRectF( x, y, \
xincrement, yincrement ))) +                    {
+                    ret.append( quad.makeSubQuad( qMax( x, quad.left()), qMax( y, \
quad.top()), +                        qMin( quad.right(), x + xincrement ), qMin( \
quad.bottom(), y + yincrement ))); +                    }
+                }
+            }
+        }
+    return ret;
+    }
+
 void WindowQuadList::makeArrays( float** vertices, float** texcoords ) const
     {
     *vertices = new float[ count() * 4 * 2 ];
Index: lib/kwineffects.h
===================================================================
--- lib/kwineffects.h	(revision 777553)
+++ lib/kwineffects.h	(working copy)
@@ -738,6 +738,7 @@
         WindowQuadList splitAtX( double x ) const;
         WindowQuadList splitAtY( double y ) const;
         WindowQuadList makeGrid( int maxquadsize ) const;
+        WindowQuadList makeRegularGrid( int xSubdivisions, int ySubdivisions ) \
const;  WindowQuadList select( WindowQuadType type ) const;
         WindowQuadList filterOut( WindowQuadType type ) const;
         bool smoothNeeded() const;



_______________________________________________
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