Index: src/place.c
===================================================================
RCS file: /cvs/gnome/metacity/src/place.c,v
retrieving revision 1.40
diff -p -u -r1.40 place.c
--- src/place.c	28 Jan 2005 14:13:28 -0000	1.40
+++ src/place.c	9 Feb 2005 07:18:10 -0000
@@ -224,6 +224,76 @@ find_next_cascade (MetaWindow *window,
     }
 }
 
+static void
+find_most_freespace (MetaWindow *window,
+                     MetaFrameGeometry *fgeom,
+                     /* visible windows on relevant workspaces */
+                     MetaWindow *focus_window,
+                     int         x,
+                     int         y,
+                     int        *new_x,
+                     int        *new_y)
+{
+  int side;
+  int max_area;
+  int max_width, max_height, left, right, top, bottom;
+  MetaRectangle work_area;
+  MetaRectangle avoid;
+  MetaRectangle outer;
+
+  meta_window_get_work_area_current_xinerama (focus_window, &work_area);
+  meta_window_get_outer_rect (focus_window, &avoid);
+  meta_window_get_outer_rect (window, &outer);
+
+  /* Find the areas of choosing the various sides of the focus window */
+  max_width  = MIN(avoid.width, outer.width);
+  max_height = MIN(avoid.height,outer.height);
+  left   = MIN(avoid.x, outer.width);
+  right  = MIN(work_area.width-(avoid.x+avoid.width), outer.width);
+  top    = MIN(avoid.y, outer.height);
+  bottom = MIN(work_area.height-(avoid.y+avoid.height), outer.height);
+
+  /* Find out which side of the focus_window can show the most of the window */
+  side = 0;
+  max_area = left*max_height;
+  if (right*max_height > max_area)
+    {
+      side = 1;
+      max_area = right*max_height;
+    }
+  if (top*max_width > max_area)
+    {
+      side = 2;
+      max_area = top*max_width;
+    }
+  if (bottom*max_width > max_area)
+    side = 3;
+
+  /* Place the window on the relevant side; convert coord to position of window,
+   * not position of frame.
+   */
+  switch (side)
+    {
+    case 0:
+      *new_x = work_area.x + fgeom->left_width;
+      *new_y = avoid.y + fgeom->top_height;
+      break;
+    case 1:
+      *new_x = avoid.x+avoid.width + fgeom->left_width;
+      *new_y = avoid.y + fgeom->top_height;
+      break;
+    case 2:
+      *new_x = avoid.x + fgeom->left_width;
+      *new_y = work_area.y + fgeom->top_height;
+      break;
+    case 3:
+      *new_x = avoid.x + fgeom->left_width;
+      *new_y = avoid.y+avoid.height + fgeom->top_height;
+      break;
+    }
+}
+
+
 static int
 intcmp (const void* a, const void* b)
 {
@@ -774,7 +844,7 @@ meta_window_place (MetaWindow        *wi
   if (find_first_fit (window, fgeom, windows,
                       xineramas_list, n_xineramas,
                       x, y, &x, &y))
-    goto done;
+    goto done_check_denied_focus;
 
   /* This is a special-case origin-cascade so that windows that are
    * too large to fit onto a workspace (and which will be
@@ -840,6 +910,51 @@ meta_window_place (MetaWindow        *wi
         {
           window->maximize_after_placement = TRUE;
         }
+    }
+
+ done_check_denied_focus:
+  /* If the window is being denied focus and isn't a transient of the
+   * focus window, we do NOT want it to overlap with the focus window
+   * if at all possible.  This is guaranteed to only be called if the
+   * focus_window is non-NULL, and we try to avoid that window.
+   */
+  if (window->denied_focus_and_not_transient)
+    {
+      gboolean       found_fit;
+      MetaWindow    *focus_window;
+      MetaRectangle  overlap;
+
+      focus_window = window->display->focus_window;
+      g_assert (focus_window != NULL);
+
+      /* No need to do anything if the window doesn't overlap at all */
+      found_fit = !meta_rectangle_intersect (&window->rect,
+                                             &focus_window->rect,
+                                             &overlap);
+
+      /* Try to do a first fit again, this time only taking into account the
+       * focus window.
+       */
+      if (!found_fit)
+        {
+          GList *focus_window_list;
+          focus_window_list = g_list_prepend (NULL, focus_window);
+
+          /* Reset x and y ("origin" placement algorithm) */
+          x = xi->x_origin;
+          y = xi->y_origin;
+
+          found_fit = find_first_fit (window, fgeom, focus_window_list,
+                                      xineramas_list, n_xineramas,
+                                      x, y, &x, &y);
+          g_list_free (focus_window_list);
+	}
+
+      /* If that still didn't work, just place it where we can see as much
+       * as possible.
+       */
+      if (!found_fit)
+        find_most_freespace (window, fgeom, focus_window, x, y, &x, &y);
     }
   
  done:
Index: src/window.c
===================================================================
RCS file: /cvs/gnome/metacity/src/window.c,v
retrieving revision 1.374
diff -p -u -r1.374 window.c
--- src/window.c	9 Feb 2005 03:18:46 -0000	1.374
+++ src/window.c	9 Feb 2005 07:18:12 -0000
@@ -444,6 +444,7 @@ meta_window_new_with_attrs (MetaDisplay 
     meta_topic (META_DEBUG_PLACEMENT,
                 "Not placing window 0x%lx since it's already mapped\n",
                 xwindow);
+  window->denied_focus_and_not_transient = FALSE;
   window->unmanaging = FALSE;
   window->calc_showing_queued = FALSE;
   window->move_resize_queued = FALSE;
@@ -1678,6 +1679,8 @@ meta_window_show (MetaWindow *window)
         {
           meta_window_stack_just_below (window, window->display->focus_window);
           ensure_mru_position_after (window, window->display->focus_window);
+          if (!window->placed)
+            window->denied_focus_and_not_transient = TRUE;
         }
     }
 
@@ -1701,6 +1704,11 @@ meta_window_show (MetaWindow *window)
        */
       window->placed = TRUE;
       did_placement = TRUE;
+
+      /* Don't want to accidentally reuse the fact that we had been denied
+       * focus in any future constraints unless we're denied focus again.
+       */
+      window->denied_focus_and_not_transient = FALSE;
     }
   
   /* Shaded means the frame is mapped but the window is not */
Index: src/window.h
===================================================================
RCS file: /cvs/gnome/metacity/src/window.h,v
retrieving revision 1.113
diff -p -u -r1.113 window.h
--- src/window.h	28 Jan 2005 14:13:28 -0000	1.113
+++ src/window.h	9 Feb 2005 07:18:12 -0000
@@ -207,6 +207,9 @@ struct _MetaWindow
   /* Have we placed this window? */
   guint placed : 1;
 
+  /* Is this not a transient of the focus window which is being denied focus? */
+  guint denied_focus_and_not_transient : 1;
+
   /* Has this window not ever been shown yet? */
   guint showing_for_first_time : 1;
 
