diff -ur metacity-2.4.34/src/window.c metacity-2.4.34-multimonitor/src/window.c
--- metacity-2.4.34/src/window.c	2003-02-05 04:46:07.000000000 +0100
+++ metacity-2.4.34-multimonitor/src/window.c	2003-02-06 15:40:15.000000000 +0100
@@ -462,6 +462,8 @@
 
   window->cached_group = NULL;
 
+  window->shaken_loose = FALSE;
+
   window->using_net_wm_name = FALSE;
   window->using_net_wm_icon_name = FALSE;
   
@@ -6201,6 +6203,7 @@
   int dx, dy;
   int new_x, new_y;
   int move_threshold;
+  int shake_loose_threshold;
 
   window->display->grab_latest_motion_x = x;
   window->display->grab_latest_motion_y = y;
@@ -6211,13 +6214,121 @@
   new_x = window->display->grab_current_window_pos.x + dx;
   new_y = window->display->grab_current_window_pos.y + dy;
 
+  shake_loose_threshold = 50;
+
+  if (window->maximized)
+  {
+  	if (ABS (dy) >= shake_loose_threshold)
+  	{
+          meta_topic (META_DEBUG_WINDOW_OPS,
+                      "Unmaximizing %s (shake loose)\n", window->desc);
+          window->maximized = FALSE;
+          window->shaken_loose = TRUE;
+          meta_window_move_resize (window,
+                                   TRUE,
+                                   new_x,
+                                   new_y,
+                                   window->saved_rect.width,
+                                   window->saved_rect.height);
+          recalc_window_features (window);
+          set_net_wm_state (window);
+  	}
+  }
+
+  if (window->shaken_loose || window->maximized)
+  {
+    int new_w, new_h;
+    int monitor;
+    MetaRectangle area;
+    
+    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)
+      {
+        MetaRectangle space_area;
+        GList *tmp;
+        
+        int left_strut;
+        int right_strut;
+        int top_strut;
+        int bottom_strut;  
+      
+        left_strut = 0;
+        right_strut = 0;
+        top_strut = 0;
+        bottom_strut = 0;
+      
+        tmp = meta_window_get_workspaces (window);
+  
+        while (tmp != NULL)
+          {
+            meta_workspace_get_work_area (tmp->data, &space_area);
+      
+            left_strut = MAX (left_strut, space_area.x);
+            right_strut = MAX (right_strut,
+                               (window->screen->width - space_area.x - space_area.width));
+            top_strut = MAX (top_strut, space_area.y);
+            bottom_strut = MAX (bottom_strut,
+                                (window->screen->height - space_area.y - space_area.height));      
+            
+            tmp = tmp->next;
+          }
+  
+        left_strut += window->screen->xinerama_infos[monitor].x_origin;
+        right_strut += window->screen->width - window->screen->xinerama_infos[monitor].width - window->screen->xinerama_infos[monitor].x_origin;
+        top_strut += window->screen->xinerama_infos[monitor].y_origin;
+        bottom_strut += window->screen->height - window->screen->xinerama_infos[monitor].height - window->screen->xinerama_infos[monitor].y_origin;
+      
+        area.x = left_strut;
+        area.y = top_strut;
+        area.width = window->screen->width - left_strut - right_strut;
+        area.height = window->screen->height - top_strut - bottom_strut;
+        
+        new_x = area.x + window->frame->child_x;
+        new_y = area.y + window->frame->child_y;
+        new_w = area.width - window->frame->child_x - window->frame->right_width;
+        new_h = area.height - window->frame->child_y - window->frame->bottom_height;
+
+	/*if (window->maximized &&
+            (new_x != window->display->grab_current_window_pos.x
+            || new_y != window->display->grab_current_window_pos.y))*/
+        {
+            window->maximized = FALSE;
+        }
+          
+        if (!window->maximized)
+        {
+          meta_topic (META_DEBUG_WINDOW_OPS,
+                      "Maximizing %s (snap in)\n", window->desc);
+          window->shaken_loose = FALSE;
+          /*window->display->grab_current_root_x = x;
+          window->display->grab_current_root_y = y;
+          window->display->grab_current_window_pos.x = new_x;
+          window->display->grab_current_window_pos.y = new_y;*/
+          meta_window_move_resize (window, TRUE, new_x, new_y, new_w, new_h);
+          window->maximized = TRUE;
+          recalc_window_features (window);
+          set_net_wm_state (window);
+        }
+        
+        return;
+      }
+    }
+    
+    if (window->maximized)
+      return;
+  }
+
   if (mask & ShiftMask)
     {
       /* snap to edges */
       new_x = meta_window_find_nearest_vertical_edge (window, new_x);
       new_y = meta_window_find_nearest_horizontal_edge (window, new_y);
     }
-
+    
   /* Force a move regardless of time if a certain delta is exceeded,
    * so we don't get too out of sync with reality when dropping frames
    */
@@ -6474,6 +6585,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;    
 
@@ -6581,26 +6695,11 @@
   int top_strut;
   int bottom_strut;  
 
-  if (for_current_xinerama)
-    {
-      const MetaXineramaScreenInfo *xinerama;
-      
-      xinerama = meta_screen_get_xinerama_for_window (window->screen,
-                                                      window);
-      
-      left_strut = xinerama->x_origin;
-      right_strut = window->screen->width - xinerama->width - xinerama->x_origin;
-      top_strut = xinerama->y_origin;
-      bottom_strut = window->screen->height - xinerama->height - xinerama->y_origin;
-    }
-  else
-    {
-      left_strut = 0;
-      right_strut = 0;
-      top_strut = 0;
-      bottom_strut = 0;
-    }
-      
+  left_strut = 0;
+  right_strut = 0;
+  top_strut = 0;
+  bottom_strut = 0;
+
   tmp = meta_window_get_workspaces (window);
   
   while (tmp != NULL)
@@ -6617,6 +6716,19 @@
       tmp = tmp->next;
     }
   
+  if (for_current_xinerama)
+    {
+      const MetaXineramaScreenInfo *xinerama;
+      
+      xinerama = meta_screen_get_xinerama_for_window (window->screen,
+                                                      window);
+      
+      left_strut += xinerama->x_origin;
+      right_strut += window->screen->width - xinerama->width - xinerama->x_origin;
+      top_strut += xinerama->y_origin;
+      bottom_strut += window->screen->height - xinerama->height - xinerama->y_origin;
+    }
+      
   area->x = left_strut;
   area->y = top_strut;
   area->width = window->screen->width - left_strut - right_strut;
diff -ur metacity-2.4.34/src/window.h metacity-2.4.34-multimonitor/src/window.h
--- metacity-2.4.34/src/window.h	2003-01-05 08:51:02.000000000 +0100
+++ metacity-2.4.34-multimonitor/src/window.h	2003-02-06 15:40:15.000000000 +0100
@@ -279,9 +279,12 @@
 
   /* 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 && !(w)->maximized && !(w)->fullscreen)
+#define META_WINDOW_ALLOWS_MOVE(w)     ((w)->has_move_func && !(w)->fullscreen)
 #define META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS(w)   ((w)->has_resize_func && !(w)->maximized && !(w)->fullscreen && !(w)->shaded)
 #define META_WINDOW_ALLOWS_RESIZE(w)   (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) &&                \
                                         (((w)->size_hints.min_width < (w)->size_hints.max_width) ||  \
