diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/constraints.c metacity/src/constraints.c
--- metacity-new/src/constraints.c	2006-04-17 23:29:49.000000000 -0400
+++ metacity/src/constraints.c	2006-04-17 17:26:01.000000000 -0400
@@ -314,6 +314,11 @@
    */
   if (!orig_fgeom)
     g_free (info.fgeom);
+
+  meta_topic (META_DEBUG_GEOMETRY, "Finished Constraining %s in move from %d,%d %dx%d to %d,%d %dx%d\n",
+	      window->desc,
+              orig->x, orig->y, orig->width, orig->height,
+              new->x,  new->y,  new->width,  new->height); 
 }
 
 static void
@@ -468,6 +473,8 @@
 
       info->current.x = placed_rect.x;
       info->current.y = placed_rect.y;
+      info->current.width = placed_rect.width;
+      info->current.height = placed_rect.height;
 
       /* Since we just barely placed the window, there's no reason to
        * consider any of the directions fixed.
diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/display.c metacity/src/display.c
--- metacity-new/src/display.c	2006-04-17 23:30:34.000000000 -0400
+++ metacity/src/display.c	2006-04-16 15:33:06.000000000 -0400
@@ -37,6 +37,7 @@
 #include "resizepopup.h"
 #include "xprops.h"
 #include "workspace.h"
+#include "history.h"
 #include "bell.h"
 #include "effects.h"
 #include "compositor.h"
@@ -3658,6 +3659,8 @@
       g_source_remove (display->grab_resize_timeout_id);
       display->grab_resize_timeout_id = 0;
     }
+  
+  meta_history_commit_window ();
 }
 
 void
diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/display.h metacity/src/display.h
--- metacity-new/src/display.h	2006-04-17 23:30:34.000000000 -0400
+++ metacity/src/display.h	2006-04-16 15:33:06.000000000 -0400
@@ -178,6 +178,7 @@
   Atom atom_metacity_version;
   Atom atom_net_wm_visible_name;
   Atom atom_net_wm_visible_icon_name;
+  Atom atom_net_wm_geometry_save_id;
 
   /* This is the actual window from focus events,
    * not the one we last set
Only in metacity/src: history.c
Only in metacity/src: history.h
diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/keybindings.c metacity/src/keybindings.c
--- metacity-new/src/keybindings.c	2006-04-17 23:29:49.000000000 -0400
+++ metacity/src/keybindings.c	2006-04-16 15:33:06.000000000 -0400
@@ -639,22 +639,13 @@
   i = 0;
   while (i < n_prefs)
     {
-      GSList *tmp = prefs[i].bindings;
-
-      while (tmp)
+      if (prefs[i].keysym != None)
         {
-          MetaKeyCombo *combo = tmp->data;
-
-          if (combo && combo->keysym != None)
-            {
-              count += 1;
-
-              if (prefs[i].add_shift &&
-                  (combo->modifiers & META_VIRTUAL_SHIFT_MASK) == 0)
-                count += 1;
-            }
+          count += 1;
 
-          tmp = tmp->next;
+          if (prefs[i].add_shift &&
+              (prefs[i].modifiers & META_VIRTUAL_SHIFT_MASK) == 0)
+            count += 1;
         }
       
       ++i;
@@ -681,41 +672,32 @@
   dest = 0;
   while (src < n_prefs)
     {
-      GSList *tmp = prefs[src].bindings;
-
-      while (tmp)
+      if (prefs[src].keysym != None)
         {
-          MetaKeyCombo *combo = tmp->data;
+          (*bindings_p)[dest].name = prefs[src].name;
+          (*bindings_p)[dest].keysym = prefs[src].keysym;
+          (*bindings_p)[dest].modifiers = prefs[src].modifiers;
+          (*bindings_p)[dest].mask = 0;
+          (*bindings_p)[dest].keycode = 0;          
+          
+          ++dest;
 
-          if (combo && combo->keysym != None)
+          if (prefs[src].add_shift &&
+              (prefs[src].modifiers & META_VIRTUAL_SHIFT_MASK) == 0)
             {
+              meta_topic (META_DEBUG_KEYBINDINGS,
+                          "Binding %s also needs Shift grabbed\n",
+                          prefs[src].name);
+              
               (*bindings_p)[dest].name = prefs[src].name;
-              (*bindings_p)[dest].keysym = combo->keysym;
-              (*bindings_p)[dest].modifiers = combo->modifiers;
+              (*bindings_p)[dest].keysym = prefs[src].keysym;
+              (*bindings_p)[dest].modifiers = prefs[src].modifiers |
+                META_VIRTUAL_SHIFT_MASK;
               (*bindings_p)[dest].mask = 0;
               (*bindings_p)[dest].keycode = 0;          
-          
-              ++dest;
-
-              if (prefs[src].add_shift &&
-                  (combo->modifiers & META_VIRTUAL_SHIFT_MASK) == 0)
-                {
-                  meta_topic (META_DEBUG_KEYBINDINGS,
-                              "Binding %s also needs Shift grabbed\n",
-                               prefs[src].name);
               
-                  (*bindings_p)[dest].name = prefs[src].name;
-                  (*bindings_p)[dest].keysym = combo->keysym;
-                  (*bindings_p)[dest].modifiers = combo->modifiers |
-                    META_VIRTUAL_SHIFT_MASK;
-                  (*bindings_p)[dest].mask = 0;
-                  (*bindings_p)[dest].keycode = 0;          
-              
-                  ++dest;
-                }
+              ++dest;
             }
-            
-          tmp = tmp->next;
         }
       
       ++src;
diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/main.c metacity/src/main.c
--- metacity-new/src/main.c	2006-01-10 14:43:21.000000000 -0500
+++ metacity/src/main.c	2006-04-01 23:11:45.000000000 -0500
@@ -26,6 +26,7 @@
 #include "display.h"
 #include "errors.h"
 #include "ui.h"
+#include "history.h"
 #include "session.h"
 #include "prefs.h"
 
@@ -386,6 +387,9 @@
 
   meta_ui_init (&argc, &argv);  
 
+  /* Load the window history so we can place windows. */
+  meta_history_init ();
+
   /* must be after UI init so we can override GDK handlers */
   meta_errors_init ();
 
@@ -509,6 +513,7 @@
   }
 
   meta_session_shutdown ();
+  meta_history_shutdown ();
   
   if (meta_restart_after_quit)
     {
diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/Makefile.am metacity/src/Makefile.am
--- metacity-new/src/Makefile.am	2006-03-03 10:53:09.000000000 -0500
+++ metacity/src/Makefile.am	2006-04-01 23:11:45.000000000 -0500
@@ -70,6 +70,8 @@
 	resizepopup.h				\
 	screen.c				\
 	screen.h				\
+	history.c				\
+	history.h				\
 	session.c				\
 	session.h				\
 	spring-model.c				\
diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/place.c metacity/src/place.c
--- metacity-new/src/place.c	2006-01-20 17:03:55.000000000 -0500
+++ metacity/src/place.c	2006-04-17 14:29:15.000000000 -0400
@@ -25,6 +25,7 @@
 #include <config.h>
 
 #include "place.h"
+#include "history.h"
 #include "workspace.h"
 #include "prefs.h"
 #include <gdk/gdkregion.h>
@@ -529,6 +530,98 @@
   rect->y = work_area->y + fluff;
 }
 
+/* Lookup the window position used before and try to use that
+ * again.  
+ * 
+ * We need to watch out for windows already placed in that
+ * position and fail if we find one.
+ */
+static gboolean
+find_last_placement (MetaWindow *window,
+		     MetaFrameGeometry *fgeom,
+		     /* visible windows on relevant workspaces */
+		     GList      *windows,
+		     int         x,
+		     int         y,
+		     int        *new_x,
+		     int        *new_y)
+{
+  MetaWindowHistoryInfo *old_place = NULL, *old_size = NULL;
+  int place_x, place_y;
+  int x_threshold, y_threshold;
+  GList *tmp;
+
+  meta_history_next_window_full (windows, window);
+  old_place = meta_history_lookup (window);
+  old_size  = meta_history_lookup_size (window);
+  
+  /* If we can't find any data, just return. */
+  if (!old_place) return FALSE;
+
+  place_x = old_place->rect.x;
+  place_y = old_place->rect.y;
+
+  /* Now we need to scan through all the windows looking 
+   * for those which are close to us, return FALSE if we
+   * find something like that.
+   */
+
+  if (fgeom)
+    {
+      x_threshold = MAX (fgeom->left_width, 15);
+      y_threshold = MAX (fgeom->top_height, 15);
+    }
+  else
+    {
+      x_threshold = 15;
+      y_threshold = 15;
+    }
+
+  tmp = windows;
+  while (tmp != NULL)
+    {
+      MetaWindow *w;
+      int wx, wy;
+
+      w = tmp->data;
+      
+      /* we want frame position, not window position */
+      if (w->frame)
+        {
+          wx = w->frame->rect.x;
+          wy = w->frame->rect.y;
+        }
+      else
+        {
+          wx = w->rect.x;
+          wy = w->rect.y;
+        }
+      
+      if (ABS (wx - place_x) <= x_threshold &&
+          ABS (wy - place_y) <= y_threshold)
+        {
+	  /* Oops.  Something is already there.  Abort! */
+	  return FALSE;
+	}
+      tmp = tmp->next;
+    }
+
+  *new_x = place_x;
+  *new_y = place_y;
+
+#if 1
+  /* This is probably the wrong place to be doing this, but we have 
+   * all the information here.  Now we restore window size and state.
+   */
+  meta_history_restore_window (old_place, old_size, window);
+
+#endif
+
+  /* FIXME: Should we change the size of the window as well? */
+
+  return TRUE;
+}
+
 /* Find the leftmost, then topmost, empty area on the workspace
  * that can contain the new window.
  *
@@ -889,7 +982,7 @@
       goto done_check_denied_focus;
     }
   
-  /* Find windows that matter (not minimized, on same workspace
+  /* Find windows that matter (on same workspace
    * as placed window, may be shaded - if shaded we pretend it isn't
    * for placement purposes)
    */
@@ -905,7 +998,6 @@
         MetaWindow *w = tmp->data;
 
         if (meta_window_showing_on_its_workspace (w) &&
-            w != window && 
             (window->workspace == w->workspace ||
              window->on_all_workspaces || w->on_all_workspaces))
           windows = g_list_prepend (windows, w);
@@ -923,6 +1015,10 @@
   x = xi->rect.x;
   y = xi->rect.y;
 
+  /* If we already know where the user likes their window, use that. */
+  if (find_last_placement (window, fgeom, windows, x, y, &x, &y))
+    goto done;
+  
   if (find_first_fit (window, fgeom, windows,
                       xineramas_list, n_xineramas,
                       x, y, &x, &y))
diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/prefs.c metacity/src/prefs.c
--- metacity-new/src/prefs.c	2006-04-17 23:29:49.000000000 -0400
+++ metacity/src/prefs.c	2006-04-16 15:33:06.000000000 -0400
@@ -63,7 +63,6 @@
 
 #define KEY_SCREEN_BINDINGS_PREFIX "/apps/metacity/global_keybindings"
 #define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings"
-#define KEY_LIST_BINDINGS_SUFFIX "_list"
 
 #define KEY_WORKSPACE_NAME_PREFIX "/apps/metacity/workspace_names/name_"
 
@@ -147,13 +146,6 @@
                                            const char *value);
 static gboolean update_screen_binding     (const char *name,
                                            const char *value);
-static gboolean find_and_update_list_binding (MetaKeyPref *bindings,
-                                              const char  *name,
-                                              GSList      *value);
-static gboolean update_window_list_binding (const char *name,
-                                            GSList      *value);
-static gboolean update_screen_list_binding (const char *name,
-                                            GSList      *value);
 static gboolean update_command            (const char  *name,
                                            const char  *value);
 static gboolean update_terminal_command   (const char *value);
@@ -177,16 +169,6 @@
 static gboolean update_binding            (MetaKeyPref *binding,
                                            const char  *value);
 
-typedef enum
-  {
-    META_LIST_OF_STRINGS,
-    META_LIST_OF_GCONFVALUE_STRINGS
-  } MetaStringListType;
-
-static gboolean update_list_binding       (MetaKeyPref *binding,
-                                           GSList      *value,
-                                           MetaStringListType type_of_value);
-
 static void     init_bindings             (void);
 static void     init_commands             (void);
 static void     init_workspace_names      (void);
@@ -731,73 +713,35 @@
     }
   else if (g_str_has_prefix (key, KEY_WINDOW_BINDINGS_PREFIX))
     {
-      if (g_str_has_suffix (key, KEY_LIST_BINDINGS_SUFFIX))
-        {
-          GSList *list;
-
-          if (value && value->type != GCONF_VALUE_LIST)
-            {
-              meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
-                            key);
-              goto out;
-            }
-
-          list = value ? gconf_value_get_list (value) : NULL;
+      const char *str;
 
-          if (update_window_list_binding (key, list))
-             queue_changed (META_PREF_WINDOW_KEYBINDINGS);
-        }
-      else
+      if (value && value->type != GCONF_VALUE_STRING)
         {
-          const char *str;
-
-          if (value && value->type != GCONF_VALUE_STRING)
-            {
-              meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
-                            key);
-              goto out;
-            }
+          meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
+                        key);
+          goto out;
+        }
 
-          str = value ? gconf_value_get_string (value) : NULL;
+      str = value ? gconf_value_get_string (value) : NULL;
 
-          if (update_window_binding (key, str))
-             queue_changed (META_PREF_WINDOW_KEYBINDINGS);
-        }
+      if (update_window_binding (key, str))
+        queue_changed (META_PREF_WINDOW_KEYBINDINGS);
     }
   else if (g_str_has_prefix (key, KEY_SCREEN_BINDINGS_PREFIX))
     {
-      if (g_str_has_suffix (key, KEY_LIST_BINDINGS_SUFFIX))
-        {
-          GSList *list;
-
-          if (value && value->type != GCONF_VALUE_LIST)
-            {
-              meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
-                            key);
-              goto out;
-            }
-
-          list = value ? gconf_value_get_list (value) : NULL;
+      const char *str;
 
-          if (update_screen_list_binding (key, list))
-             queue_changed (META_PREF_SCREEN_KEYBINDINGS);
-         }
-      else
+      if (value && value->type != GCONF_VALUE_STRING)
         {
-          const char *str;
-
-          if (value && value->type != GCONF_VALUE_STRING)
-            {
-               meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
-                            key);
-               goto out;
-            }
+          meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
+                        key);
+          goto out;
+        }
 
-          str = value ? gconf_value_get_string (value) : NULL;
+      str = value ? gconf_value_get_string (value) : NULL;
 
-          if (update_screen_binding (key, str))
-             queue_changed (META_PREF_SCREEN_KEYBINDINGS);
-        }
+      if (update_screen_binding (key, str))
+        queue_changed (META_PREF_SCREEN_KEYBINDINGS);
     }
   else if (strcmp (key, KEY_ACTION_DOUBLE_CLICK_TITLEBAR) == 0)
     {
@@ -1793,110 +1737,110 @@
 
 /* Indexes must correspond to MetaKeybindingAction */
 static MetaKeyPref screen_bindings[] = {
-  { META_KEYBINDING_WORKSPACE_1, NULL, FALSE },
-  { META_KEYBINDING_WORKSPACE_2, NULL, FALSE },
-  { META_KEYBINDING_WORKSPACE_3, NULL, FALSE },
-  { META_KEYBINDING_WORKSPACE_4, NULL, FALSE },
-  { META_KEYBINDING_WORKSPACE_5, NULL, FALSE },
-  { META_KEYBINDING_WORKSPACE_6, NULL, FALSE },
-  { META_KEYBINDING_WORKSPACE_7, NULL, FALSE },
-  { META_KEYBINDING_WORKSPACE_8, NULL, FALSE }, 
-  { META_KEYBINDING_WORKSPACE_9, NULL, FALSE },
-  { META_KEYBINDING_WORKSPACE_10, NULL, FALSE },
-  { META_KEYBINDING_WORKSPACE_11, NULL, FALSE },
-  { META_KEYBINDING_WORKSPACE_12, NULL, FALSE },
-  { META_KEYBINDING_WORKSPACE_LEFT, NULL, FALSE },
-  { META_KEYBINDING_WORKSPACE_RIGHT, NULL, FALSE },
-  { META_KEYBINDING_WORKSPACE_UP, NULL, FALSE },
-  { META_KEYBINDING_WORKSPACE_DOWN, NULL, FALSE },
-  { META_KEYBINDING_SWITCH_GROUP, NULL, TRUE },
-  { META_KEYBINDING_SWITCH_GROUP_BACKWARD, NULL, TRUE },
-  { META_KEYBINDING_SWITCH_WINDOWS, NULL, TRUE },
-  { META_KEYBINDING_SWITCH_WINDOWS_BACKWARD, NULL, TRUE },
-  { META_KEYBINDING_SWITCH_PANELS, NULL, TRUE },
-  { META_KEYBINDING_SWITCH_PANELS_BACKWARD, NULL, TRUE },
-  { META_KEYBINDING_CYCLE_GROUP, NULL, TRUE },
-  { META_KEYBINDING_CYCLE_GROUP_BACKWARD, NULL, TRUE },
-  { META_KEYBINDING_CYCLE_WINDOWS, NULL, TRUE },
-  { META_KEYBINDING_CYCLE_WINDOWS_BACKWARD, NULL, TRUE },
-  { META_KEYBINDING_CYCLE_PANELS, NULL, TRUE },
-  { META_KEYBINDING_CYCLE_PANELS_BACKWARD, NULL, TRUE },
-  { META_KEYBINDING_SHOW_DESKTOP, NULL, FALSE },
-  { META_KEYBINDING_PANEL_MAIN_MENU, NULL, FALSE },
-  { META_KEYBINDING_PANEL_RUN_DIALOG, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_1, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_2, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_3, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_4, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_5, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_6, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_7, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_8, NULL, FALSE }, 
-  { META_KEYBINDING_COMMAND_9, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_10, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_11, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_12, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_13, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_14, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_15, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_16, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_17, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_18, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_19, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_20, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_21, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_22, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_23, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_24, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_25, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_26, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_27, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_28, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_29, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_30, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_31, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_32, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_SCREENSHOT, NULL, FALSE },
-  { META_KEYBINDING_COMMAND_WIN_SCREENSHOT, NULL, FALSE },
-  { META_KEYBINDING_RUN_COMMAND_TERMINAL, NULL, FALSE },
-  { NULL, NULL, FALSE}
+  { META_KEYBINDING_WORKSPACE_1, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_2, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_3, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_4, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_5, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_6, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_7, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_8, 0, 0, FALSE }, 
+  { META_KEYBINDING_WORKSPACE_9, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_10, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_11, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_12, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_LEFT, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_RIGHT, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_UP, 0, 0, FALSE },
+  { META_KEYBINDING_WORKSPACE_DOWN, 0, 0, FALSE },
+  { META_KEYBINDING_SWITCH_GROUP, 0, 0, TRUE },
+  { META_KEYBINDING_SWITCH_GROUP_BACKWARD, 0, 0, TRUE },
+  { META_KEYBINDING_SWITCH_WINDOWS, 0, 0, TRUE },
+  { META_KEYBINDING_SWITCH_WINDOWS_BACKWARD, 0, 0, TRUE },
+  { META_KEYBINDING_SWITCH_PANELS, 0, 0, TRUE },
+  { META_KEYBINDING_SWITCH_PANELS_BACKWARD, 0, 0, TRUE },
+  { META_KEYBINDING_CYCLE_GROUP, 0, 0, TRUE },
+  { META_KEYBINDING_CYCLE_GROUP_BACKWARD, 0, 0, TRUE },
+  { META_KEYBINDING_CYCLE_WINDOWS, 0, 0, TRUE },
+  { META_KEYBINDING_CYCLE_WINDOWS_BACKWARD, 0, 0, TRUE },
+  { META_KEYBINDING_CYCLE_PANELS, 0, 0, TRUE },
+  { META_KEYBINDING_CYCLE_PANELS_BACKWARD, 0, 0, TRUE },
+  { META_KEYBINDING_SHOW_DESKTOP, 0, 0, FALSE },
+  { META_KEYBINDING_PANEL_MAIN_MENU, 0, 0, FALSE },
+  { META_KEYBINDING_PANEL_RUN_DIALOG, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_1, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_2, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_3, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_4, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_5, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_6, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_7, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_8, 0, 0, FALSE }, 
+  { META_KEYBINDING_COMMAND_9, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_10, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_11, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_12, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_13, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_14, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_15, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_16, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_17, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_18, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_19, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_20, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_21, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_22, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_23, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_24, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_25, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_26, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_27, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_28, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_29, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_30, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_31, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_32, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_SCREENSHOT, 0, 0, FALSE },
+  { META_KEYBINDING_COMMAND_WIN_SCREENSHOT, 0, 0, FALSE },
+  { META_KEYBINDING_RUN_COMMAND_TERMINAL, 0, 0, FALSE },
+  { NULL, 0, 0, FALSE}
 };
 
 static MetaKeyPref window_bindings[] = {
-  { META_KEYBINDING_WINDOW_MENU, NULL, FALSE },
-  { META_KEYBINDING_TOGGLE_FULLSCREEN, NULL, FALSE },
-  { META_KEYBINDING_TOGGLE_MAXIMIZE, NULL, FALSE },
-  { META_KEYBINDING_TOGGLE_ABOVE, NULL, FALSE },
-  { META_KEYBINDING_MAXIMIZE, NULL, FALSE },
-  { META_KEYBINDING_UNMAXIMIZE, NULL, FALSE },
-  { META_KEYBINDING_TOGGLE_SHADE, NULL, FALSE },
-  { META_KEYBINDING_MINIMIZE, NULL, FALSE },
-  { META_KEYBINDING_CLOSE, NULL, FALSE },
-  { META_KEYBINDING_BEGIN_MOVE, NULL, FALSE },
-  { META_KEYBINDING_BEGIN_RESIZE, NULL, FALSE },
-  { META_KEYBINDING_TOGGLE_STICKY, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_1, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_2, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_3, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_4, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_5, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_6, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_7, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_8, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_9, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_10, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_11, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_12, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_LEFT, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_RIGHT, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_UP, NULL, FALSE },
-  { META_KEYBINDING_MOVE_WORKSPACE_DOWN, NULL, FALSE },
-  { META_KEYBINDING_RAISE_OR_LOWER, NULL, FALSE },
-  { META_KEYBINDING_RAISE, NULL, FALSE },
-  { META_KEYBINDING_LOWER, NULL, FALSE },
-  { META_KEYBINDING_MAXIMIZE_VERTICALLY, NULL, FALSE },
-  { META_KEYBINDING_MAXIMIZE_HORIZONTALLY, NULL, FALSE },
-  { NULL, NULL, FALSE }
+  { META_KEYBINDING_WINDOW_MENU, 0, 0, FALSE },
+  { META_KEYBINDING_TOGGLE_FULLSCREEN, 0, 0, FALSE },
+  { META_KEYBINDING_TOGGLE_MAXIMIZE, 0, 0, FALSE },
+  { META_KEYBINDING_TOGGLE_ABOVE, 0, 0, FALSE },
+  { META_KEYBINDING_MAXIMIZE, 0, 0, FALSE },
+  { META_KEYBINDING_UNMAXIMIZE, 0, 0, FALSE },
+  { META_KEYBINDING_TOGGLE_SHADE, 0, 0, FALSE },
+  { META_KEYBINDING_MINIMIZE, 0, 0, FALSE },
+  { META_KEYBINDING_CLOSE, 0, 0, FALSE },
+  { META_KEYBINDING_BEGIN_MOVE, 0, 0, FALSE },
+  { META_KEYBINDING_BEGIN_RESIZE, 0, 0, FALSE },
+  { META_KEYBINDING_TOGGLE_STICKY, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_1, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_2, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_3, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_4, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_5, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_6, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_7, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_8, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_9, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_10, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_11, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_12, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_LEFT, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_RIGHT, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_UP, 0, 0, FALSE },
+  { META_KEYBINDING_MOVE_WORKSPACE_DOWN, 0, 0, FALSE },
+  { META_KEYBINDING_RAISE_OR_LOWER, 0, 0, FALSE },
+  { META_KEYBINDING_RAISE, 0, 0, FALSE },
+  { META_KEYBINDING_LOWER, 0, 0, FALSE },
+  { META_KEYBINDING_MAXIMIZE_VERTICALLY, 0, 0, FALSE },
+  { META_KEYBINDING_MAXIMIZE_HORIZONTALLY, 0, 0, FALSE },
+  { NULL, 0, 0, FALSE }
 };
 
 #ifndef HAVE_GCONF
@@ -1956,7 +1900,6 @@
   i = 0;
   while (window_bindings[i].name)
     {
-      GSList *list_val, *tmp;
       char *str_val;
       char *key;
 
@@ -1972,33 +1915,12 @@
       g_free (str_val);      
       g_free (key);
 
-      key = g_strconcat (KEY_WINDOW_BINDINGS_PREFIX, "/",
-                         window_bindings[i].name,
-                         KEY_LIST_BINDINGS_SUFFIX, NULL);
-
-      err = NULL;
-
-      list_val = gconf_client_get_list (default_client, key, GCONF_VALUE_STRING, &err);
-      cleanup_error (&err);
-
-      update_list_binding (&window_bindings[i], list_val, META_LIST_OF_STRINGS);
-
-      tmp = list_val;
-      while (tmp)
-        {
-          g_free (tmp->data);
-          tmp = tmp->next;
-        }
-      g_slist_free (list_val);
-      g_free (key);
-
       ++i;
     }
 
   i = 0;
   while (screen_bindings[i].name)
     {
-      GSList *list_val, *tmp;
       char *str_val;
       char *key;
 
@@ -2014,26 +1936,6 @@
       g_free (str_val);      
       g_free (key);
 
-      key = g_strconcat (KEY_SCREEN_BINDINGS_PREFIX, "/",
-                         screen_bindings[i].name,
-                         KEY_LIST_BINDINGS_SUFFIX, NULL);
-
-      err = NULL;
-
-      list_val = gconf_client_get_list (default_client, key, GCONF_VALUE_STRING, &err);
-      cleanup_error (&err);
-
-      update_list_binding (&screen_bindings[i], list_val, META_LIST_OF_STRINGS);
-
-      tmp = list_val;
-      while (tmp)
-        {
-          g_free (tmp->data);
-          tmp = tmp->next;
-        }
-      g_slist_free (list_val);
-      g_free (key);
-
       ++i;
     }
 #else /* HAVE_GCONF */
@@ -2152,7 +2054,6 @@
 {
   unsigned int keysym;
   MetaVirtualModifier mods;
-  MetaKeyCombo *combo;
   gboolean changed;
   
   meta_topic (META_DEBUG_KEYBINDINGS,
@@ -2174,17 +2075,7 @@
         }
     }
 
-  /* If there isn't already a first element, make one. */
-  if (!binding->bindings)
-    {
-      MetaKeyCombo *blank = g_malloc0 (sizeof (MetaKeyCombo));
-      binding->bindings = g_slist_alloc();
-      binding->bindings->data = blank;
-    }
-  
-   combo = binding->bindings->data;
-
-   /* Bug 329676: Bindings which can be shifted must not have no modifiers,
+  /* Bug 329676: Bindings which can be shifted must not have no modifiers,
    * nor only SHIFT as a modifier.
    */
 
@@ -2202,8 +2093,8 @@
                     value);
 
       old_setting = meta_ui_accelerator_name(
-                      combo->keysym,
-                      combo->modifiers);
+                      binding->keysym,
+                      binding->modifiers);
       
       if (!strcmp(old_setting, value))
         {
@@ -2245,17 +2136,17 @@
     }
   
   changed = FALSE;
-  if (keysym != combo->keysym ||
-      mods != combo->modifiers)
+  if (keysym != binding->keysym ||
+      mods != binding->modifiers)
     {
       changed = TRUE;
       
-      combo->keysym = keysym;
-      combo->modifiers = mods;
+      binding->keysym = keysym;
+      binding->modifiers = mods;
       
       meta_topic (META_DEBUG_KEYBINDINGS,
                   "New keybinding for \"%s\" is keysym = 0x%x mods = 0x%x\n",
-                  binding->name, combo->keysym, combo->modifiers);
+                  binding->name, binding->keysym, binding->modifiers);
     }
   else
     {
@@ -2266,115 +2157,6 @@
   return changed;
 }
 
-static gboolean
-update_list_binding (MetaKeyPref *binding,
-                     GSList      *value,
-                     MetaStringListType type_of_value)
-{
-  unsigned int keysym;
-  MetaVirtualModifier mods;
-  gboolean changed = FALSE;
-  const gchar *pref_string;
-  GSList *pref_iterator = value, *tmp;
-  MetaKeyCombo *combo;
-
-  meta_topic (META_DEBUG_KEYBINDINGS,
-              "Binding \"%s\" has new gconf value\n",
-              binding->name);
-  
-  if (binding->bindings == NULL)
-    {
-      /* We need to insert a dummy element into the list, because the first
-       * element is the one governed by update_binding. We only handle the
-       * subsequent elements.
-       */
-      MetaKeyCombo *blank = g_malloc0 (sizeof (MetaKeyCombo));
-      binding->bindings = g_slist_alloc();
-      binding->bindings->data = blank;
-    }
-       
-  /* Okay, so, we're about to provide a new list of key combos for this
-   * action. Delete any pre-existing list.
-   */
-  tmp = binding->bindings->next;
-  while (tmp)
-    {
-      g_free (tmp->data);
-      tmp = tmp->next;
-    }
-  g_slist_free (binding->bindings->next);
-  binding->bindings->next = NULL;
-  
-  while (pref_iterator)
-    {
-      keysym = 0;
-      mods = 0;
-
-      if (!pref_iterator->data)
-        {
-          pref_iterator = pref_iterator->next;
-          continue;
-        }
-
-      switch (type_of_value)
-        {
-        case META_LIST_OF_STRINGS:
-          pref_string = pref_iterator->data;
-          break;
-        case META_LIST_OF_GCONFVALUE_STRINGS:
-          pref_string = gconf_value_get_string (pref_iterator->data);
-          break;
-        default:
-          g_assert_not_reached ();
-        }
-      
-      if (!meta_ui_parse_accelerator (pref_string, &keysym, &mods))
-        {
-          meta_topic (META_DEBUG_KEYBINDINGS,
-                      "Failed to parse new gconf value\n");
-          meta_warning (_("\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n"),
-                        pref_string, binding->name);
-
-          /* Should we remove this value from the list in gconf? */
-          pref_iterator = pref_iterator->next;
-          continue;
-        }
-
-      /* Bug 329676: Bindings which can be shifted must not have no modifiers,
-       * nor only SHIFT as a modifier.
-       */
-
-      if (binding->add_shift &&
-          0 != keysym &&
-          (META_VIRTUAL_SHIFT_MASK == mods || 0 == mods))
-        {
-          meta_warning ("Cannot bind \"%s\" to %s: it needs a modifier "
-                        "such as Ctrl or Alt.\n",
-                        binding->name,
-                        pref_string);
-
-          /* Should we remove this value from the list in gconf? */
-
-          pref_iterator = pref_iterator->next;
-          continue;
-        }
-  
-      changed = TRUE;
-
-      combo = g_malloc0 (sizeof (MetaKeyCombo));
-      combo->keysym = keysym;
-      combo->modifiers = mods;
-      binding->bindings->next = g_slist_prepend (binding->bindings->next, combo);
-
-      meta_topic (META_DEBUG_KEYBINDINGS,
-                      "New keybinding for \"%s\" is keysym = 0x%x mods = 0x%x\n",
-                      binding->name, keysym, mods);
-
-      pref_iterator = pref_iterator->next;
-    }  
-  return changed;
-}
-
 #ifdef HAVE_GCONF
 static const gchar*
 relative_key (const gchar* key)
@@ -2430,50 +2212,6 @@
 }
 
 static gboolean
-find_and_update_list_binding (MetaKeyPref *bindings,
-                              const char  *name,
-                              GSList      *value)
-{
-  const char *key;
-  int i;
-  gchar *name_without_suffix = g_strdup(name);
-
-  name_without_suffix[strlen(name_without_suffix) - strlen(KEY_LIST_BINDINGS_SUFFIX)] = 0;
-
-  /* FIXME factor out dupld code */
-  if (*name_without_suffix == '/')
-    key = relative_key (name_without_suffix);
-  else
-    key = name_without_suffix;
-
-  i = 0;
-  while (bindings[i].name &&
-         strcmp (key, bindings[i].name) != 0)
-    ++i;
-
-  g_free (name_without_suffix);
-
-  if (bindings[i].name)
-    return update_list_binding (&bindings[i], value, META_LIST_OF_GCONFVALUE_STRINGS);
-  else
-    return FALSE;
-}
-
-static gboolean
-update_window_list_binding (const char *name,
-                            GSList *value)
-{
-  return find_and_update_list_binding (window_bindings, name, value);
-}
-
-static gboolean
-update_screen_list_binding (const char *name,
-                            GSList *value)
-{
-  return find_and_update_list_binding (screen_bindings, name, value);
-}
-
-static gboolean
 update_command (const char  *name,
                 const char  *value)
 {
@@ -2860,10 +2598,6 @@
   return META_KEYBINDING_ACTION_NONE;
 }
 
-/* This is used by the menu system to decide what key binding
- * to display next to an option. We return the first non-disabled
- * binding, if any.
- */
 void
 meta_prefs_get_window_binding (const char          *name,
                                unsigned int        *keysym,
@@ -2876,24 +2610,8 @@
     {
       if (strcmp (window_bindings[i].name, name) == 0)
         {
-          GSList *s = window_bindings[i].bindings;
-
-          while (s)
-            {
-              MetaKeyCombo *c = s->data;
-
-              if (c->keysym!=0 || c->modifiers!=0)
-                {
-                  *keysym = c->keysym;
-                  *modifiers = c->modifiers;
-                  return;
-                }
-
-              s = s->next;
-            }
-
-          /* Not found; return the disabled value */
-          *keysym = *modifiers = 0;
+          *keysym = window_bindings[i].keysym;
+          *modifiers = window_bindings[i].modifiers;
           return;
         }
       
diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/prefs.h metacity/src/prefs.h
--- metacity-new/src/prefs.h	2006-04-17 23:29:49.000000000 -0400
+++ metacity/src/prefs.h	2006-04-16 15:33:06.000000000 -0400
@@ -256,21 +256,9 @@
 
 typedef struct
 {
-  unsigned int keysym;
-  MetaVirtualModifier modifiers;
-} MetaKeyCombo;
-
-typedef struct
-{
   const char   *name;
-  /* a list of MetaKeyCombos. Each of them is bound to
-   * this keypref. If one has keysym==modifiers==0, it is
-   * ignored. For historical reasons, the first entry is
-   * governed by the pref FOO and the remainder are
-   * governed by the pref FOO_list.
-   */
-  GSList *bindings;
-
+  unsigned int  keysym;
+  MetaVirtualModifier modifiers;
   /* for keybindings that can have shift or not like Alt+Tab */
   gboolean      add_shift;
 } MetaKeyPref;
diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/session.c metacity/src/session.c
--- metacity-new/src/session.c	2006-01-20 17:03:55.000000000 -0500
+++ metacity/src/session.c	2006-04-02 23:13:02.000000000 -0400
@@ -666,7 +666,7 @@
  * session manager.
  */
 
-static const char*
+const char*
 window_type_to_string (MetaWindowType type)
 {
   switch (type)
@@ -694,7 +694,7 @@
   return "";
 } 
 
-static MetaWindowType
+MetaWindowType
 window_type_from_string (const char *str)
 {
   if (strcmp (str, "normal") == 0)
@@ -719,7 +719,7 @@
     return META_WINDOW_NORMAL;
 }
 
-static int
+int
 window_gravity_from_string (const char *str)
 {
   if (strcmp (str, "NorthWestGravity") == 0)
@@ -746,52 +746,6 @@
     return NorthWestGravity;
 }
 
-static char*
-encode_text_as_utf8_markup (const char *text)
-{
-  /* text can be any encoding, and is nul-terminated.
-   * we pretend it's Latin-1 and encode as UTF-8
-   */
-  GString *str;
-  const char *p;
-  char *escaped;
-  
-  str = g_string_new ("");
-
-  p = text;
-  while (*p)
-    {
-      g_string_append_unichar (str, *p);
-      ++p;
-    }
-
-  escaped = g_markup_escape_text (str->str, str->len);
-  g_string_free (str, TRUE);
-  
-  return escaped;
-}
-
-static char*
-decode_text_from_utf8 (const char *text)
-{
-  /* Convert back from the encoded (but not escaped) UTF-8 */
-  GString *str;
-  const char *p;
-
-  str = g_string_new ("");
-  
-  p = text;
-  while (*p)
-    {
-      /* obviously this barfs if the UTF-8 contains chars > 255 */
-      g_string_append_c (str, g_utf8_get_char (p));
-
-      p = g_utf8_next_char (p);
-    }
-
-  return g_string_free (str, FALSE);
-}
-
 static int
 stack_cmp (const void *a,
            const void *b)
@@ -1481,18 +1435,6 @@
    */
 }
 
-static gboolean
-both_null_or_matching (const char *a,
-                       const char *b)
-{
-  if (a == NULL && b == NULL)
-    return TRUE;
-  else if (a && b && strcmp (a, b) == 0)
-    return TRUE;
-  else
-    return FALSE;
-}
-
 static GSList*
 get_possible_matches (MetaWindow *window)
 {
diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/util.c metacity/src/util.c
--- metacity-new/src/util.c	2006-03-16 21:55:21.000000000 -0500
+++ metacity/src/util.c	2006-04-02 22:46:51.000000000 -0400
@@ -305,6 +305,8 @@
       return "COMPOSITOR";
     case META_DEBUG_EDGE_RESISTANCE:
       return "EDGE_RESISTANCE";
+    case META_DEBUG_HISTORY:
+      return "HISTORY";
     }
 
   return "WM";
@@ -509,3 +511,62 @@
       break;
     }
 }
+
+gboolean
+both_null_or_matching (const char *a,
+                       const char *b)
+{
+  if (a == NULL && b == NULL)
+    return TRUE;
+  else if (a && b && strcmp (a, b) == 0)
+    return TRUE;
+  else
+    return FALSE;
+}
+
+char*
+encode_text_as_utf8_markup (const char *text)
+{
+  /* text can be any encoding, and is nul-terminated.
+   * we pretend it's Latin-1 and encode as UTF-8
+   */
+  GString *str;
+  const char *p;
+  char *escaped;
+  
+  str = g_string_new ("");
+
+  p = text;
+  while (*p)
+    {
+      g_string_append_unichar (str, *p);
+      ++p;
+    }
+
+  escaped = g_markup_escape_text (str->str, str->len);
+  g_string_free (str, TRUE);
+  
+  return escaped;
+}
+
+char*
+decode_text_from_utf8 (const char *text)
+{
+  /* Convert back from the encoded (but not escaped) UTF-8 */
+  GString *str;
+  const char *p;
+
+  str = g_string_new ("");
+  
+  p = text;
+  while (*p)
+    {
+      /* obviously this barfs if the UTF-8 contains chars > 255 */
+      g_string_append_c (str, g_utf8_get_char (p));
+
+      p = g_utf8_next_char (p);
+    }
+
+  return g_string_free (str, FALSE);
+}
+
diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/util.h metacity/src/util.h
--- metacity-new/src/util.h	2006-03-16 21:55:21.000000000 -0500
+++ metacity/src/util.h	2006-04-02 22:47:37.000000000 -0400
@@ -69,7 +69,8 @@
   META_DEBUG_RESIZING        = 1 << 18,
   META_DEBUG_SHAPES          = 1 << 19,
   META_DEBUG_COMPOSITOR      = 1 << 20,
-  META_DEBUG_EDGE_RESISTANCE = 1 << 21
+  META_DEBUG_EDGE_RESISTANCE = 1 << 21,
+  META_DEBUG_HISTORY         = 1 << 22
 } MetaDebugTopic;
 
 void meta_topic_real      (MetaDebugTopic topic,
@@ -83,6 +84,12 @@
                                 gconstpointer v2);
 guint meta_unsigned_long_hash  (gconstpointer v);
 
+gboolean both_null_or_matching (const char            *a,
+				const char            *b);
+
+char* encode_text_as_utf8_markup (const char *text);
+char* decode_text_from_utf8      (const char *text);
+
 void meta_print_backtrace (void);
 
 const char* meta_gravity_to_string (int gravity);
diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/window.c metacity/src/window.c
--- metacity-new/src/window.c	2006-04-17 23:29:49.000000000 -0400
+++ metacity/src/window.c	2006-04-17 13:16:44.000000000 -0400
@@ -33,6 +33,7 @@
 #include "keybindings.h"
 #include "ui.h"
 #include "place.h"
+#include "history.h"
 #include "session.h"
 #include "effects.h"
 #include "prefs.h"
@@ -57,6 +58,7 @@
 static void     update_role               (MetaWindow     *window);
 static void     update_net_wm_type        (MetaWindow     *window);
 static void     update_net_frame_extents  (MetaWindow     *window);
+static void     update_geometry_save_id   (MetaWindow     *window);
 static void     recalc_window_type        (MetaWindow     *window);
 static void     recalc_window_features    (MetaWindow     *window);
 static void     invalidate_work_areas     (MetaWindow     *window);
@@ -116,9 +118,7 @@
 static void meta_window_apply_session_info (MetaWindow                  *window,
                                             const MetaWindowSessionInfo *info);
 
-static void unmaximize_window_before_freeing (MetaWindow        *window);
-static void unminimize_window_and_all_transient_parents (MetaWindow *window);
-
+static void     unmaximize_window_before_freeing (MetaWindow        *window);
 
 #ifdef WITH_VERBOSE_MODE
 static const char*
@@ -515,6 +515,13 @@
   window->role = NULL;
   window->sm_client_id = NULL;
   window->wm_client_machine = NULL;
+
+  window->orig_title = NULL;
+  window->num = -1;
+  window->orig_h = -1;
+  window->orig_w = -1;
+  window->save_id = NULL;
+
   window->startup_id = NULL;
   
   window->net_wm_pid = -1;
@@ -578,6 +585,7 @@
   update_role (window);
   update_net_wm_type (window);
   meta_window_update_icon_now (window);
+  update_geometry_save_id (window);
 
   if (window->initially_iconic)
     {
@@ -745,10 +753,6 @@
   meta_window_foreach_transient (window,
                                  queue_calc_showing_func,
                                  NULL);
-  /* See bug 334899; the window may have minimized ancestors which need to be
-   * shown.
-   */
-  unminimize_window_and_all_transient_parents (window);
 
   meta_error_trap_pop (display, FALSE); /* pop the XSync()-reducing trap */
   meta_display_ungrab (display);
@@ -920,6 +924,8 @@
   
   window->unmanaging = TRUE;
 
+  meta_history_forget_window ();
+
   if (window->fullscreen)
     {
       MetaGroup *group;
@@ -1101,6 +1107,7 @@
   g_free (window->role);
   g_free (window->res_class);
   g_free (window->res_name);
+  g_free (window->orig_title);
   g_free (window->title);
   g_free (window->icon_name);
   g_free (window->desc);
@@ -2105,6 +2112,14 @@
 void
 meta_window_minimize (MetaWindow  *window)
 {
+  meta_window_minimize_internal (window);
+
+  meta_history_update_inplace (window);
+}
+
+void
+meta_window_minimize_internal (MetaWindow  *window)
+{
   if (!window->minimized)
     {
       window->minimized = TRUE;
@@ -2132,6 +2147,14 @@
 void
 meta_window_unminimize (MetaWindow  *window)
 {
+  meta_window_unminimize_internal (window);
+  
+  meta_history_update_inplace (window);
+}
+
+void
+meta_window_unminimize_internal (MetaWindow  *window)
+{
   if (window->minimized)
     {
       window->minimized = FALSE;
@@ -2198,10 +2221,20 @@
   set_net_wm_state (window);
 }
 
+
 void
 meta_window_maximize (MetaWindow        *window,
                       MetaMaximizeFlags  directions)
 {
+  meta_window_maximize_real (window, directions);
+
+  meta_history_update_inplace (window);
+}
+
+void
+meta_window_maximize_real (MetaWindow        *window,
+			   MetaMaximizeFlags  directions)
+{
   /* At least one of the two directions ought to be set */
   gboolean maximize_horizontally, maximize_vertically;
   maximize_horizontally = directions & META_MAXIMIZE_HORIZONTAL;
@@ -2255,10 +2288,22 @@
   set_net_wm_state (window);
 }
 
+
+
 void
 meta_window_unmaximize (MetaWindow        *window,
                         MetaMaximizeFlags  directions)
 {
+  meta_window_unmaximize_real (window, directions);
+
+  meta_history_update_inplace (window);
+
+}
+
+void
+meta_window_unmaximize_real (MetaWindow        *window,
+			     MetaMaximizeFlags  directions)
+{
   /* At least one of the two directions ought to be set */
   gboolean unmaximize_horizontally, unmaximize_vertically;
   unmaximize_horizontally = directions & META_MAXIMIZE_HORIZONTAL;
@@ -2332,6 +2377,14 @@
 void
 meta_window_make_fullscreen (MetaWindow  *window)
 {
+  meta_window_make_fullscreen_internal (window);
+  
+  meta_history_update_inplace (window);
+}
+
+void
+meta_window_make_fullscreen_internal (MetaWindow  *window)
+{
   if (!window->fullscreen)
     {
       meta_topic (META_DEBUG_WINDOW_OPS,
@@ -2362,6 +2415,14 @@
 void
 meta_window_unmake_fullscreen (MetaWindow  *window)
 {
+  meta_window_unmake_fullscreen_internal (window);
+  
+  meta_history_update_inplace (window);
+}
+
+void
+meta_window_unmake_fullscreen_internal (MetaWindow  *window)
+{
   if (window->fullscreen)
     {
       meta_topic (META_DEBUG_WINDOW_OPS,
@@ -2817,6 +2878,11 @@
   new_rect.width  = w;
   new_rect.height = h;
 
+  if (window->orig_h == -1)
+    window->orig_h = h;
+  if (window->orig_w == -1)
+    window->orig_w = w;
+
   /* If this is a resize only, the position should be ignored and
    * instead obtained by resizing the old rectangle according to the
    * relevant gravity.
@@ -3149,12 +3215,18 @@
       need_move_client || need_resize_client)
     {
       int newx, newy;
+
       meta_window_get_position (window, &newx, &newy);
       meta_topic (META_DEBUG_GEOMETRY,
                   "New size/position %d,%d %dx%d (user %d,%d %dx%d)\n",
                   newx, newy, window->rect.width, window->rect.height,
                   window->user_rect.x, window->user_rect.y,
                   window->user_rect.width, window->user_rect.height);
+
+      if (is_user_action)
+	meta_history_remember_window (window);
+      if (!is_user_action)
+	meta_history_commit_window ();
     }
   else
     {
@@ -3189,6 +3261,7 @@
                                     flags,
                                     NorthWestGravity,
                                     x, y, w, h);
+
 }
 
 void
@@ -3817,6 +3890,14 @@
 static void
 window_stick_impl (MetaWindow  *window)
 {
+  meta_window_stick_internal (window);
+
+  meta_history_update_inplace (window);
+}
+
+void
+meta_window_stick_internal (MetaWindow  *window)
+{
   GList *tmp; 
   MetaWorkspace *workspace;
 
@@ -3852,6 +3933,14 @@
 static void
 window_unstick_impl (MetaWindow  *window)
 {
+  meta_window_unstick_internal (window);
+
+  meta_history_update_inplace (window);
+}
+
+void
+meta_window_unstick_internal (MetaWindow  *window)
+{
   GList *tmp;
   MetaWorkspace *workspace;
 
@@ -5060,6 +5149,12 @@
       meta_window_reload_property (window,
                                    window->display->atom_net_wm_user_time);
     }
+  else if (event->atom == window->display->atom_net_wm_geometry_save_id)
+    {
+      meta_verbose ("Property notify on %s for _NET_WM_GEOMETRY_SAVE_ID\n", window->desc);
+      
+      update_geometry_save_id (window);
+    }
 
   return TRUE;
 }
@@ -5102,6 +5197,33 @@
   meta_error_trap_pop (window->display, FALSE);
 }
 
+static void
+update_geometry_save_id (MetaWindow *window)
+{
+  gchar *save_id = NULL;
+
+  if (!meta_prop_get_save_id (window->display, window->xwindow,
+				       window->display->atom_net_wm_geometry_save_id,
+				       &save_id))
+    {
+      meta_verbose ("Window Geometry Save ID wasn't set.  We manage this window.\n");
+      return;
+
+    }
+
+ 
+  if (!save_id || strlen (save_id) == 0) 
+    {
+      meta_verbose ("Window Geometry Save ID is empty.  Clearing Window History.\n");
+      meta_history_clear_window (window);
+      return;      
+    }
+
+  meta_history_update_key (window, save_id);
+  
+  meta_verbose ("Window Geometry Save ID updated.\n");
+}
+
 gboolean
 meta_window_get_icon_geometry (MetaWindow    *window,
                                MetaRectangle *rect)
@@ -7568,6 +7690,47 @@
                      &x, &y);
 }
 
+const char*
+window_gravity_to_string (int gravity)
+{
+  switch (gravity)
+    {
+    case NorthWestGravity:
+      return "NorthWestGravity";
+      break;
+    case NorthGravity:
+      return "NorthGravity";
+      break;
+    case NorthEastGravity:
+      return "NorthEastGravity";
+      break;
+    case WestGravity:
+      return "WestGravity";
+      break;
+    case CenterGravity:
+      return "CenterGravity";
+      break;
+    case EastGravity:
+      return "EastGravity";
+      break;
+    case SouthWestGravity:
+      return "SouthWestGravity";
+      break;
+    case SouthGravity:
+      return "SouthGravity";
+      break;
+    case SouthEastGravity:
+      return "SouthEastGravity";
+      break;
+    case StaticGravity:
+      return "StaticGravity";
+      break;
+    default:
+      return "NorthWestGravity";
+      break;
+    }
+}
+  
 void
 meta_window_update_layer (MetaWindow *window)
 {
diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/window.h metacity/src/window.h
--- metacity-new/src/window.h	2006-04-17 23:29:49.000000000 -0400
+++ metacity/src/window.h	2006-04-17 13:14:26.000000000 -0400
@@ -108,6 +108,13 @@
   char *wm_client_machine;
   char *startup_id;
 
+  /* Needed for Window History Tracking */
+  char *orig_title;
+  char *save_id;
+  int orig_h;
+  int orig_w;
+  int num;
+
   int net_wm_pid;
   
   Window xtransient_for;
@@ -379,7 +386,11 @@
 void        meta_window_calc_showing       (MetaWindow  *window);
 void        meta_window_queue_calc_showing (MetaWindow  *window);
 void        meta_window_minimize           (MetaWindow  *window);
+void        meta_window_minimize_internal  (MetaWindow  *window);
 void        meta_window_unminimize         (MetaWindow  *window);
+void        meta_window_unminimize_internal(MetaWindow  *window);
+void        meta_window_maximize_real      (MetaWindow        *window,
+					    MetaMaximizeFlags  diections);
 void        meta_window_maximize           (MetaWindow        *window,
                                             MetaMaximizeFlags  directions);
 void        meta_window_maximize_internal  (MetaWindow        *window,
@@ -387,6 +398,8 @@
                                             MetaRectangle     *saved_rect);
 void        meta_window_unmaximize         (MetaWindow        *window,
                                             MetaMaximizeFlags  directions);
+void        meta_window_unmaximize_real    (MetaWindow        *window,
+                                            MetaMaximizeFlags  directions);
 void        meta_window_make_above         (MetaWindow  *window);
 void        meta_window_unmake_above       (MetaWindow  *window);
 void        meta_window_shade              (MetaWindow  *window);
@@ -394,12 +407,16 @@
 void        meta_window_change_workspace   (MetaWindow  *window,
                                             MetaWorkspace *workspace);
 void        meta_window_stick              (MetaWindow  *window);
+void        meta_window_stick_internal     (MetaWindow  *window);
 void        meta_window_unstick            (MetaWindow  *window);
+void 	     meta_window_unstick_internal   (MetaWindow  *window);
 
 void        meta_window_activate           (MetaWindow  *window,
                                             guint32      current_time);
 void        meta_window_make_fullscreen    (MetaWindow  *window);
+void        meta_window_make_fullscreen_internal(MetaWindow  *window);
 void        meta_window_unmake_fullscreen  (MetaWindow  *window);
+void        meta_window_unmake_fullscreen_internal(MetaWindow  *window);
 
 /* args to move are window pos, not frame pos */
 void        meta_window_move               (MetaWindow  *window,
@@ -568,6 +585,12 @@
                                          gboolean    update_cursor);
 void meta_window_update_keyboard_move   (MetaWindow *window);
 
+const char* window_type_to_string      (MetaWindowType  type);
+MetaWindowType window_type_from_string (const char     *str);
+
+const char* window_gravity_to_string (int         gravity);
+int window_gravity_from_string       (const char *str);
+
 void meta_window_update_layer (MetaWindow *window);
 
 gboolean meta_window_get_icon_geometry (MetaWindow    *window,
diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/window-props.c metacity/src/window-props.c
--- metacity-new/src/window-props.c	2006-03-25 17:57:22.000000000 -0500
+++ metacity/src/window-props.c	2006-04-16 16:06:07.000000000 -0400
@@ -254,6 +254,9 @@
   set_title_text (window, title, window->display->atom_net_wm_visible_name,
                   &window->title);
   
+  if (!window->orig_title)
+    window->orig_title = g_strdup (window->title);
+
   /* strndup is a hack since GNU libc has broken %.10s */
   str = g_strndup (window->title, 10);
   g_free (window->desc);
@@ -618,8 +621,9 @@
 
   if (value->type != META_PROP_VALUE_INVALID)
     { 
-      if (value->v.class_hint.res_name)
+      if (value->v.class_hint.res_name) {
         window->res_name = g_strdup (value->v.class_hint.res_name);
+      }
 
       if (value->v.class_hint.res_class)
         window->res_class = g_strdup (value->v.class_hint.res_class);
diff -u -r --exclude=CVS --exclude=po --exclude=ChangeLog metacity-new/src/xprops.c metacity/src/xprops.c
--- metacity-new/src/xprops.c	2006-04-17 23:30:34.000000000 -0400
+++ metacity/src/xprops.c	2006-04-16 15:33:06.000000000 -0400
@@ -332,6 +332,38 @@
 }
 
 gboolean
+meta_prop_get_save_id (MetaDisplay   *display,
+		       Window         xwindow,
+		       Atom           xatom,
+		       char         **save_id)
+{
+  GetPropertyResults results;
+
+  if (!get_property (display, xwindow, xatom, AnyPropertyType,
+		     &results))
+    {
+      meta_verbose ("History Geometry Save ID wasn't set on this window.\n");
+      return FALSE;
+    }
+  if (results.type == None || results.n_items <= 0)
+    {
+      meta_verbose ("History Geometry Save ID was set to NULL.  We need to forget this window's state.\n");
+      *save_id = NULL;
+      if (results.prop)
+	{
+	  XFree (results.prop);
+	  results.prop = NULL;
+	}
+      return TRUE;
+    }
+
+  *save_id = g_strdup (results.prop);
+  XFree (results.prop);
+
+  return TRUE;
+}
+
+gboolean
 meta_prop_get_motif_hints (MetaDisplay   *display,
                            Window         xwindow,
                            Atom           xatom,
