diff -ru metacity-cvs-shakeloose-03-preserveprop-02/src/boxes.c metacity-cvs/src/boxes.c
--- metacity-cvs-shakeloose-03-preserveprop-02/src/boxes.c	2006-08-08 01:34:55.000000000 +0200
+++ metacity-cvs/src/boxes.c	2006-09-29 21:15:20.000000000 +0200
@@ -661,6 +661,34 @@
 }
 
 void
+meta_rectangle_find_extents (const GList *region,
+                             MetaRectangle *extents)
+{
+  const GList *temp = region;
+
+  int const very_large = 1000000;
+  int left   =  very_large;
+  int right  = -very_large;
+  int top    =  very_large;
+  int bottom = -very_large;
+
+  while (temp != NULL)
+    {
+      MetaRectangle *rect = (MetaRectangle*) temp->data;
+      left = MIN (left, BOX_LEFT(*rect));
+      right = MAX (right, BOX_RIGHT(*rect));
+      top = MIN (top, BOX_TOP(*rect));
+      bottom = MAX (bottom, BOX_BOTTOM(*rect));
+      temp = temp->next;
+    }
+
+  extents->x = left;
+  extents->y = top;
+  extents->width = right - left;
+  extents->height = bottom - top;
+}
+
+void
 meta_rectangle_free_list_and_elements (GList *filled_list)
 {
   g_list_foreach (filled_list, 
@@ -811,29 +839,28 @@
   /* First, find best rectangle from spanning_rects to which we will clip
    * rect into.
    */
-  temp = spanning_rects;
-  while (temp)
+  for (temp = spanning_rects; temp; temp = temp->next)
     {
       int factor = 1;
       MetaRectangle *compare_rect = temp->data;
       MetaRectangle  overlap;
       int            maximal_overlap_amount_for_compare;
-      
-      /* If x is fixed and the entire width of rect doesn't fit in compare, set
-       * factor to 0.
+     
+      /* If x is fixed and the entire width of rect doesn't fit in compare,
+       * skip the rectangle.
        */
       if ((fixed_directions & FIXED_DIRECTION_X) &&
           (compare_rect->x > rect->x || 
            compare_rect->x + compare_rect->width < rect->x + rect->width))
-        factor = 0;
+        continue;
         
-      /* If y is fixed and the entire height of rect doesn't fit in compare, set
-       * factor to 0.
+      /* If y is fixed and the entire height of rect doesn't fit in compare,
+       * skip the rectangle.
        */
       if ((fixed_directions & FIXED_DIRECTION_Y) &&
           (compare_rect->y > rect->y || 
            compare_rect->y + compare_rect->height < rect->y + rect->height))
-        factor = 0;
+        continue;
 
       /* Determine maximal overlap amount */
       meta_rectangle_intersect (rect, compare_rect, &overlap);
@@ -846,8 +873,6 @@
           best_rect    = compare_rect;
           best_overlap = maximal_overlap_amount_for_compare;
         }
-
-      temp = temp->next;
     }
 
   /* Clip rect appropriately */
@@ -923,7 +948,7 @@
         MIN (rect->width,  compare_rect->width) *
         MIN (rect->height, compare_rect->height);
 
-      /* Determine distance necessary to put rect into comapre_rect */
+      /* Determine distance necessary to put rect into compare_rect */
       dist_to_compare = 0;
       if (compare_rect->x > rect->x)
         dist_to_compare += compare_rect->x - rect->x;
diff -ru metacity-cvs-shakeloose-03-preserveprop-02/src/boxes.h metacity-cvs/src/boxes.h
--- metacity-cvs-shakeloose-03-preserveprop-02/src/boxes.h	2006-08-08 01:34:55.000000000 +0200
+++ metacity-cvs/src/boxes.h	2006-09-29 22:40:21.000000000 +0200
@@ -164,6 +164,11 @@
                                          const int            min_x,
                                          const int            min_y);
 
+/* Find the minimal rectangle that contains all of region
+ */
+void     meta_rectangle_find_extents    (const GList          *region,
+                                         MetaRectangle        *extents);
+
 /* Free the list created by
  *   meta_rectangle_get_minimal_spanning_set_for_region()
  * or
diff -ru metacity-cvs-shakeloose-03-preserveprop-02/src/constraints.c metacity-cvs/src/constraints.c
--- metacity-cvs-shakeloose-03-preserveprop-02/src/constraints.c	2006-09-29 02:28:09.000000000 +0200
+++ metacity-cvs/src/constraints.c	2006-09-29 23:53:47.000000000 +0200
@@ -701,7 +701,253 @@
   if (!window->maximized_horizontally && !window->maximized_vertically)
     return TRUE;
 
-  work_area = info->work_area_xinerama;
+  if (window->maximized_horizontally && window->maximized_vertically)
+    work_area = info->work_area_xinerama;
+  else
+    {
+      FixedDirections fixed_direction;
+      MetaRectangle relevant_area;
+      MetaRectangle xinerama_extents;
+
+      /* Initialize relevant_area with the minimal rectangle
+       * that containing all workspace. This can be smaller
+       * than window->screen->rect in the case of expanded
+       * panels. We need to know that in order for this
+       * to work correctly when the window is partly over
+       * such a panel. Basically we are saying: we don't
+       * care what happens with the window that is off-screen,
+       * but we also don't care what happens with the part
+       * of the window that overlaps with an expanded panel
+       * (or any strut that extends over the full length of
+       * the xinerama).
+       */
+      meta_rectangle_find_extents(
+          info->usable_screen_region, &relevant_area);
+
+      /* Same here; needed, instead of info->entire_xinerama,
+       * in the presence of expanded struts.
+       */
+      meta_rectangle_find_extents(
+          info->usable_xinerama_region, &xinerama_extents);
+
+      /* Set work_area to the rectangle that we would maximize
+       * to if there were no struts.
+       *
+       * At the same time, clip relevant_area to the maximum size
+       * (of the window) in the direction that we maximize in,
+       * and possibly adjust it also for expanded struts on
+       * this xinerama in the direction we do not maximize in,
+       * that weren't 'detected' yet because there is no such
+       * strut on the adjacent monitor (in the direction that
+       * we are maximizing in).
+       */
+      if (window->maximized_horizontally)
+        {
+	  /* The y direction will not be changed */
+	  fixed_direction = FIXED_DIRECTION_Y;
+	  /* The result will fit into this vertical interval */
+	  work_area.y = info->current.y;
+	  work_area.height = info->current.height;
+	  /* The result will fit into this horizontal interval */
+	  relevant_area.x = work_area.x = xinerama_extents.x;
+	  relevant_area.width = work_area.width = xinerama_extents.width;
+	  /* Check if the edge of the xinerama is (likely) the screen edge.
+	   * If so, clip the relevant area to the xinerama extents.
+	   * This is needed to account for expanded struts at the top/bottom
+	   * of the xinerama.
+	   */
+	  if (BOX_BOTTOM(xinerama_extents) >
+	      BOX_BOTTOM(relevant_area) - info->entire_xinerama.height / 4)
+            relevant_area.height =
+	        BOX_BOTTOM(xinerama_extents) - BOX_TOP(relevant_area);
+	  if (BOX_TOP(xinerama_extents) <
+	      BOX_TOP(relevant_area) + info->entire_xinerama.height / 4)
+	    {
+	      int offset = BOX_TOP(xinerama_extents) - BOX_TOP(relevant_area);
+	      relevant_area.y += offset;
+	      relevant_area.height -= offset;
+	    }
+	}
+      else /* window->maximized_vertically */
+        {
+	  /* The x direction will not be changed */
+	  fixed_direction = FIXED_DIRECTION_X;
+	  /* The result will fit into this horizontal interval */
+	  work_area.x = info->current.x;
+	  work_area.width = info->current.width;
+	  /* The result will fit into this vertical interval */
+	  relevant_area.y = work_area.y = xinerama_extents.y;
+	  relevant_area.height = work_area.height = xinerama_extents.height;
+	  /* Check if the edge of the xinerama is (likely) the screen edge.
+	   * If so, clip the relevant area to the xinerama extents.
+	   * This is needed to account for expanded struts at the left/right
+	   * of the xinerama.
+	   */
+	  if (BOX_RIGHT(xinerama_extents) >
+	      BOX_RIGHT(relevant_area) - info->entire_xinerama.height / 4)
+            relevant_area.width =
+	        BOX_RIGHT(xinerama_extents) - BOX_LEFT(relevant_area);
+	  if (BOX_LEFT(xinerama_extents) <
+	      BOX_LEFT(relevant_area) + info->entire_xinerama.height / 4)
+	    {
+	      int offset = BOX_LEFT(xinerama_extents) - BOX_LEFT(relevant_area);
+	      relevant_area.x += offset;
+	      relevant_area.width -= offset;
+	    }
+        }
+
+      /* At this point, work_area is equal to the window, unidirectionally
+       * maximized to the extend of the current xinerama. That means:
+       * maximized while taking expanded struts into account, but not
+       * yet taking unexpanded struts into account.
+       *
+       * At this point, relevant_area is a rectangle that, in the direction
+       * that we maximize in is equal to the current xinerama excluding
+       * possible expanded struts at its edge, and in the direction that
+       * we do not maximize in, equal to the whole screen excluding possible
+       * expanded struts at its edge.
+       *
+       * Next, we will clip (shrink) work_area again, till it is the
+       * correct size.
+       */
+      {
+	const GList *temp;
+	const MetaRectangle *best_rect = NULL;
+	int best_overlap = 0;
+	MetaRectangle relevant_rect;
+
+	/* Set relevant_rect to work_area clipped to relevant_area */
+	relevant_rect.x =
+	    MAX (BOX_LEFT(work_area),
+	         BOX_LEFT(relevant_area));
+	relevant_rect.y =
+	    MAX (BOX_TOP(work_area),
+	         BOX_TOP(relevant_area));
+	relevant_rect.width =
+	    MIN (BOX_RIGHT(work_area),
+	         BOX_RIGHT(relevant_area)) - relevant_rect.x;
+	relevant_rect.height =
+	    MIN (BOX_BOTTOM(work_area),
+	         BOX_BOTTOM(relevant_area)) - relevant_rect.y;
+
+	/* Find the best rectangle from usable_screen_region to which we
+	 * will clip work_area to, only looking at the relevant part
+	 * of work_area (that is, ignoring parts outside the screen
+	 * or on top of expanded struts).
+	 */
+	for (temp = info->usable_screen_region; temp; temp = temp->next)
+	  {
+	    MetaRectangle *compare_rect = temp->data;
+	    int            overlap;
+	   
+	    if (fixed_direction == FIXED_DIRECTION_X)
+	      {
+		/* Skip rectangles that the fixed direction doesn't fit into. */
+		if (BOX_LEFT(relevant_rect)  < BOX_LEFT(*compare_rect) ||
+		    BOX_RIGHT(relevant_rect) > BOX_RIGHT(*compare_rect))
+		  continue;
+
+		/* Find the vertical overlap */
+		{
+		  /*
+		   * Just using compare_rect->height would work, in the
+		   * sense that in that case simply the largest space is picked,
+		   * to maximize into, but that would take away all control from
+		   * the user about where to maximize a window. Rather we include
+		   * saved_rect some how, in a way that theoretically the window
+		   * can end up anywhere (in a sensible way).
+		   *
+		   * Consider the following:
+		   *
+		   *       saved_rect
+		   *   <---------------->
+		   *   <----lenA-->                            lenB == 0
+		   *      A        <---------STRUT-------->       B
+		   * <------------------Xinerama-side---------------------->
+		   *
+		   * In this case we want to maximize into area A.
+		   * But in this case:
+		   *
+		   *                                      saved_rect
+		   *                                  <---------------->
+		   *   lenA == 0                           <---lenB---->
+		   *      A        <---------STRUT-------->       B
+		   * <------------------Xinerama-side---------------------->
+		   *
+		   * we want to maximize into area B.
+		   * Finally, in this case:
+		   *
+		   *                      saved_rect
+		   *   lenA == 0      <---------------->      lenB == 0
+		   *      A        <---------STRUT-------->       B
+		   * <------------------Xinerama-side---------------------->
+		   *
+		   * We just want to maximize to the largest of A and B.
+		   *
+		   * The following will pick the largest len, weighted with
+		   * the actual resulting size - or the largest size when
+		   * len is always 0 (case 3).
+		   */
+
+		  /* The 1 dimensional overlap along the y-axis between the
+		   * saved_rect (unmaximized window) and the candidate
+		   * compare_rect, clamped to a minimum of 1, weighted
+		   * by the resulting maximized height for this candidate. */
+		  overlap = MAX(1,
+		                MIN (BOX_BOTTOM(window->saved_rect),
+		                     BOX_BOTTOM(*compare_rect)) -
+			        MAX (BOX_TOP(window->saved_rect),
+			             BOX_TOP(*compare_rect))) *
+		            compare_rect->height;
+	        }
+	      }
+	    else /* fixed_direction == FIXED_DIRECTION_Y */
+	      {
+		/* Skip rectangles that the fixed direction doesn't fit into. */
+		if (BOX_TOP(relevant_rect)    < BOX_TOP(*compare_rect) ||
+		    BOX_BOTTOM(relevant_rect) > BOX_BOTTOM(*compare_rect))
+		  continue;
+
+		/* Find the horizontal overlap */
+		{
+		  /* See above */
+		  overlap = MAX(1,
+		                MIN (BOX_RIGHT(window->saved_rect),
+		                     BOX_RIGHT(*compare_rect)) -
+			        MAX (BOX_LEFT(window->saved_rect),
+			             BOX_LEFT(*compare_rect))) *
+		            compare_rect->width;
+	        }
+	      }
+	    /* See if this is the best rect so far */
+	    if (overlap > best_overlap)
+	      {
+		best_rect    = compare_rect;
+		best_overlap = overlap;
+	      }
+	  }
+
+	/* Clip rect appropriately */
+	if (best_rect == NULL)				/* Should never happen */
+	  meta_warning ("No rect to unidirectional clip to found!\n");
+	else if (fixed_direction != FIXED_DIRECTION_X)
+	  {
+	    /* Clip horizontally */
+	    int new_x = MAX (BOX_LEFT(work_area), BOX_LEFT(*best_rect));
+	    work_area.width = MIN (BOX_RIGHT(work_area), BOX_RIGHT(*best_rect)) - new_x;
+	    work_area.x = new_x;
+	  }
+	else
+	  {
+	    /* Clip vertically */
+	    int new_y = MAX (BOX_TOP(work_area), BOX_TOP(*best_rect));
+	    work_area.height = MIN (BOX_BOTTOM(work_area), BOX_BOTTOM(*best_rect)) - new_y;
+	    work_area.y = new_y;
+	  }
+      }
+
+    }
+
   unextend_by_frame (&work_area, info->fgeom);
   get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size);
 
@@ -992,13 +1238,15 @@
   gboolean exit_early = FALSE, constraint_satisfied;
   MetaRectangle how_far_it_can_be_smushed, min_size, max_size;
 
+#ifdef WITH_VERBOSE_MODE
   /* First, log some debugging information */
   char spanning_region[1 + 28 * g_list_length (region_spanning_rectangles)];
-  (void) spanning_region;  /* Avoid stupid & incorrect compiler warnings... */
+
   meta_topic (META_DEBUG_GEOMETRY,
               "screen/xinerama constraint; region_spanning_rectangles: %s\n",
               meta_rectangle_region_to_string (region_spanning_rectangles, ", ", 
                                                spanning_region));
+#endif
 
   /* Determine whether constraint applies; exit if it doesn't */
   how_far_it_can_be_smushed = info->current;
