diff --git a/ChangeLog b/ChangeLog
index d070a9025..676874c4d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2006-10-01  Elijah Newren  <newren gmail com>
+
+	Patch from Carlo Wood to ensure that maximized and minimized
+	properties are maintained across restarts.  #358042.
+
+	* src/constraints.c (place_window_if_needed): fix up partial
+	maximization handling and add minimize_after_placement handling.
+
+	* src/display.[ch] (struct MetaDisplay, meta_display_open): add a
+	new display->display_opening flag to allow handling startup
+	differently where needed.
+
+	* src/window-props.c (reload_net_wm_state): handle
+	_net_wm_state_hidden as well, setting
+	window->minimize_after_placement appropriately
+
+	* src/window.[ch] (struct MetaWindow, meta_window_new_with_attrs):
+	add a window->minimize_after_placement field
+
+	* src/window.c (meta_window_new_with_attrs): only unminimize the
+	window and its transients if the display isn't being opened,
+	(unmaximize_window_before_freeing): don't reset the state unless
+	the window is becoming withdrawn, if the screen is being closed be
+	sure to save the unmaximized state of the window so the next
+	window manager can restore it
+
 2006-10-01  Elijah Newren  <newren gmail com>
 
 	* src/window-props.c (set_title_text): surround the
diff --git a/src/constraints.c b/src/constraints.c
index 228d0ad96..4c2fbbc8d 100644
--- a/src/constraints.c
+++ b/src/constraints.c
@@ -458,13 +458,15 @@ place_window_if_needed(MetaWindow     *window,
 
   /* Do placement if any, so we go ahead and apply position
    * constraints in a move-only context. Don't place
-   * maximized/fullscreen windows until they are unmaximized
-   * and unfullscreened
+   * maximized/minimized/fullscreen windows until they are
+   * unmaximized, unminimized and unfullscreened.
    */
   did_placement = FALSE;
   if (!window->placed &&
       window->calc_placement &&
-      !META_WINDOW_MAXIMIZED (window) &&
+      !(window->maximized_horizontally ||
+        window->maximized_vertically) &&
+      !window->minimized &&
       !window->fullscreen)
     {
       MetaRectangle placed_rect = info->orig;
@@ -499,53 +501,47 @@ place_window_if_needed(MetaWindow     *window,
       info->fixed_directions = 0;
     }
 
-  if ((window->maximize_horizontally_after_placement ||
-       window->maximize_vertically_after_placement) &&
-      (window->placed || did_placement))
+  if (window->placed || did_placement)
     {
-      /* define a sane saved_rect so that the user can unmaximize to
-       * something reasonable.
-       */
-      if (info->current.width >= info->work_area_xinerama.width)
-        {
-          info->current.width = .75 * info->work_area_xinerama.width;
-          info->current.x = info->work_area_xinerama.x +
-                   .125 * info->work_area_xinerama.width;
-        }
-      if (info->current.height >= info->work_area_xinerama.height)
-        {
-          info->current.height = .75 * info->work_area_xinerama.height;
-          info->current.y = info->work_area_xinerama.y +
-                   .083 * info->work_area_xinerama.height;
-        }
-
-      if (window->maximize_horizontally_after_placement &&
+      if (window->maximize_horizontally_after_placement ||
           window->maximize_vertically_after_placement)
-        meta_window_maximize_internal (window,   
-                                       META_MAXIMIZE_HORIZONTAL |
-                                       META_MAXIMIZE_VERTICAL,
-                                       &info->current);
-      else if (window->maximize_horizontally_after_placement)
         {
-          info->current.x = info->work_area_xinerama.x
-            + info->fgeom->left_width;
-          info->current.width = info->work_area_xinerama.width
-            - info->fgeom->left_width - info->fgeom->right_width;
+          /* define a sane saved_rect so that the user can unmaximize to
+           * something reasonable.
+           */
+          if (info->current.width >= info->work_area_xinerama.width)
+            {
+              info->current.width = .75 * info->work_area_xinerama.width;
+              info->current.x = info->work_area_xinerama.x +
+                       .125 * info->work_area_xinerama.width;
+            }
+          if (info->current.height >= info->work_area_xinerama.height)
+            {
+              info->current.height = .75 * info->work_area_xinerama.height;
+              info->current.y = info->work_area_xinerama.y +
+                       .083 * info->work_area_xinerama.height;
+            }
+
+          if (window->maximize_horizontally_after_placement ||
+              window->maximize_vertically_after_placement)
+            meta_window_maximize_internal (window,   
+                (window->maximize_horizontally_after_placement ?
+                 META_MAXIMIZE_HORIZONTAL : 0 ) |
+                (window->maximize_vertically_after_placement ?
+                 META_MAXIMIZE_VERTICAL : 0), &info->current);
+
+          /* maximization may have changed frame geometry */
+          if (window->frame && !window->fullscreen)
+            meta_frame_calc_geometry (window->frame, info->fgeom);
+
+          window->maximize_horizontally_after_placement = FALSE;
+          window->maximize_vertically_after_placement = FALSE;
         }
-      else if (window->maximize_vertically_after_placement);
+      if (window->minimize_after_placement)
         {
-          info->current.y = info->work_area_xinerama.y
-            + info->fgeom->top_height;
-          info->current.height = info->work_area_xinerama.height
-            - info->fgeom->top_height - info->fgeom->bottom_height;
+          meta_window_minimize (window);
+          window->minimize_after_placement = FALSE;
         }
-
-      /* maximization may have changed frame geometry */
-      if (window->frame && !window->fullscreen)
-        meta_frame_calc_geometry (window->frame, info->fgeom);
-
-      window->maximize_horizontally_after_placement = FALSE;
-      window->maximize_vertically_after_placement = FALSE;
     }
 }
 
diff --git a/src/display.c b/src/display.c
index 0f1d82eef..fd6ebcb31 100644
--- a/src/display.c
+++ b/src/display.c
@@ -363,6 +363,7 @@ meta_display_open (void)
   display->error_traps = 0;
   display->error_trap_handler = NULL;
   display->server_grab_count = 0;
+  display->display_opening = TRUE;
 
   display->pending_pings = NULL;
   display->autoraise_timeout_id = 0;
@@ -767,6 +768,9 @@ meta_display_open (void)
   if (meta_prefs_get_compositing_manager ())
     enable_compositor (display);
   
+  /* Done opening new display */
+  display->display_opening = FALSE;
+
   return TRUE;
 }
 
diff --git a/src/display.h b/src/display.h
index 689af220b..528e23271 100644
--- a/src/display.h
+++ b/src/display.h
@@ -311,6 +311,9 @@ struct _MetaDisplay
   /* Xinerama cache */
   unsigned int xinerama_cache_invalidated : 1;
 
+  /* Opening the display */
+  unsigned int display_opening : 1;
+
   /* Closing down the display */
   int closing;
 
diff --git a/src/window-props.c b/src/window-props.c
index 92026e08e..49df9aeeb 100644
--- a/src/window-props.c
+++ b/src/window-props.c
@@ -464,6 +464,8 @@ reload_net_wm_state (MetaWindow    *window,
         window->maximize_horizontally_after_placement = TRUE;
       else if (value->v.atom_list.atoms[i] == window->display->atom_net_wm_state_maximized_vert)
         window->maximize_vertically_after_placement = TRUE;
+      else if (value->v.atom_list.atoms[i] == window->display->atom_net_wm_state_hidden)
+        window->minimize_after_placement = TRUE;
       else if (value->v.atom_list.atoms[i] == window->display->atom_net_wm_state_modal)
         window->wm_state_modal = TRUE;
       else if (value->v.atom_list.atoms[i] == window->display->atom_net_wm_state_skip_taskbar)
diff --git a/src/window.c b/src/window.c
index 31f1ce73e..acccfe66d 100644
--- a/src/window.c
+++ b/src/window.c
@@ -445,6 +445,7 @@ meta_window_new_with_attrs (MetaDisplay       *display,
   window->maximized_vertically = FALSE;
   window->maximize_horizontally_after_placement = FALSE;
   window->maximize_vertically_after_placement = FALSE;
+  window->minimize_after_placement = FALSE;
   window->fullscreen = FALSE;
   window->require_fully_onscreen = TRUE;
   window->require_on_single_xinerama = TRUE;
@@ -757,10 +758,15 @@ meta_window_new_with_attrs (MetaDisplay       *display,
   meta_window_foreach_transient (window,
                                  queue_calc_showing_func,
                                  NULL);
-  /* See bug 334899; the window may have minimized ancestors which need to be
-   * shown.
+  /* See bug 334899; the window may have minimized ancestors
+   * which need to be shown.
+   *
+   * However, we shouldn't unminimize windows here when opening
+   * a new display because that breaks passing _NET_WM_STATE_HIDDEN
+   * between window managers when replacing them; see bug 358042.
    */
-  unminimize_window_and_all_transient_parents (window);
+  if (!display->display_opening)
+    unminimize_window_and_all_transient_parents (window);
 
   meta_error_trap_pop (display, FALSE); /* pop the XSync()-reducing trap */
   meta_display_ungrab (display);
@@ -2318,13 +2324,32 @@ unmaximize_window_before_freeing (MetaWindow        *window)
   meta_topic (META_DEBUG_WINDOW_OPS,
               "Unmaximizing %s just before freeing\n",
               window->desc);
-      
-  window->rect = window->saved_rect;
-  send_configure_notify (window);
 
   window->maximized_horizontally = FALSE;
   window->maximized_vertically = FALSE;
-  set_net_wm_state (window);
+
+  if (window->withdrawn)                /* See bug #137185 */
+    {
+      window->rect = window->saved_rect;
+      send_configure_notify (window);
+
+      set_net_wm_state (window);
+    }
+  else if (window->screen->closing)     /* See bug #358042 */
+    {
+      /* Do NOT update net_wm_state: this screen is closing,
+       * it likely will be managed by another window manager
+       * that will need the current _NET_WM_STATE atoms.
+       * Moreover, it will need to know the unmaximized geometry,
+       * therefore move_resize the window to saved_rect here
+       * before closing it. */
+      meta_window_move_resize (window,
+                               FALSE,
+                               window->saved_rect.x,
+                               window->saved_rect.y,
+                               window->saved_rect.width,
+                               window->saved_rect.height);
+    }
 }
 
 void
diff --git a/src/window.h b/src/window.h
index f31c33da7..2b9dd201a 100644
--- a/src/window.h
+++ b/src/window.h
@@ -123,8 +123,11 @@ struct _MetaWindow
   /* Whether we're maximized */
   guint maximized_horizontally : 1;
   guint maximized_vertically : 1;
+
+  /* Whether we have to maximize/minimize after placement */
   guint maximize_horizontally_after_placement : 1;
   guint maximize_vertically_after_placement : 1;
+  guint minimize_after_placement : 1;
 
   /* Whether we're shaded */
   guint shaded : 1;