Index: wobblywindows.h
===================================================================
--- wobblywindows.h	(revision 890790)
+++ wobblywindows.h	(working copy)
@@ -90,6 +90,14 @@
 
             // for closing
             QRectF closeRect;
+
+            enum Edges { NONE=0, TOP=1, RIGHT=2, BOTTOM=4, LEFT=8,
+                         TOP_LEFT = TOP|LEFT,
+                         TOP_RIGHT = TOP|RIGHT,
+                         BOTTOM_LEFT = BOTTOM|LEFT,
+                         BOTTOM_RIGHT = BOTTOM|RIGHT,
+                         ALL = TOP|RIGHT|BOTTOM|LEFT  };
+            unsigned edges;
         };
 
         QHash< const EffectWindow*,  WindowWobblyInfos > windows;
@@ -120,6 +128,7 @@
         bool m_moveWobble; // Expands m_moveEffectEnabled
         bool m_resizeWobble;
 
+        void firstUserMovedResized(EffectWindow* w);
         void initWobblyInfo(WindowWobblyInfos& wwi, QRect geometry) const;
         void freeWobblyInfo(WindowWobblyInfos& wwi) const;
         void wobblyOpenInit(WindowWobblyInfos& wwi) const;
Index: wobblywindows.cpp
===================================================================
--- wobblywindows.cpp	(revision 890790)
+++ wobblywindows.cpp	(working copy)
@@ -365,56 +365,29 @@
 
 void WobblyWindowsEffect::windowUserMovedResized(EffectWindow* w, bool first, bool last)
 {
-    if (m_moveEffectEnabled && first && !w->isSpecialWindow() &&
+    if (m_moveEffectEnabled && !w->isSpecialWindow() &&
        ((w->isUserMove() && m_moveWobble) || (w->isUserResize() && m_resizeWobble)))
     {
-        if (!windows.contains(w))
-        {
-            WindowWobblyInfos new_wwi;
-            initWobblyInfo(new_wwi, w->geometry());
-            windows[w] = new_wwi;
-        }
+        if (first)
+            firstUserMovedResized(w);
 
+        // maintain flags indicating that each window edge is unstuck from the screen edge
+        const QRectF& window_rect = w->geometry();
         WindowWobblyInfos& wwi = windows[w];
-        wwi.status = Moving;
-        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()};
-        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(1212) << "Picked index == " << pickedPointIndex << " with (" << cursorPos().x() << "," << cursorPos().y() << ")";
-            pickedPointIndex = 0;
-        }
-        else if (static_cast<unsigned int>(pickedPointIndex) > wwi.count - 1)
-        {
-            kDebug(1212) << "Picked index == " << pickedPointIndex << " with (" << cursorPos().x() << "," << cursorPos().y() << ")";
-            pickedPointIndex = wwi.count - 1;
-        }
-#if defined VERBOSE_MODE
-        kDebug(1212) << "Original Picked point -- x : " << picked.x << " - y : " << picked.y;
-#endif
-        wwi.constraint[pickedPointIndex] = true;
-
-        if (w->isUserResize())
-        {
-            if (picked.x > rect.center().x())
-                if (picked.y > rect.center().y())
-                    // picked somewhere in the bottom right, so constrain the top left corner too
-                    wwi.locked[0] = wwi.constraint[0] = true;
-                else
-                    wwi.locked[wwi.count-wwi.width] = wwi.constraint[wwi.count-wwi.width] = true;
-            else
-                if (picked.y > rect.center().y())
-                    wwi.locked[wwi.width-1] = wwi.constraint[wwi.width-1] = true;
-                else
-                    wwi.locked[wwi.count-1] = wwi.constraint[wwi.count-1] = true;
-        }
+        QRect snap_rect_1 = effects->clientArea( MaximizeArea, -1, 0 );
+        QRect snap_rect_2 = effects->clientArea( MaximizeFullArea, -1, 0 );
+        if (window_rect.x() != snap_rect_1.x() && 
+            window_rect.x() != snap_rect_2.x() )
+            wwi.edges |= WindowWobblyInfos::LEFT;
+        if (window_rect.y() != snap_rect_1.y() && 
+            window_rect.y() != snap_rect_2.y() )
+            wwi.edges |= WindowWobblyInfos::TOP;
+        if (window_rect.right() != snap_rect_1.right()+1 && 
+            window_rect.right() != snap_rect_2.right()+1 )
+            wwi.edges |= WindowWobblyInfos::RIGHT;
+        if (window_rect.bottom() != snap_rect_1.bottom()+1 &&
+            window_rect.bottom() != snap_rect_2.bottom()+1 )
+            wwi.edges |= WindowWobblyInfos::BOTTOM;
     }
     else if (m_moveEffectEnabled && last)
     {
@@ -426,6 +399,59 @@
     }
 }
 
+void WobblyWindowsEffect::firstUserMovedResized(EffectWindow* w)
+{
+    if (!windows.contains(w))
+    {
+        WindowWobblyInfos new_wwi;
+        initWobblyInfo(new_wwi, w->geometry());
+        windows[w] = new_wwi;
+    }
+
+    WindowWobblyInfos& wwi = windows[w];
+    wwi.status = Moving;
+    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()};
+    int indx = int(0.5 + (picked.x - rect.x()) / x_increment );
+    int indy = int(0.5 + (picked.y - rect.y()) / y_increment );
+    int pickedPointIndex = indy*wwi.width + indx;
+    if (pickedPointIndex < 0)
+    {
+        kDebug(1212) << "Picked index == " << pickedPointIndex << " with (" << cursorPos().x() << "," << cursorPos().y() << ")";
+        pickedPointIndex = 0;
+    }
+    else if (static_cast<unsigned int>(pickedPointIndex) > wwi.count - 1)
+    {
+        kDebug(1212) << "Picked index == " << pickedPointIndex << " with (" << cursorPos().x() << "," << cursorPos().y() << ")";
+        pickedPointIndex = wwi.count - 1;
+    }
+#if defined VERBOSE_MODE
+    kDebug(1212) << "Original Picked point -- x : " << picked.x << " - y : " << picked.y;
+#endif
+    wwi.constraint[pickedPointIndex] = true;
+
+    if (w->isUserResize())
+    {
+        if (picked.x > rect.center().x())
+            if (picked.y > rect.center().y())
+                // picked somewhere in the bottom right, so constrain the top left corner too
+                wwi.locked[0] = wwi.constraint[0] = true;
+            else
+                wwi.locked[wwi.count-wwi.width] = wwi.constraint[wwi.count-wwi.width] = true;
+        else
+            if (picked.y > rect.center().y())
+                wwi.locked[wwi.width-1] = wwi.constraint[wwi.width-1] = true;
+            else
+                wwi.locked[wwi.count-1] = wwi.constraint[wwi.count-1] = true;
+
+        wwi.edges = WindowWobblyInfos::NONE;
+    }
+}
+
 void WobblyWindowsEffect::windowAdded(EffectWindow* w)
 {
     if (m_openEffectEnabled)
@@ -534,6 +560,7 @@
     wwi.bezierSurface = new Pair[wwi.bezierCount];
 
     wwi.status = Moving;
+    wwi.edges = WindowWobblyInfos::ALL;
 
     qreal x = geometry.x(), y = geometry.y();
     qreal width = geometry.width(), height = geometry.height();
@@ -756,7 +783,7 @@
 
     // top-left
 
-    if (wwi.constraint[0])
+    if (wwi.constraint[0] || !(wwi.edges&WindowWobblyInfos::TOP_LEFT))
     {
         Pair window_pos = wwi.origin[0];
         Pair current_pos = wwi.position[0];
@@ -781,7 +808,7 @@
 
     // top-right
 
-    if (wwi.constraint[wwi.width-1])
+    if (wwi.constraint[wwi.width-1] || !(wwi.edges&WindowWobblyInfos::TOP_RIGHT))
     {
         Pair window_pos = wwi.origin[wwi.width-1];
         Pair current_pos = wwi.position[wwi.width-1];
@@ -806,7 +833,7 @@
 
     // bottom-left
 
-    if (wwi.constraint[wwi.width*(wwi.height-1)])
+    if (wwi.constraint[wwi.width*(wwi.height-1)] || !(wwi.edges&WindowWobblyInfos::BOTTOM_LEFT))
     {
         Pair window_pos = wwi.origin[wwi.width*(wwi.height-1)];
         Pair current_pos = wwi.position[wwi.width*(wwi.height-1)];
@@ -831,7 +858,7 @@
 
     // bottom-right
 
-    if (wwi.constraint[wwi.count-1])
+    if (wwi.constraint[wwi.count-1] || !(wwi.edges&WindowWobblyInfos::BOTTOM_RIGHT))
     {
         Pair window_pos = wwi.origin[wwi.count-1];
         Pair current_pos = wwi.position[wwi.count-1];
@@ -860,7 +887,7 @@
     // top border
     for (unsigned int i=1; i<wwi.width-1; ++i)
     {
-        if (wwi.constraint[i])
+        if (wwi.constraint[i] || !(wwi.edges&WindowWobblyInfos::TOP))
         {
             Pair window_pos = wwi.origin[i];
             Pair current_pos = wwi.position[i];
@@ -888,7 +915,7 @@
     // bottom border
     for (unsigned int i=wwi.width*(wwi.height-1)+1; i<wwi.count-1; ++i)
     {
-        if (wwi.constraint[i])
+        if (wwi.constraint[i] || !(wwi.edges&WindowWobblyInfos::BOTTOM))
         {
             Pair window_pos = wwi.origin[i];
             Pair current_pos = wwi.position[i];
@@ -916,7 +943,7 @@
     // left border
     for (unsigned int i=wwi.width; i<wwi.width*(wwi.height-1); i+=wwi.width)
     {
-        if (wwi.constraint[i])
+        if (wwi.constraint[i] || !(wwi.edges&WindowWobblyInfos::LEFT))
         {
             Pair window_pos = wwi.origin[i];
             Pair current_pos = wwi.position[i];
@@ -944,7 +971,7 @@
     // right border
     for (unsigned int i=2*wwi.width-1; i<wwi.count-1; i+=wwi.width)
     {
-        if (wwi.constraint[i])
+        if (wwi.constraint[i] || !(wwi.edges&WindowWobblyInfos::RIGHT))
         {
             Pair window_pos = wwi.origin[i];
             Pair current_pos = wwi.position[i];
@@ -1083,6 +1110,20 @@
 #endif
     }
 
+    // If window edges are not yet unstuck from screen edges...
+    if (!(wwi.edges&WindowWobblyInfos::LEFT))
+        for(unsigned i=0; i<wwi.count; i+=wwi.width)                                                   
+            wwi.position[i] = wwi.origin[i];
+    if (!(wwi.edges&WindowWobblyInfos::RIGHT))
+        for(unsigned i=wwi.width-1; i<wwi.count; i+=wwi.width)
+            wwi.position[i] = wwi.origin[i];
+    if (!(wwi.edges&WindowWobblyInfos::TOP))
+        for(unsigned i=0; i<wwi.width; i+=1)
+            wwi.position[i] = wwi.origin[i];
+    if (!(wwi.edges&WindowWobblyInfos::BOTTOM))
+        for(unsigned i=wwi.count-wwi.width; i<wwi.count; i+=1)
+            wwi.position[i] = wwi.origin[i];
+
 #if defined VERBOSE_MODE
 #   if defined COMPUTE_STATS
         kDebug(1212) << "Acceleration bounds (" << accBound.x << ", " << accBound.y << ")";

