=== modified file 'plugins/place/src/place.cpp'
--- plugins/place/src/place.cpp	2013-03-24 05:51:41 +0000
+++ plugins/place/src/place.cpp	2013-04-08 06:52:21 +0000
@@ -202,7 +202,9 @@
 PlaceScreen::handleEvent (XEvent *event)
 {
     if (event->type == ConfigureNotify &&
-	event->xconfigure.window == screen->root ())
+	event->xconfigure.window == screen->root () &&
+	(event->xconfigure.width != screen->width () ||
+	 event->xconfigure.height != screen->height ()))
     {
 	mPrevSize.setWidth (screen->width ());
 	mPrevSize.setHeight (screen->height ());

=== modified file 'plugins/place/src/screen-size-change/src/screen-size-change.cpp'
--- plugins/place/src/screen-size-change/src/screen-size-change.cpp	2012-07-30 10:01:45 +0000
+++ plugins/place/src/screen-size-change/src/screen-size-change.cpp	2013-04-08 06:52:21 +0000
@@ -40,8 +40,6 @@
     int            vpX, vpY;
     compiz::window::Geometry g, vpRelRect;
     int		   pivotX, pivotY;
-    int		   curVpOffsetX = getViewport ().x () * newSize.width ();
-    int		   curVpOffsetY = getViewport ().y () * newSize.height ();
 
     g = getGeometry ();
     compiz::window::Geometry og (g);
@@ -59,24 +57,14 @@
     if (pivotY < 0)
 	vpY -= 1;
 
-    /* if window's target vp is to the left of the leftmost viewport on that
-       row, assign its target vp column as 0 (-s->x rel. to current vp) */
-    if (getViewport ().x () + vpX < 0)
-	vpX = -getViewport ().x ();
-
-    /* if window's target vp is above the topmost viewport on that column,
-       assign its target vp row as 0 (-s->y rel. to current vp) */
-    if (getViewport ().y () + vpY < 0)
-	vpY = -getViewport ().y ();
-
     unsigned int mask = mSaver.pop (vpRelRect, CHANGE_X | CHANGE_Y |
 					       CHANGE_WIDTH | CHANGE_HEIGHT);
 
     if (mask)
     {
 	/* set position/size to saved original rectangle */
-	g.applyChange (compiz::window::Geometry (vpRelRect.x () + vpX * newSize.width (),
-						 vpRelRect.y () + vpY * newSize.height (),
+	g.applyChange (compiz::window::Geometry (vpRelRect.x (),
+						 vpRelRect.y (),
 						 vpRelRect.width (),
 						 vpRelRect.height (),
 						 vpRelRect.border ()), mask);
@@ -90,42 +78,24 @@
 	vpRelRect.setWidth (g.width ());
 	vpRelRect.setHeight (g.height ());
 
-	g.setPos (g.pos ());
-
-	int shiftX = vpX * (newSize.width () - oldSize.width ()),
-	    shiftY = vpY * (newSize.width () - oldSize.height ());
+	g = vpRelRect;
 
 	/* if coords. relative to viewport are outside new viewport area,
 	   shift window left/up so that it falls inside */
-	if (vpRelRect.x () >= newSize.width ())
-	    shiftX -= vpRelRect.x () - (newSize.width () - 1);
-	if (vpRelRect.y () >= newSize.height ())
-	    shiftY -= vpRelRect.y () - (newSize.height () - 1);
-
-	if (shiftX)
-	    g.setX (g.x () + shiftX);
-
-	if (shiftY)
-	    g.setY (g.y () + shiftY);
+	if (vpRelRect.x () + vpRelRect.width() >= newSize.width ())
+	    g.setX (g.x () - (vpRelRect.x () + vpRelRect.width () - newSize.width ()));
+	if (vpRelRect.y () + vpRelRect.height() >= newSize.height ())
+	    g.setY (g.y () - (vpRelRect.y () + vpRelRect.width () - newSize.height ()));
 
 	g.setWidth (vpRelRect.width ());
 	g.setHeight (vpRelRect.height ());
     }
 
-    /* Handle non-(0,0) current viewport by shifting by curVpOffsetX,Y,
-       and bring window to (0,0) by shifting by minus its vp offset */
-
-    g.setX (g.x () + curVpOffsetX - (getViewport ().x () + vpX) * newSize.width ());
-    g.setY (g.y () + curVpOffsetY - (getViewport ().y () + vpY) * newSize.height ());
-
     unsigned int flags = 0;
     const CompRect &workArea = getWorkarea (g);
 
     compiz::place::clampGeometryToWorkArea (g, workArea, getExtents (), flags, newSize);
 
-    g.setX (g.x () - curVpOffsetX + (getViewport ().x () + vpX) * newSize.width ());
-    g.setY (g.y () - curVpOffsetY + (getViewport ().y () + vpY) * newSize.height ());
-
     if (!mask)
     {
 	/* save window geometry (relative to viewport) so that it
@@ -151,6 +121,9 @@
 	mSaver.push (vpRelRect, remaining);
     }
 
+    g.setX (g.x () + vpX * newSize.width ());
+    g.setY (g.y () + vpY * newSize.height ());
+
     /* for maximized/fullscreen windows, update saved pos/size XXX,
      * also pull in the old code to handle maximized windows which
      * currently can't be implemented yet */

=== modified file 'plugins/place/src/screen-size-change/tests/screen-size-change/src/test-place-screen-size-change.cpp'
--- plugins/place/src/screen-size-change/tests/screen-size-change/src/test-place-screen-size-change.cpp	2012-07-26 09:10:09 +0000
+++ plugins/place/src/screen-size-change/tests/screen-size-change/src/test-place-screen-size-change.cpp	2013-04-08 06:52:21 +0000
@@ -57,6 +57,9 @@
 			 unsigned int bottom);
 
 	void setGeometry (const compiz::window::Geometry &g);
+	compiz::window::Geometry sizeAdjustTest (const CompSize &oldSize,
+						 const CompSize &newSize,
+						 CompRect &workArea);
 
     private:
 
@@ -162,21 +165,34 @@
     workArea.setBottom (workArea.bottom () - 24);
 }
 
+compiz::window::Geometry
+MockScreenSizeChangeObject::sizeAdjustTest (const CompSize &oldSize,
+					    const CompSize &newSize,
+					    CompRect &workArea)
+{
+    /* Reserve top, bottom and left parts of the screen for
+     * fake "24px" panels */
+    reserveStruts (workArea);
+
+    setWorkArea (workArea);
+
+    compiz::window::Geometry g = adjustForSize (oldSize, newSize);
+
+    return g;
+}
+
+
 TEST_F(CompPlaceScreenSizeChangeTestScreenSizeChange, TestScreenSizeChange)
 {
     CompSize		     current, old;
     compiz::window::Geometry g (200, 250, 300, 400, 0);
+    compiz::window::Geometry expected;
 
     MockScreenSizeChangeObject ms (g);
 
     current = CompSize (1280, 800);
 
-    /* Reserve top, bottom and left parts of the screen for
-     * fake "24px" panels */
-    CompRect workArea = CompRect (0, 0, current.width (), current.height ());
-    reserveStruts (workArea);
-
-    ms.setWorkArea (workArea);
+    CompRect workArea;
 
     /* First test that changing the screen size
      * to something smaller here doesn't cause our
@@ -184,114 +200,100 @@
 
     old = current;
     current = CompSize (1024, 768);
-
     workArea = CompRect (0, 0, current.width (), current.height ());
-    reserveStruts (workArea);
-
-    ms.setWorkArea (workArea);
-
-    g = ms.adjustForSize (old, current);
-
-    EXPECT_EQ (g, compiz::window::Geometry (200, 250, 300, 400, 0));
+
+    expected = compiz::window::Geometry (200, 250, 300, 400, 0);
+
+    g = ms.sizeAdjustTest (old, current, workArea);
+
+    EXPECT_EQ (expected, g);
 
     /* Making the screen size bigger with no
      * saved geometry should cause the window not to move */
-
     old = current;
     current = CompSize (2048, 768);
-
     workArea = CompRect (0, 0, current.width (), current.height ());
-    reserveStruts (workArea);
-
-    ms.setWorkArea (workArea);
-
-    g = ms.adjustForSize (old, current);
-
-    EXPECT_EQ (g, compiz::window::Geometry (200, 250, 300, 400, 0));
+
+    g = ms.sizeAdjustTest (old, current, workArea);
+
+    EXPECT_EQ (expected, g);
 
     /* Move the window to the other "monitor" */
-
     ms.setGeometry (compiz::window::Geometry (1025, 250, 300, 400, 0));
 
-    old = current;
-
     /* Unplug a "monitor" */
+    old = current;
     current = CompSize (1024, 768);
-
     workArea = CompRect (0, 0, current.width (), current.height ());
-    reserveStruts (workArea);
-
-    ms.setWorkArea (workArea);
-
-    g = ms.adjustForSize (old, current);
-
-    EXPECT_EQ (g, compiz::window::Geometry (724, 250, 300, 400, 0));
-
-    old = current;
+
+    expected = compiz::window::Geometry (724, 250, 300, 400, 0);
+
+    g = ms.sizeAdjustTest (old, current, workArea);
+
+    EXPECT_EQ (expected, g);
 
     /* Re-plug the monitor - window should go back
      * to the same position */
+    old = current;
     current = CompSize (2048, 768);
-
     workArea = CompRect (0, 0, current.width (), current.height ());
-    reserveStruts (workArea);
-
-    ms.setWorkArea (workArea);
-
-    g = ms.adjustForSize (old, current);
-
-    EXPECT_EQ (g, compiz::window::Geometry (1025, 250, 300, 400, 0));
-
-    old = current;
+
+    expected = compiz::window::Geometry (1025, 250, 300, 400, 0);
+
+    g = ms.sizeAdjustTest (old, current, workArea);
+
+    EXPECT_EQ (expected, g);
 
     /* Plug 2 monitors downwards, no change */
+    old = current;
     current = CompSize (2048, 1536);
-
     workArea = CompRect (0, 0, current.width (), current.height ());
-    reserveStruts (workArea);
-
-    ms.setWorkArea (workArea);
-
-    g = ms.adjustForSize (old, current);
-
-    EXPECT_EQ (g, compiz::window::Geometry (1025, 250, 300, 400, 0));
+
+    g = ms.sizeAdjustTest (old, current, workArea);
+
+    EXPECT_EQ (expected, g);
 
     /* Move the window to the bottom "monitor" */
-
     ms.setGeometry (compiz::window::Geometry (1025, 791, 300, 400, 0));
 
-    old = current;
-
     /* Unplug bottom "monitor" */
+    old = current;
     current = CompSize (2048, 768);
-
     workArea = CompRect (0, 0, current.width (), current.height ());
-    reserveStruts (workArea);
-
-    ms.setWorkArea (workArea);
-
-    g = ms.adjustForSize (old, current);
-
-    EXPECT_EQ (g, compiz::window::Geometry (1025, 344, 300, 400, 0));
-
-    old = current;
+
+    expected = compiz::window::Geometry (1025, 344, 300, 400, 0);
+
+    g = ms.sizeAdjustTest (old, current, workArea);
+
+    EXPECT_EQ (expected, g);
 
     /* Re-plug bottom "monitor" */
+    old = current;
     current = CompSize (2048, 1356);
-
     workArea = CompRect (0, 0, current.width (), current.height ());
-    reserveStruts (workArea);
-
-    ms.setWorkArea (workArea);
-
-    g = ms.adjustForSize (old, current);
-
-    EXPECT_EQ (g, compiz::window::Geometry (1025, 791, 300, 400, 0));
+
+    expected = compiz::window::Geometry (1025, 791, 300, 400, 0);
+
+    g = ms.sizeAdjustTest (old, current, workArea);
+
+    EXPECT_EQ (expected, g);
+
+}
+
+TEST_F(CompPlaceScreenSizeChangeTestScreenSizeChange, TestScreenChangeWindowsOnSecondViewport)
+{
+    CompSize		     current, old;
+    compiz::window::Geometry g (1025, 791, 300, 400, 0);
+    compiz::window::Geometry expected;
+
+    MockScreenSizeChangeObject ms (g);
+
+    current = CompSize (2048, 1356);
+
+    CompRect workArea;
 
     /* Move the entire window right a viewport */
-
     g.setPos (g.pos () + CompPoint (current.width (), 0));
-
     ms.setGeometry (g);
 
     /* Now change the screen resolution again - the window should
@@ -301,14 +303,115 @@
     /* Unplug a "monitor" */
     old = current;
     current = CompSize (1024, 1356);
-
-    workArea = CompRect (0, 0, current.width (), current.height ());
-    reserveStruts (workArea);
-
-    ms.setWorkArea (workArea);
-
-    g = ms.adjustForSize (old, current);
-
-    EXPECT_EQ (g, compiz::window::Geometry (current.width () + 724, 791, 300, 400, 0));
-}
-
+    workArea = CompRect (0, 0, current.width (), current.height ());
+
+    expected = compiz::window::Geometry (current.width () + 724, 791, 300, 400, 0);
+
+    g = ms.sizeAdjustTest (old, current, workArea);
+
+    EXPECT_EQ (expected, g);
+
+    /* Replug the monitor, make sure that the geometry is restored */
+    old = current;
+    current = CompSize (2048, 1356);
+    workArea = CompRect (0, 0, current.width (), current.height ());
+
+    expected = compiz::window::Geometry (current.width () + 1025, 791, 300, 400, 0);
+
+    g = ms.sizeAdjustTest (old, current, workArea);
+
+    EXPECT_EQ (expected, g);
+
+    /* Replug the monitor and move the window to where it fits on the first
+     * monitor on the second viewport, then make sure it doesn't move */
+    old = CompSize (2048, 1356);
+    current = CompSize (1024, 1356);
+    workArea = CompRect (0, 0, current.width (), current.height ());
+
+    g.setPos (CompPoint (old.width () + 25, 791));
+    ms.setGeometry (g);
+    /* clear the saved geometry */
+    ms.unset();
+
+    expected = compiz::window::Geometry (current.width () + 25, 791, 300, 400, 0);
+
+    g = ms.sizeAdjustTest (old, current, workArea);
+
+    EXPECT_EQ (expected, g);
+
+    old = current;
+    current = CompSize (2048, 1356);
+    workArea = CompRect (0, 0, current.width (), current.height ());
+
+    expected = compiz::window::Geometry (current.width () + 25, 791, 300, 400, 0);
+
+    g = ms.sizeAdjustTest (old, current, workArea);
+
+    EXPECT_EQ (expected, g);
+}
+
+TEST_F(CompPlaceScreenSizeChangeTestScreenSizeChange, TestScreenChangeWindowsOnPreviousViewport)
+{
+    CompSize		     current, old;
+    compiz::window::Geometry g (0, 0, 300, 400, 0);
+    compiz::window::Geometry expected;
+
+    MockScreenSizeChangeObject ms (g);
+
+    current = CompSize (2048, 1356);
+
+    CompRect workArea;
+
+    /* Deal with the case where the position is negative, which means
+     * it's actually wrapped around to the rightmost viewport
+     */
+    g.setPos (CompPoint (-300, 200));
+    ms.setGeometry (g);
+
+    expected = g;
+
+    /* Unplug the right "monitor" */
+    old = current;
+    current = CompSize (1024, 1356);
+    workArea = CompRect (0, 0, current.width (), current.height ());
+
+    g = ms.sizeAdjustTest (old, current, workArea);
+
+    EXPECT_EQ (expected, g);
+
+    /* Re-plug the right "monitor" */
+    old = current;
+    current = CompSize (2048, 1356);
+    workArea = CompRect (0, 0, current.width (), current.height ());
+
+    g = ms.sizeAdjustTest (old, current, workArea);
+
+    EXPECT_EQ (expected, g);
+
+    /* Move the window to the left monitor, verify that it survives an
+     * unplug/plug cycle
+     */
+    g.setPos (CompPoint (-1324, 200));
+    ms.setGeometry (g);
+
+    old = current;
+    current = CompSize (1024, 1356);
+    workArea = CompRect (0, 0, current.width (), current.height ());
+
+    expected = compiz::window::Geometry (-300, 200, 300, 400, 0);
+
+    g = ms.sizeAdjustTest (old, current, workArea);
+
+    EXPECT_EQ (expected, g);
+
+    old = current;
+    current = CompSize (2048, 1356);
+    workArea = CompRect (0, 0, current.width (), current.height ());
+
+    expected = compiz::window::Geometry (-1324, 200, 300, 400, 0);
+
+    g = ms.sizeAdjustTest (old, current, workArea);
+
+    EXPECT_EQ (expected, g);
+
+}

