diff -uNr metacity-2.5.2/src/window.c metacity-2.5.2-multimonitor/src/window.c
--- metacity-2.5.2/src/window.c	2003-06-05 16:39:48.000000000 +0200
+++ metacity-2.5.2-multimonitor/src/window.c	2003-06-05 16:39:04.000000000 +0200
@@ -492,6 +492,8 @@
 
   window->cached_group = NULL;
 
+  window->shaken_loose = FALSE;
+
   window->using_net_wm_name = FALSE;
   window->using_net_wm_icon_name = FALSE;
 
@@ -5341,7 +5343,6 @@
 
   if (window->maximized)
     {
-      window->has_move_func = FALSE;
       window->has_resize_func = FALSE;
     }
 
@@ -5690,6 +5691,70 @@
   new_x = window->display->grab_current_window_pos.x + dx;
   new_y = window->display->grab_current_window_pos.y + dy;
 
+#define SHAKE_LOOSE_THRESHOLD 50
+
+  if (window->maximized)
+    {
+      if (ABS (dy) >= SHAKE_LOOSE_THRESHOLD)
+        {
+          window->shaken_loose = TRUE;
+
+          if (window->frame)
+            {
+              window->saved_rect.x = x - (window->frame->child_x +
+                                          window->frame->right_width +
+                                          window->saved_rect.width) / 2;
+              window->saved_rect.y = y - window->frame->child_y / 2;
+            }
+
+         meta_window_unmaximize (window);
+
+         return;
+       }
+    }
+
+  if (window->shaken_loose || window->maximized)
+    {
+      const MetaXineramaScreenInfo *wxinerama;
+      int monitor;
+
+      wxinerama = meta_screen_get_xinerama_for_window (window->screen, window);
+
+      for (monitor = 0; monitor < window->screen->n_xinerama_infos; monitor++)
+        {
+          if (x >= window->screen->xinerama_infos[monitor].x_origin &&
+              x < window->screen->xinerama_infos[monitor].x_origin + 
+                  window->screen->xinerama_infos[monitor].width &&
+              y >= window->screen->xinerama_infos[monitor].y_origin &&
+              y < window->screen->xinerama_infos[monitor].y_origin +
+                  SHAKE_LOOSE_THRESHOLD)
+            {
+              if (wxinerama->number != monitor)
+                {
+                  window->saved_rect.x = window->screen->xinerama_infos[monitor].x_origin;
+                  window->saved_rect.y = window->screen->xinerama_infos[monitor].y_origin;
+
+                  if (window->frame) 
+                    {
+                      window->saved_rect.x += window->frame->child_x;
+                      window->saved_rect.y += window->frame->child_y;
+                    } 
+
+                  meta_window_unmaximize (window);
+                }
+
+              window->shaken_loose = FALSE;
+
+              meta_window_maximize (window);
+
+              return;
+            }
+        }
+
+      if (window->maximized)
+        return;
+    }
+
   if (mask & ShiftMask)
     {
       /* snap to edges */
@@ -5925,6 +5990,9 @@
             update_resize (window, event->xbutton.x_root, event->xbutton.y_root);
         }
 
+      // reset shaken loose state on end grab op
+      window->shaken_loose = FALSE;
+
       meta_display_end_grab_op (window->display, event->xbutton.time);
       break;    
 
diff -uNr metacity-2.5.2/src/window.h metacity-2.5.2-multimonitor/src/window.h
--- metacity-2.5.2/src/window.h	2003-06-05 16:39:48.000000000 +0200
+++ metacity-2.5.2-multimonitor/src/window.h	2003-06-05 16:39:04.000000000 +0200
@@ -285,6 +285,9 @@
 
   /* maintained by group.c */
   MetaGroup *cached_group;
+
+  /* Whether we've been shaken loose */
+  guint shaken_loose : 1;
 };
 
 #define META_WINDOW_ALLOWS_MOVE(w)     ((w)->has_move_func)
