Index: constraints.c
===================================================================
RCS file: /cvs/gnome/metacity/src/constraints.c,v
retrieving revision 1.8
diff -p -u -r1.8 constraints.c
--- constraints.c	2 May 2003 07:31:59 -0000	1.8
+++ constraints.c	8 Jun 2003 17:51:03 -0000
@@ -1119,20 +1119,38 @@ meta_window_constrain (MetaWindow       
       !window->maximized &&
       !window->fullscreen)
     {
-      int x, y;
+      MetaRectangle placed_rect = current;
 
       meta_window_place (window, orig_fgeom, current.x, current.y,
-                         &x, &y);
+                         &placed_rect.x, &placed_rect.y);
+
+      /* placing the window may have changed the xinerama.  Find the
+       * new xinerama and update the ConstraintInfo
+       */
+      info.xinerama = meta_screen_get_xinerama_for_rect (window->screen,
+                                              &placed_rect);
+      meta_window_get_work_area_for_xinerama (window,
+                                              info.xinerama->number,
+                                              &info.work_area_xinerama);
+      update_position_limits (window, &info);
 
       constrain_move (window, &info, &current,
-                      x - current.x,
-                      y - current.y,
+                      placed_rect.x - current.x,
+                      placed_rect.y - current.y,
                       new);
       current = *new;
 
       /* Ignore any non-placement movement */
       x_move_delta = 0;
       y_move_delta = 0;
+
+    }
+
+  if (window->maximize_after_placement &&
+      window->placed)
+    {
+      window->maximize_after_placement = FALSE;
+      meta_window_maximize_internal (window, new);
     }
 
   /* Maximization, fullscreen, etc. are defined as a move followed by
Index: place.c
===================================================================
RCS file: /cvs/gnome/metacity/src/place.c,v
retrieving revision 1.33
diff -p -u -r1.33 place.c
--- place.c	7 Apr 2003 03:33:45 -0000	1.33
+++ place.c	8 Jun 2003 17:51:07 -0000
@@ -404,6 +404,8 @@ find_first_fit (MetaWindow *window,
                 MetaFrameGeometry *fgeom,
                 /* visible windows on relevant workspaces */
                 GList      *windows,
+		int*        xineramas_list,
+		int         n_xineramas,
                 int         x,
                 int         y,
                 int        *new_x,
@@ -423,8 +425,6 @@ find_first_fit (MetaWindow *window,
   MetaRectangle rect;
   MetaRectangle work_area;
   int i;
-  int* xineramas_list;
-  int  n_xineramas;
   
   retval = FALSE;
 
@@ -447,9 +447,6 @@ find_first_fit (MetaWindow *window,
       rect.height += fgeom->top_height + fgeom->bottom_height;
     }
 
-  meta_screen_get_natural_xinerama_list (window->screen,
-					 &xineramas_list,
-					 &n_xineramas);
   for (i = 0; i < n_xineramas; i++)
     {
       meta_topic (META_DEBUG_XINERAMA,
@@ -552,68 +549,11 @@ find_first_fit (MetaWindow *window,
   
  out:
 
-  g_free (xineramas_list);
   g_list_free (below_sorted);
   g_list_free (right_sorted);
   return retval;
 }
 
-static void
-constrain_placement (MetaWindow        *window,
-                     MetaFrameGeometry *fgeom,
-                     int                x,
-                     int                y,
-                     int               *new_x,
-                     int               *new_y)
-{
-  /* The purpose of this function is to apply constraints that are not
-   * covered by window.c:constrain_position(), but should apply
-   * whenever we are _placing_ a window regardless of placement algorithm.
-   */
-  MetaRectangle work_area;  
-  int nw_x, nw_y;
-  int offscreen_w, offscreen_h;
-  MetaRectangle outer_rect;
-
-  meta_window_get_outer_rect (window, &outer_rect);
-
-  /* FIXME this is bogus because we get the current xinerama
-   * for the window based on its position, but we haven't
-   * placed it yet.
-   */
-  meta_window_get_work_area_current_xinerama (window, &work_area);
-
-  nw_x = work_area.x;
-  nw_y = work_area.y;
-
-  if (window->frame)
-    {
-      nw_x += fgeom->left_width;
-      nw_y += fgeom->top_height;
-    }
-
-  /* Keep window from going off the bottom right, though we don't have
-   * this constraint once the window has been placed
-   */
-  offscreen_w = (outer_rect.x + outer_rect.width) - (work_area.x + work_area.width);
-  if (offscreen_w > 0)
-    nw_x -= offscreen_w;
-  offscreen_h = (outer_rect.y + outer_rect.height) - (work_area.y + work_area.height);
-  if (offscreen_h > 0)
-    nw_y -= offscreen_h;
-  
-  /* Keep window from going off left edge, though again we don't have
-   * this constraint once the window has been placed.
-   */
-  if (x < nw_x)
-    x = nw_x;
-  if (y < nw_y)
-    y = nw_y;
-
-  *new_x = x;
-  *new_y = y;
-}
-
 void
 meta_window_place (MetaWindow        *window,
                    MetaFrameGeometry *fgeom,
@@ -624,6 +564,10 @@ meta_window_place (MetaWindow        *wi
 {
   GList *windows;
   const MetaXineramaScreenInfo *xi;
+  int* xineramas_list = NULL;
+  int  n_xineramas;
+  int  i;
+  int placed_on = -1;
   
   /* frame member variables should NEVER be used in here, only
    * MetaFrameGeometry. But remember fgeom == NULL
@@ -811,16 +755,87 @@ meta_window_place (MetaWindow        *wi
   x = xi->x_origin;
   y = xi->y_origin;
 
-  if (find_first_fit (window, fgeom, windows, x, y, &x, &y))
+  meta_screen_get_natural_xinerama_list (window->screen,
+					 &xineramas_list,
+					 &n_xineramas);
+
+  if (find_first_fit (window, fgeom, windows,
+                      xineramas_list, n_xineramas,
+                      x, y, &x, &y))
     goto done;
-  
-  find_next_cascade (window, fgeom, windows, x, y, &x, &y);
+
+  /* This is a special-case origin-cascade so that windows that are
+   * too large to fit onto a workspace (and which will be
+   * automaximized later) will go onto an empty xinerama if one is
+   * available.
+   */
+  if (window->has_maximize_func && window->decorated &&
+      !window->fullscreen)
+    {
+      if (window->frame)
+        {
+          x = fgeom->left_width;
+          y = fgeom->top_height;
+        }
+      else
+        {
+          x = 0;
+          y = 0;
+        }
+
+      for (i = 0; i < n_xineramas; i++)
+        {
+          MetaRectangle work_area;
+          
+          meta_window_get_work_area_for_xinerama (window, xineramas_list[i], &work_area);
+          
+          if (!rectangle_overlaps_some_window (&work_area, windows))
+            {
+              x += work_area.x;
+              y += work_area.y;
+              placed_on = i;
+              break;
+            }
+        }
+    }
+
+  /* if the window wasn't placed at the origin of an empty xinerama,
+   * cascade it onto the current xinerama
+   */
+  if (placed_on == -1)
+    {
+      find_next_cascade (window, fgeom, windows, x, y, &x, &y);
+      placed_on = 0;
+    }
+
+  /* Maximize windows if they are too big for their work area (bit of
+   * a hack here). Assume undecorated windows probably don't intend to
+   * be maximized.  
+   */
+  if (window->has_maximize_func && window->decorated &&
+      !window->fullscreen)
+    {
+      MetaRectangle workarea;
+      MetaRectangle outer;
+
+      meta_window_get_work_area_for_xinerama (window,
+                                              xineramas_list[placed_on],
+                                              &workarea);      
+      meta_window_get_outer_rect (window, &outer);
+      
+      if (outer.width >= workarea.width &&
+          outer.height >= workarea.height)
+        {
+          outer.x = x;
+          outer.y = y;
+          meta_window_maximize_internal (window, &outer);
+        }
+    }
   
  done:
+  g_free (xineramas_list);
   g_list_free (windows);
   
-  constrain_placement (window, fgeom, x, y, &x, &y);
-
  done_no_constraints:
 
   *new_x = x;
Index: window.c
===================================================================
RCS file: /cvs/gnome/metacity/src/window.c,v
retrieving revision 1.284
diff -p -u -r1.284 window.c
--- window.c	7 Jun 2003 17:15:33 -0000	1.284
+++ window.c	8 Jun 2003 17:51:15 -0000
@@ -417,6 +417,7 @@ meta_window_new (MetaDisplay *display,
   window->user_has_move_resized = FALSE;
   
   window->maximized = FALSE;
+  window->maximize_after_placement = FALSE;
   window->fullscreen = FALSE;
   window->on_all_workspaces = FALSE;
   window->shaded = FALSE;
@@ -695,28 +696,6 @@ meta_window_new (MetaDisplay *display,
       }
   }
   
-  /* Maximize windows if they are too big for their work
-   * area (bit of a hack here). Assume undecorated windows
-   * probably don't intend to be maximized.
-   */
-  if (window->has_maximize_func && window->decorated &&
-      !window->fullscreen)
-    {
-      MetaRectangle workarea;
-      MetaRectangle outer;
-
-      if (!window->placed)
-        meta_warning ("Metacity issue: using position-based current xinerama prior to placement\n");
-
-      meta_window_get_work_area_current_xinerama (window, &workarea);      
-    
-      meta_window_get_outer_rect (window, &outer);
-      
-      if (outer.width >= workarea.width &&
-          outer.height >= workarea.height)
-        meta_window_maximize (window);
-    }
-  
   /* Sync stack changes */
   meta_stack_thaw (window->screen->stack);
 
@@ -1841,29 +1820,44 @@ meta_window_save_rect (MetaWindow *windo
 }
 
 void
+meta_window_maximize_internal (MetaWindow    *window,
+                               MetaRectangle *saved_rect)
+{
+  meta_topic (META_DEBUG_WINDOW_OPS,
+              "Maximizing %s\n", window->desc);
+  
+  if (saved_rect != NULL)
+    window->saved_rect = *saved_rect;
+  else
+    meta_window_save_rect (window);
+  
+  window->maximized = TRUE;
+  
+  recalc_window_features (window);
+  set_net_wm_state (window);
+}
+
+void
 meta_window_maximize (MetaWindow  *window)
 {
   if (!window->maximized)
     {
-      meta_topic (META_DEBUG_WINDOW_OPS,
-                  "Maximizing %s\n", window->desc);
-
       if (window->shaded)
         meta_window_unshade (window);
-
-      meta_window_save_rect (window);
       
-      window->maximized = TRUE;
+      /* if the window hasn't been placed yet, we'll maximize it then
+       */
+      if (!window->placed)
+	{
+	  window->maximize_after_placement = TRUE;
+	  return;
+	}
+
+      meta_window_maximize_internal (window, NULL);
 
-      /* FIXME why did I put this here? */
-      meta_window_raise (window);      
-      
       /* move_resize with new maximization constraints
        */
       meta_window_queue_move_resize (window);
-
-      recalc_window_features (window);
-      set_net_wm_state (window);
     }
 }
 
@@ -4309,9 +4303,9 @@ update_net_wm_state (MetaWindow *window)
           if (atoms[i] == window->display->atom_net_wm_state_shaded)
             window->shaded = TRUE;
           else if (atoms[i] == window->display->atom_net_wm_state_maximized_horz)
-            window->maximized = TRUE;
+            window->maximize_after_placement = TRUE;
           else if (atoms[i] == window->display->atom_net_wm_state_maximized_vert)
-            window->maximized = TRUE;
+            window->maximize_after_placement = TRUE;
           else if (atoms[i] == window->display->atom_net_wm_state_modal)
             window->wm_state_modal = TRUE;
           else if (atoms[i] == window->display->atom_net_wm_state_skip_taskbar)
Index: window.h
===================================================================
RCS file: /cvs/gnome/metacity/src/window.h,v
retrieving revision 1.89
diff -p -u -r1.89 window.h
--- window.h	4 Jun 2003 19:15:46 -0000	1.89
+++ window.h	8 Jun 2003 17:51:15 -0000
@@ -94,6 +94,7 @@ struct _MetaWindow
   
   /* Whether we're maximized */
   guint maximized : 1;
+  guint maximize_after_placement : 1;
 
   /* Whether we're shaded */
   guint shaded : 1;
@@ -304,6 +305,8 @@ void        meta_window_queue_calc_showi
 void        meta_window_minimize           (MetaWindow  *window);
 void        meta_window_unminimize         (MetaWindow  *window);
 void        meta_window_maximize           (MetaWindow  *window);
+void        meta_window_maximize_internal  (MetaWindow    *window,
+                                            MetaRectangle *saved_rect);
 void        meta_window_unmaximize         (MetaWindow  *window);
 void        meta_window_shade              (MetaWindow  *window);
 void        meta_window_unshade            (MetaWindow  *window);
