Index: src/display.c
===================================================================
RCS file: /cvs/gnome/metacity/src/display.c,v
retrieving revision 1.245
diff -p -u -r1.245 display.c
--- src/display.c	10 Jan 2005 00:27:00 -0000	1.245
+++ src/display.c	23 Jan 2005 15:28:01 -0000
@@ -63,6 +63,12 @@
 
 #define USE_GDK_DISPLAY
 
+#define GRAB_OP_IS_WINDOW_SWITCH(g)                     \
+        (g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL  ||  \
+         g == META_GRAB_OP_KEYBOARD_TABBING_DOCK    ||  \
+         g == META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL ||  \
+         g == META_GRAB_OP_KEYBOARD_ESCAPING_DOCK)
+
 typedef struct 
 {
   MetaDisplay *display;
@@ -790,6 +796,9 @@ meta_display_close (MetaDisplay *display
   meta_prefs_remove_listener (prefs_changed_callback, display);
   
   meta_display_remove_autoraise_callback (display);
+
+  if (display->grab_old_window_stacking)
+    g_list_free (display->grab_old_window_stacking);
   
 #ifdef USE_GDK_DISPLAY
   /* Stop caring about events */
@@ -1574,6 +1583,16 @@ event_callback (XEvent   *event,
                       (display->grab_window ?
                        display->grab_window->desc : 
                        "none"));
+          if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
+            {
+              MetaScreen *screen;
+              meta_topic (META_DEBUG_WINDOW_OPS, 
+                          "Syncing to old stack positions.\n");
+              screen = 
+                meta_display_screen_for_root (display, event->xany.window);
+              meta_stack_set_positions (screen->stack,
+                                        display->grab_old_window_stacking);
+            }
           meta_display_end_grab_op (display,
                                     event->xbutton.time);
         }
@@ -3289,6 +3308,16 @@ meta_display_begin_grab_op (MetaDisplay 
   g_assert (display->grab_window != NULL || display->grab_screen != NULL);
   g_assert (display->grab_op != META_GRAB_OP_NONE);
 
+  /* Save the old stacking */
+  if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
+    {
+      meta_topic (META_DEBUG_WINDOW_OPS,
+                  "Saving old stack positions; old pointer was %p.\n",
+                  display->grab_old_window_stacking);
+      display->grab_old_window_stacking = 
+        meta_stack_get_positions (screen->stack);
+    }
+
   /* Do this last, after everything is set up. */
   switch (op)
     {
@@ -3340,10 +3369,7 @@ meta_display_end_grab_op (MetaDisplay *d
   if (display->grab_window != NULL)
     display->grab_window->shaken_loose = FALSE;
   
-  if (display->grab_op == META_GRAB_OP_KEYBOARD_TABBING_NORMAL ||
-      display->grab_op == META_GRAB_OP_KEYBOARD_TABBING_DOCK ||
-      display->grab_op == META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL ||
-      display->grab_op == META_GRAB_OP_KEYBOARD_ESCAPING_DOCK ||
+  if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op) ||
       display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING)
     {
       meta_ui_tab_popup_free (display->grab_screen->tab_popup);
@@ -3355,6 +3381,15 @@ meta_display_end_grab_op (MetaDisplay *d
       display->ungrab_should_not_cause_focus_window = display->grab_xwindow;
     }
   
+  if (display->grab_old_window_stacking != NULL)
+    {
+      meta_topic (META_DEBUG_WINDOW_OPS,
+                  "Clearing out the old stack position, which was %p.\n",
+                  display->grab_old_window_stacking);
+      g_list_free (display->grab_old_window_stacking);
+      display->grab_old_window_stacking = NULL;
+    }
+
   if (display->grab_wireframe_active)
     {
       display->grab_wireframe_active = FALSE;
Index: src/display.h
===================================================================
RCS file: /cvs/gnome/metacity/src/display.h,v
retrieving revision 1.127
diff -p -u -r1.127 display.h
--- src/display.h	10 Jan 2005 00:27:00 -0000	1.127
+++ src/display.h	23 Jan 2005 15:28:01 -0000
@@ -265,6 +265,7 @@ struct _MetaDisplay
   MetaResizePopup *grab_resize_popup;
   GTimeVal    grab_last_moveresize_time;
   Time        grab_motion_notify_time;
+  GList*      grab_old_window_stacking;
   
   /* we use property updates as sentinels for certain window focus events
    * to avoid some race conditions on EnterNotify events
Index: src/keybindings.c
===================================================================
RCS file: /cvs/gnome/metacity/src/keybindings.c,v
retrieving revision 1.108
diff -p -u -r1.108 keybindings.c
--- src/keybindings.c	20 Dec 2004 02:46:42 -0000	1.108
+++ src/keybindings.c	23 Jan 2005 15:28:02 -0000
@@ -2475,6 +2475,11 @@ process_tab_grab (MetaDisplay *display,
       /* end grab */
       meta_topic (META_DEBUG_KEYBINDINGS,
                   "Ending tabbing/cycling, uninteresting key pressed\n");
+
+      meta_topic (META_DEBUG_KEYBINDINGS, 
+                  "Syncing to old stack positions.\n");
+      meta_stack_set_positions (screen->stack,
+                                screen->display->grab_old_window_stacking);
     }
   
   return key_used;
Index: src/stack.c
===================================================================
RCS file: /cvs/gnome/metacity/src/stack.c,v
retrieving revision 1.72
diff -p -u -r1.72 stack.c
--- src/stack.c	23 Dec 2004 00:20:33 -0000	1.72
+++ src/stack.c	23 Jan 2005 15:28:02 -0000
@@ -1466,6 +1466,110 @@ meta_stack_windows_cmp  (MetaStack  *sta
     return 0; /* not reached */
 }
 
+static int
+compare_just_window_stack_position (void *a,
+                                    void *b)
+{
+  MetaWindow *window_a = a;
+  MetaWindow *window_b = b;
+
+  if (window_a->stack_position < window_b->stack_position)
+    return -1; /* move window_a earlier in list */
+  else if (window_a->stack_position > window_b->stack_position)
+    return 1;
+  else
+    return 0; /* not reached */
+}
+
+GList*
+meta_stack_get_positions (MetaStack *stack)
+{
+  GList *tmp;
+
+  /* Make sure to handle any adds or removes */
+  meta_stack_ensure_sorted (stack);
+
+  tmp = g_list_copy (stack->sorted);
+  tmp = g_list_sort (tmp, (GCompareFunc) compare_just_window_stack_position);
+
+  return tmp;
+}
+
+gint
+compare_pointers (gconstpointer a,
+                  gconstpointer b)
+{
+  if (a > b)
+    return 1;
+  else if (a < b)
+    return -1;
+  else 
+    return 0;
+}
+
+static gboolean
+lists_contain_same_windows (GList *a,
+                            GList *b)
+{
+  GList *copy1, *copy2;
+  GList *tmp1, *tmp2;
+
+  if (g_list_length (a) != g_list_length (b))
+    return FALSE;
+
+  tmp1 = copy1 = g_list_sort (g_list_copy (a), compare_pointers);
+  tmp2 = copy2 = g_list_sort (g_list_copy (b), compare_pointers);
+
+  while (tmp1 && tmp1->data == tmp2->data)   /* tmp2 is non-NULL if tmp1 is */
+    {
+      tmp1 = tmp1->next;
+      tmp2 = tmp2->next;
+    }
+
+  g_list_free (copy1);
+  g_list_free (copy2);
+
+  return (tmp1 == NULL);    /* tmp2 is non-NULL if tmp1 is */
+}
+
+void
+meta_stack_set_positions (MetaStack *stack,
+                          GList     *windows)
+{
+  int i;
+  GList *tmp;
+
+  /* Make sure any adds or removes aren't in limbo -- is this needed? */
+  meta_stack_ensure_sorted (stack);
+  
+  if (!lists_contain_same_windows (windows, stack->sorted))
+    {
+      meta_warning ("This list of windows has somehow changed; not resetting "
+                    "positions of the windows.\n");
+      return;
+    }
+
+  g_list_free (stack->sorted);
+  stack->sorted = g_list_copy (windows);
+
+  stack->need_resort = TRUE;
+  stack->need_constrain = TRUE;
+   
+  i = 0;
+  tmp = windows;
+  while (tmp != NULL)
+    {
+      MetaWindow *w = tmp->data;
+      w->stack_position = i++;
+      tmp = tmp->next;
+    }
+  
+  meta_topic (META_DEBUG_STACK,
+              "Reset the stack positions of (nearly) all windows\n");
+
+  meta_stack_sync_to_server (stack);
+}
+
 void
 meta_window_set_stack_position_no_sync (MetaWindow *window,
                                         int         position)
Index: src/stack.h
===================================================================
RCS file: /cvs/gnome/metacity/src/stack.h,v
retrieving revision 1.17
diff -p -u -r1.17 stack.h
--- src/stack.h	24 Jun 2004 15:47:05 -0000	1.17
+++ src/stack.h	23 Jan 2005 15:28:03 -0000
@@ -140,4 +140,8 @@ int         meta_stack_windows_cmp  (Met
 void meta_window_set_stack_position (MetaWindow *window,
                                      int         position);
 
+GList* meta_stack_get_positions (MetaStack *stack);
+void   meta_stack_set_positions (MetaStack *stack,
+                                 GList     *windows);
+
 #endif
