diff -X /usr/src/metacity/.diffignore -rudp -X /usr/src/metacity/.diffignore -rudp metacity-svn-shakeloose-05/src/constraints.c metacity-svn-shakeloose-05-maxconstraint-04/src/constraints.c
--- metacity-svn-shakeloose-05/src/constraints.c	2007-03-15 03:21:41.000000000 +0100
+++ metacity-svn-shakeloose-05-maxconstraint-04/src/constraints.c	2007-03-15 03:34:55.000000000 +0100
@@ -691,7 +691,7 @@ constrain_maximization (MetaWindow      
                         ConstraintPriority  priority,
                         gboolean            check_only)
 {
-  MetaRectangle min_size, max_size, work_area;
+  MetaRectangle min_size, max_size, target_size;
   gboolean hminbad, vminbad;
   gboolean horiz_equal, vert_equal;
   gboolean constraint_already_satisfied;
@@ -703,20 +703,161 @@ constrain_maximization (MetaWindow      
   if (!window->maximized_horizontally && !window->maximized_vertically)
     return TRUE;
 
-  work_area = info->work_area_xinerama;
-  unextend_by_frame (&work_area, info->fgeom);
-  get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size);
+  /* Calculate the targetted maximized client area of the window */
+  if (window->maximized_horizontally && window->maximized_vertically)
+    /* This is the correct target size, including frame (if any) */
+    target_size = info->work_area_xinerama;
+  else
+    {
+      MetaXineramaScreenInfo const* const xinerama_infos =
+          window->screen->xinerama_infos;
+      int i;
+ 
+      /* This is an unidirectionally maximized window.
+       * An unidirectionally maximized window, can span
+       * multiple xinerama's (in the non-maximized direction).
+       */
+      if (window->maximized_horizontally)
+        {
+          target_size.x      = info->entire_xinerama.x;
+          target_size.width  = info->entire_xinerama.width;
+          /* Include frame here; it will be subtracted later */
+          target_size.y      = info->current.y -
+                               info->fgeom->top_height;
+          target_size.height = info->current.height +
+                               info->fgeom->top_height +
+                               info->fgeom->bottom_height;
+        }
+      else
+        {
+          target_size.y      = info->entire_xinerama.y;
+          target_size.height = info->entire_xinerama.height;
+          /* Include frame here; it will be subtracted later */
+          target_size.x      = info->current.x -
+                               info->fgeom->left_width;
+          target_size.width  = info->current.width +
+                               info->fgeom->left_width +
+                               info->fgeom->right_width;
+        }
+      /* Xinerama's adjacent to the 'current' xinerama might
+       * be smaller -- we have to clip to their size if the
+       * window overlaps with them.
+       *              .---------------------. <-- entire_xinerama.y
+       * .------------| 21"                 | <-- correct y
+       * | 14"    .---+--------.            |
+       * |        |   | window |            |
+       * |        '---+--------'            |
+       * '------------|                     |
+       *              |                     |
+       *              '---------------------'
+       */
+      for (i = 0; i < window->screen->n_xinerama_infos; ++i)
+        if (meta_rectangle_overlap(&xinerama_infos[i].rect, &target_size))
+          {
+            if (window->maximized_horizontally)
+              {
+                /* Clip right-side to right-side of overlapping xinerama's */
+                if (BOX_RIGHT(target_size) > BOX_RIGHT(xinerama_infos[i].rect))
+                  target_size.width =
+                      BOX_RIGHT(xinerama_infos[i].rect) - BOX_LEFT(target_size);
+                /* Clip left-side to left-side of overlapping xinerama's */
+                if (BOX_LEFT(target_size) < BOX_LEFT(xinerama_infos[i].rect))
+                  {
+                    gint offset = BOX_LEFT(xinerama_infos[i].rect) -
+                                  BOX_LEFT(target_size);
+                    target_size.x += offset;
+                    target_size.width -= offset;
+                  }
+              }
+            else
+              {
+                /* Clip bottom to bottom of overlapping xinerama's */
+                if (BOX_BOTTOM(target_size) > BOX_BOTTOM(xinerama_infos[i].rect))
+                  target_size.height = BOX_BOTTOM(xinerama_infos[i].rect) -
+                                       BOX_TOP(target_size);
+                /* Clip top to top of overlapping xinerama's
+                 * (see ascii art above).
+                 */
+                if (BOX_TOP(target_size) < BOX_TOP(xinerama_infos[i].rect))
+                  {
+                    gint offset = BOX_TOP(xinerama_infos[i].rect) -
+                                  BOX_TOP(target_size);
+                    target_size.y += offset;
+                    target_size.height -= offset;
+                  }
+              }
+          }
+      /* Finally, we have to take the struts into account */
+      /* Run over all xinerama's */
+      for (i = 0; i < window->screen->n_xinerama_infos; ++i)
+        {
+          const GSList *strut_iter;
+ 
+          /* Skip xinerama's that don't overlap */
+          if (!meta_rectangle_overlap(&xinerama_infos[i].rect, &target_size))
+            continue;
+ 
+          /* Run over all struts */
+          for (strut_iter = window->screen->active_workspace->all_struts;
+               strut_iter; strut_iter = strut_iter->next)
+            {
+              MetaRectangle *strut = (MetaRectangle*) strut_iter->data;
+ 
+              /* Skip struts that don't overlap */
+              if (!meta_rectangle_overlap(strut, &target_size))
+                continue;
+              /* Skip struts that aren't on the xinerama under consideration */
+              if (!meta_rectangle_overlap(strut, &xinerama_infos[i].rect))
+                continue;
+              if (window->maximized_horizontally)
+                {
+                  /* Only consider structs whose orientation is perpendicular
+                   * to the direction that we are maximizing in.
+                   */
+                  if (BOX_LEFT(*strut) == BOX_LEFT(xinerama_infos[i].rect))
+                    {
+                      gint offset = BOX_RIGHT(*strut) - BOX_LEFT(target_size);
+                      target_size.x += offset;
+                      target_size.width -= offset;
+                    }
+                  else if (BOX_RIGHT(*strut) == BOX_RIGHT(xinerama_infos[i].rect))
+                    {
+                      gint offset = BOX_RIGHT(target_size) - BOX_LEFT(*strut);
+                      target_size.width -= offset;
+                    }
+                }
+              else
+                {
+                  if (BOX_TOP(*strut) == BOX_TOP(xinerama_infos[i].rect))
+                    {
+                      gint offset = BOX_BOTTOM(*strut) - BOX_TOP(target_size);
+                      target_size.y += offset;
+                      target_size.height -= offset;
+                    }
+                  else if (BOX_BOTTOM(*strut) == BOX_BOTTOM(xinerama_infos[i].rect))
+                    {
+                      gint offset = BOX_BOTTOM(target_size) - BOX_TOP(*strut);
+                      target_size.height -= offset;
+                    }
+                }
+            }
+        }
+    }
+  /* Subtract the frame size (if any) */
+  unextend_by_frame (&target_size, info->fgeom);
 
-  hminbad = work_area.width < min_size.width && window->maximized_horizontally;
-  vminbad = work_area.height < min_size.height && window->maximized_vertically;
+  /* Check max/min size constraints */
+  get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size);
+  hminbad = target_size.width < min_size.width && window->maximized_horizontally;
+  vminbad = target_size.height < min_size.height && window->maximized_vertically;
   if (hminbad || vminbad)
     return TRUE;
 
   /* Determine whether constraint is already satisfied; exit if it is */
-  horiz_equal = work_area.x      == info->current.x &&
-                work_area.width  == info->current.width;
-  vert_equal  = work_area.y      == info->current.y &&
-                work_area.height == info->current.height;
+  horiz_equal = target_size.x      == info->current.x &&
+                target_size.width  == info->current.width;
+  vert_equal  = target_size.y      == info->current.y &&
+                target_size.height == info->current.height;
   constraint_already_satisfied =
     (horiz_equal || !window->maximized_horizontally) &&
     (vert_equal  || !window->maximized_vertically);
@@ -726,13 +867,13 @@ constrain_maximization (MetaWindow      
   /*** Enforce constraint ***/
   if (window->maximized_horizontally)
     {
-      info->current.x      = work_area.x;
-      info->current.width  = work_area.width;
+      info->current.x      = target_size.x;
+      info->current.width  = target_size.width;
     }
   if (window->maximized_vertically)
     {
-      info->current.y      = work_area.y;
-      info->current.height = work_area.height;
+      info->current.y      = target_size.y;
+      info->current.height = target_size.height;
     }
   return TRUE;
 }
