Index: display.c
===================================================================
RCS file: /cvs/gnome/metacity/src/display.c,v
retrieving revision 1.184
diff -p -u -r1.184 display.c
--- display.c	16 May 2003 21:59:07 -0000	1.184
+++ display.c	17 May 2003 02:51:53 -0000
@@ -269,7 +269,8 @@ meta_display_open (const char *name)
     "SYNC_COUNTER",
     "_GNOME_PANEL_ACTION",
     "_GNOME_PANEL_ACTION_MAIN_MENU",
-    "_GNOME_PANEL_ACTION_RUN_DIALOG"
+    "_GNOME_PANEL_ACTION_RUN_DIALOG",
+    "_METACITY_SENTINEL"
   };
   Atom atoms[G_N_ELEMENTS(atom_names)];
   
@@ -416,6 +417,7 @@ meta_display_open (const char *name)
   display->atom_gnome_panel_action = atoms[81];
   display->atom_gnome_panel_action_main_menu = atoms[82];
   display->atom_gnome_panel_action_run_dialog = atoms[83];
+  display->atom_metacity_sentinel = atoms[84];
   
   display->prop_hooks = NULL;
   meta_display_init_window_prop_hooks (display);
@@ -474,6 +476,7 @@ meta_display_open (const char *name)
   display->ungrab_should_not_cause_focus_window = None;
   
   display->current_time = CurrentTime;
+  display->ignore_enter_notify = FALSE;
   
   display->grab_op = META_GRAB_OP_NONE;
   display->grab_window = NULL;
@@ -1435,7 +1438,8 @@ event_callback (XEvent   *event,
         meta_window_handle_mouse_grab_op_event (window, event);
       /* do this even if window->has_focus to avoid races */
       else if (window && !serial_is_ignored (display, event->xany.serial) &&
-               event->xcrossing.detail != NotifyInferior)
+               event->xcrossing.detail != NotifyInferior &&
+               !display->ignore_enter_notify)
         {
           switch (meta_prefs_get_focus_mode ())
             {
@@ -1804,7 +1808,7 @@ event_callback (XEvent   *event,
                                                         space);
 
                   if (workspace)
-                    meta_workspace_activate (workspace);
+                    meta_workspace_activate (workspace, NULL);
                   else
                     meta_verbose ("Don't know about workspace %d\n", space);
                 }
Index: display.h
===================================================================
RCS file: /cvs/gnome/metacity/src/display.h,v
retrieving revision 1.101
diff -p -u -r1.101 display.h
--- display.h	15 Mar 2003 02:16:21 -0000	1.101
+++ display.h	17 May 2003 02:51:53 -0000
@@ -172,6 +172,7 @@ struct _MetaDisplay
   Atom atom_gnome_panel_action;
   Atom atom_gnome_panel_action_main_menu;
   Atom atom_gnome_panel_action_run_dialog;
+  Atom atom_metacity_sentinel;
   
   /* This is the actual window from focus events,
    * not the one we last set
@@ -249,6 +250,12 @@ struct _MetaDisplay
   MetaResizePopup *grab_resize_popup;
   GTimeVal    grab_last_moveresize_time;
   Time        grab_motion_notify_time;
+
+  /* we use property updates as sentinels for certain window focus events
+   * to avoid some race conditions on EnterNotify events
+   */
+  gboolean    ignore_enter_notify;
+
 #ifdef HAVE_XKB
   int         xkb_base_event_type;
 #endif
Index: keybindings.c
===================================================================
RCS file: /cvs/gnome/metacity/src/keybindings.c,v
retrieving revision 1.85
diff -p -u -r1.85 keybindings.c
--- keybindings.c	17 May 2003 00:00:55 -0000	1.85
+++ keybindings.c	17 May 2003 02:51:56 -0000
@@ -2328,7 +2328,7 @@ switch_to_workspace (MetaDisplay *displa
         }
     }
       
-  meta_workspace_activate (workspace);
+  meta_workspace_activate (workspace, NULL);
 
   if (move_window)
     {
@@ -3022,7 +3022,7 @@ do_handle_move_to_workspace  (MetaDispla
       /* Activate second, so the window is never unmapped */
       meta_window_change_workspace (window, workspace);
       if (flip)
-        meta_workspace_activate (workspace);
+        meta_workspace_activate (workspace, window);
     }
   else
     {
Index: screen.c
===================================================================
RCS file: /cvs/gnome/metacity/src/screen.c,v
retrieving revision 1.106
diff -p -u -r1.106 screen.c
--- screen.c	16 May 2003 21:59:07 -0000	1.106
+++ screen.c	17 May 2003 02:51:58 -0000
@@ -599,7 +599,7 @@ meta_screen_new (MetaDisplay *display,
   /* Screens must have at least one workspace at all times,
    * so create that required workspace.
    */
-  meta_workspace_activate (meta_workspace_new (screen));
+  meta_workspace_activate (meta_workspace_new (screen), NULL);
   update_num_workspaces (screen);
   
   set_workspace_names (screen);
@@ -636,7 +636,7 @@ meta_screen_new (MetaDisplay *display,
                                                 current_workspace);
     
     if (space != NULL)
-      meta_workspace_activate (space);
+      meta_workspace_activate (space, NULL);
   }
   
   meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
@@ -999,7 +999,7 @@ update_num_workspaces (MetaScreen *scree
     }
 
   if (need_change_space)
-    meta_workspace_activate (last_remaining);
+    meta_workspace_activate (last_remaining, NULL);
 
   /* Should now be safe to free the workspaces */
   tmp = extras;
Index: window.c
===================================================================
RCS file: /cvs/gnome/metacity/src/window.c,v
retrieving revision 1.276
diff -p -u -r1.276 window.c
--- window.c	16 May 2003 21:59:08 -0000	1.276
+++ window.c	17 May 2003 02:52:04 -0000
@@ -1336,6 +1336,7 @@ idle_calc_showing (gpointer data)
   GSList *should_show;
   GSList *should_hide;
   GSList *unplaced;
+  GSList *need_sentinel;
   
   meta_topic (META_DEBUG_WINDOW_STATE,
               "Clearing the calc_showing queue\n");
@@ -1359,6 +1360,7 @@ idle_calc_showing (gpointer data)
   should_show = NULL;
   should_hide = NULL;
   unplaced = NULL;
+  need_sentinel = NULL;
   
   tmp = copy;
   while (tmp != NULL)
@@ -1415,6 +1417,12 @@ idle_calc_showing (gpointer data)
 
       window = tmp->data;
 
+      if (!window->display->ignore_enter_notify)
+        {
+          window->display->ignore_enter_notify = TRUE;
+          need_sentinel = g_slist_prepend(need_sentinel, window);
+        }
+
       implement_showing (window, TRUE);
       
       tmp = tmp->next;
@@ -1436,12 +1444,35 @@ idle_calc_showing (gpointer data)
       
       tmp = tmp->next;
     }
+
+  /* for all displays used in the queue, set a sentinel property on
+   * one of the windows so that we can ignore EnterNotify events that
+   * occur before the window maps occur.  This avoids a race
+   * condition.
+   */
+  tmp = need_sentinel;
+  while (tmp != NULL)
+    {
+      MetaWindow *window;
+      unsigned long data[1];
+
+      window = tmp->data;
+      data[0] = meta_display_get_current_time(window->display);
+
+      XChangeProperty (window->display->xdisplay, window->xwindow,
+                       window->display->atom_metacity_sentinel,
+                       XA_CARDINAL,
+                       32, PropModeReplace, (guchar*) data, 1);
+
+      tmp = tmp->next;
+    }
   
   g_slist_free (copy);
 
   g_slist_free (unplaced);
   g_slist_free (should_show);
   g_slist_free (should_hide);
+  g_slist_free (need_sentinel);
   
   destroying_windows_disallowed -= 1;
   
@@ -4204,6 +4235,15 @@ process_property_notify (MetaWindow     
       
       meta_window_reload_property (window,
                                    window->display->atom_metacity_update_counter);
+    }
+  else if (event->atom == window->display->atom_metacity_sentinel)
+    {
+      /* we just use this property as a sentinel to avoid certain race
+	 conditions.  See the comment for the ignore_enter_notify
+	 variable declaration in display.h */
+      meta_verbose ("Property notify on %s for _METACITY_SENTINEL\n", window->desc);
+
+      window->display->ignore_enter_notify = FALSE;
     }
   
   return TRUE;
Index: workspace.c
===================================================================
RCS file: /cvs/gnome/metacity/src/workspace.c,v
retrieving revision 1.42
diff -p -u -r1.42 workspace.c
--- workspace.c	23 Feb 2003 17:09:46 -0000	1.42
+++ workspace.c	17 May 2003 02:52:04 -0000
@@ -196,7 +196,8 @@ meta_workspace_queue_calc_showing  (Meta
 }
 
 void
-meta_workspace_activate (MetaWorkspace *workspace)
+meta_workspace_activate (MetaWorkspace *workspace,
+                         MetaWindow    *focus_this)
 {
   MetaWorkspace *old;
   
@@ -218,8 +219,16 @@ meta_workspace_activate (MetaWorkspace *
   meta_workspace_queue_calc_showing (old);
   meta_workspace_queue_calc_showing (workspace);
 
-  meta_topic (META_DEBUG_FOCUS, "Focusing default window on new workspace\n");
-  meta_screen_focus_default_window (workspace->screen, NULL);
+  if (focus_this)
+    {
+      meta_window_focus (focus_this,
+			 meta_display_get_current_time (focus_this->display));
+    }
+  else
+    {
+      meta_topic (META_DEBUG_FOCUS, "Focusing default window on new workspace\n");
+      meta_screen_focus_default_window (workspace->screen, NULL);
+    }
 }
 
 int
Index: workspace.h
===================================================================
RCS file: /cvs/gnome/metacity/src/workspace.h,v
retrieving revision 1.14
diff -p -u -r1.14 workspace.h
--- workspace.h	23 Feb 2003 17:09:46 -0000	1.14
+++ workspace.h	17 May 2003 02:52:04 -0000
@@ -58,7 +58,8 @@ void           meta_workspace_relocate_w
 /* don't confuse with meta_window_visible_on_workspace() */
 gboolean       meta_workspace_contains_window (MetaWorkspace *workspace,
                                                MetaWindow  *window);
-void           meta_workspace_activate      (MetaWorkspace *workspace);
+void           meta_workspace_activate      (MetaWorkspace *workspace,
+                                             MetaWindow    *focus_this);
 int            meta_workspace_index         (MetaWorkspace *workspace);
 GList*         meta_workspace_list_windows  (MetaWorkspace *workspace);
 
