--- metacity-2.4.55/src/prefs.h.strict-pointer-mode	2004-08-18 16:40:39.321178224 -0400
+++ metacity-2.4.55/src/prefs.h	2004-08-18 16:40:39.323177920 -0400
@@ -44,7 +44,8 @@
   META_PREF_COMMANDS,
   META_PREF_BUTTON_LAYOUT,
   META_PREF_WORKSPACE_NAMES,
-  META_PREF_REDUCED_RESOURCES
+  META_PREF_REDUCED_RESOURCES,
+  META_PREF_STRICT_POINTER_MODE
 } MetaPreference;
 
 typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
@@ -60,6 +61,7 @@
 
 MetaVirtualModifier         meta_prefs_get_mouse_button_mods  (void);
 MetaFocusMode               meta_prefs_get_focus_mode         (void);
+gboolean                    meta_prefs_get_strict_pointer_mode (void);
 gboolean                    meta_prefs_get_raise_on_click     (void);
 const char*                 meta_prefs_get_theme              (void);
 /* returns NULL if GTK default should be used */
@@ -237,6 +239,11 @@
                                     unsigned int        *keysym,
                                     MetaVirtualModifier *modifiers);
 
+        
+#define META_ENABLE_FOCUS_HEURISTICS() \
+    (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK || \
+     !meta_prefs_get_strict_pointer_mode ())
+
 #endif
 
 
--- metacity-2.4.55/src/prefs.c.strict-pointer-mode	2004-08-18 16:40:39.320178376 -0400
+++ metacity-2.4.55/src/prefs.c	2004-08-18 16:40:39.325177616 -0400
@@ -49,6 +49,7 @@
 #define KEY_DISABLE_WORKAROUNDS "/apps/metacity/general/disable_workarounds"
 #define KEY_BUTTON_LAYOUT "/apps/metacity/general/button_layout"
 #define KEY_REDUCED_RESOURCES "/apps/metacity/general/reduced_resources"
+#define KEY_STRICT_POINTER_MODE "/apps/metacity/rhel3_workarounds/strict_pointer_mode"
 
 #define KEY_COMMAND_PREFIX "/apps/metacity/keybinding_commands/command_"
 #define KEY_SCREEN_BINDINGS_PREFIX "/apps/metacity/global_keybindings"
@@ -77,7 +78,8 @@
 static gboolean auto_raise = FALSE;
 static gboolean auto_raise_delay = 500;
 static gboolean reduced_resources = FALSE;
- 
+static gboolean strict_pointer_mode = FALSE;
+
 static MetaButtonLayout button_layout = {
   {
     META_BUTTON_FUNCTION_MENU,
@@ -122,6 +124,7 @@
 static gboolean update_workspace_name     (const char  *name,
                                            const char  *value);
 static gboolean update_reduced_resources  (gboolean     value);
+static gboolean update_strict_pointer_mode (gboolean    value);
 
 static void change_notify (GConfClient    *client,
                            guint           cnxn_id,
@@ -375,6 +378,11 @@
                                     &err);
   cleanup_error (&err);
   update_reduced_resources (bool_val);
+
+  bool_val = gconf_client_get_bool (default_client, KEY_STRICT_POINTER_MODE,
+                                    &err);
+  cleanup_error (&err);
+  update_strict_pointer_mode (bool_val);
 #endif /* HAVE_GCONF */
   
   /* Load keybindings prefs */
@@ -727,6 +735,22 @@
       if (update_reduced_resources (b))
         queue_changed (META_PREF_REDUCED_RESOURCES);
     }
+  else if (strcmp (key, KEY_STRICT_POINTER_MODE) == 0)
+    {
+      gboolean b;
+
+      if (value && value->type != GCONF_VALUE_BOOL)
+        {
+          meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
+                        KEY_STRICT_POINTER_MODE);
+          goto out;
+        }
+
+      b = value ? gconf_value_get_bool (value) : reduced_resources;
+
+      if (update_strict_pointer_mode (b))
+        queue_changed (META_PREF_STRICT_POINTER_MODE);
+    }
   else
     {
       meta_topic (META_DEBUG_PREFS, "Key %s doesn't mean anything to Metacity\n",
@@ -1218,6 +1242,16 @@
 
   return old != reduced_resources;
 }
+
+static gboolean
+update_strict_pointer_mode (gboolean value)
+{
+  gboolean old = value;
+
+  strict_pointer_mode = value;
+
+  return old != strict_pointer_mode;
+}
 #endif /* HAVE_GCONF */
 
 #ifdef WITH_VERBOSE_MODE
@@ -1279,6 +1313,10 @@
     case META_PREF_REDUCED_RESOURCES:
       return "REDUCED_RESOURCES";
       break;
+
+    case META_PREF_STRICT_POINTER_MODE:
+      return "STRICT_POINTER_MODE";
+      break;
     }
 
   return "(unknown)";
@@ -1904,6 +1942,12 @@
   return reduced_resources;
 }
 
+gboolean
+meta_prefs_get_strict_pointer_mode ()
+{
+  return strict_pointer_mode;
+}
+
 MetaKeyBindingAction
 meta_prefs_get_keybinding_action (const char *name)
 {
--- metacity-2.4.55/src/metacity.schemas.in.strict-pointer-mode	2004-08-18 16:40:39.318178680 -0400
+++ metacity-2.4.55/src/metacity.schemas.in	2004-08-18 16:44:56.239120760 -0400
@@ -4,6 +4,32 @@
     <!-- General preferences -->        
 
     <schema>
+      <key>/schemas/apps/metacity/rhel3_workarounds/strict_pointer_mode</key>
+      <applyto>/apps/metacity/rhel3_workarounds/strict_pointer_mode</applyto>
+      <owner>metacity</owner>
+      <type>bool</type>
+      <default>false</default>
+      <locale name="C">
+         <short>Never focus windows unless they were the last window the mouse entered</short>
+         <long>
+          This option only has an effect in "mouse" and "sloppy" focus modes.
+        If true, then only the mouse pointer will determine where focus goes;
+        metacity will only move the focus due to new windows, or when closing 
+        existing windows, if the new window or closed window changes the window 
+        under the pointer. This will make it difficult to navigate the desktop 
+        via the keyboard, for example Ctrl+O will open a file dialog but 
+        won't focus it, and closing a dialog won't go back to the window you 
+        were using before.
+
+        This option is under rhel3_workarounds for now since it hasn't
+        been in an upstream release, but will probably move
+        to a supported option in upstream metacity if it turns out 
+        to do the job.
+         </long>
+      </locale>
+    </schema>
+
+    <schema>
       <key>/schemas/apps/metacity/general/mouse_button_modifier</key>
       <applyto>/apps/metacity/general/mouse_button_modifier</applyto>
       <owner>metacity</owner>
--- metacity-2.4.55/src/window.c.strict-pointer-mode	2004-08-18 16:40:39.313179440 -0400
+++ metacity-2.4.55/src/window.c	2004-08-18 16:40:39.331176704 -0400
@@ -882,26 +882,29 @@
    * on what gets focused, maintaining sloppy focus
    * invariants.
    */
-  if (window->has_focus)
+  if (META_ENABLE_FOCUS_HEURISTICS ())
     {
-      meta_topic (META_DEBUG_FOCUS,
-                  "Focusing top window since we're unmanaging %s\n",
-                  window->desc);
-      meta_screen_focus_top_window (window->screen, window);
-    }
-  else if (window->display->expected_focus_window == window)
-    {
-      meta_topic (META_DEBUG_FOCUS,
-                  "Focusing top window since expected focus window freed %s\n",
-                  window->desc);
-      window->display->expected_focus_window = NULL;
-      meta_screen_focus_top_window (window->screen, window);
-    }
-  else
-    {
-      meta_topic (META_DEBUG_FOCUS,
-                  "Unmanaging window %s which doesn't currently have focus\n",
-                  window->desc);
+      if (window->has_focus)
+        {
+          meta_topic (META_DEBUG_FOCUS,
+                      "Focusing top window since we're unmanaging %s\n",
+                      window->desc);
+          meta_screen_focus_top_window (window->screen, window);
+        }
+      else if (window->display->expected_focus_window == window)
+        {
+          meta_topic (META_DEBUG_FOCUS,
+                      "Focusing top window since expected focus window freed %s\n",
+                      window->desc);
+          window->display->expected_focus_window = NULL;
+          meta_screen_focus_top_window (window->screen, window);
+        }
+      else
+        {
+          meta_topic (META_DEBUG_FOCUS,
+                      "Unmanaging window %s which doesn't currently have focus\n",
+                      window->desc);
+        }
     }
 
   if (window->has_struts)
@@ -1504,40 +1507,16 @@
       break;
     case META_WINDOW_NORMAL:
 
-      /* Always focus new windows */
-      return TRUE;
-
-      /* Old Windows-XP style rule for reference */
-      /* Focus only if the current focus is on a desktop element
-       * or nonexistent.
-       *
-       * (using display->focus_window is a bit of a race condition,
-       *  but I have no idea how to avoid it)
-       */
-      if (window->display->focus_window == NULL ||
-          (window->display->focus_window &&
-           (window->display->focus_window->type == META_WINDOW_DOCK ||
-            window->display->focus_window->type == META_WINDOW_DESKTOP)))
+      if (META_ENABLE_FOCUS_HEURISTICS ())
         return TRUE;
+
       break;
     case META_WINDOW_DIALOG:
     case META_WINDOW_MODAL_DIALOG:
-
-      /* Always focus */
-      return TRUE;
-
-      /* Old Windows-XP style rule for reference */
-      /* Focus only if the transient parent has focus */
-      /* (using display->focus_window is a bit of a race condition,
-       *  but I have no idea how to avoid it)
-       */
-      if (window->display->focus_window == NULL ||
-          (window->display->focus_window &&
-           meta_window_is_ancestor_of_transient (window->display->focus_window,
-                                                 window)) ||
-          (window->display->focus_window->type == META_WINDOW_DOCK ||
-           window->display->focus_window->type == META_WINDOW_DESKTOP))
+      
+      if (META_ENABLE_FOCUS_HEURISTICS ())
         return TRUE;
+
       break;
     }
 
@@ -1745,19 +1724,22 @@
       meta_window_foreach_transient (window,
                                      queue_calc_showing_func,
                                      NULL);
-      
-      if (window->has_focus)
-        {
-          meta_topic (META_DEBUG_FOCUS,
-                      "Focusing top window due to minimization of focus window %s\n",
-                      window->desc);
-          meta_screen_focus_top_window (window->screen, window);
-        }
-      else
+
+      if (META_ENABLE_FOCUS_HEURISTICS ())
         {
-          meta_topic (META_DEBUG_FOCUS,
-                      "Minimizing window %s which doesn't have the focus\n",
-                      window->desc);
+          if (window->has_focus)
+            {
+              meta_topic (META_DEBUG_FOCUS,
+                          "Focusing top window due to minimization of focus window %s\n",
+                          window->desc);
+              meta_screen_focus_top_window (window->screen, window);
+            }
+          else
+            {
+              meta_topic (META_DEBUG_FOCUS,
+                          "Minimizing window %s which doesn't have the focus\n",
+                          window->desc);
+            }
         }
     }
 }
--- metacity-2.4.55/src/delete.c.strict-pointer-mode	2004-08-18 16:41:55.665572112 -0400
+++ metacity-2.4.55/src/delete.c	2004-08-18 16:50:27.949693088 -0400
@@ -23,6 +23,7 @@
 #include "util.h"
 #include "window.h"
 #include "errors.h"
+#include "prefs.h"
 
 #include <sys/types.h>
 #include <signal.h>
@@ -377,23 +378,26 @@
                             delete_ping_reply_func,
                             delete_ping_timeout_func,
                             window);
-  
-  if (window->has_focus)
-    {
-      /* This is unfortunately going to result in weirdness
-       * if the window doesn't respond to the delete event.
-       * I don't know how to avoid that though.
-       */
-      meta_topic (META_DEBUG_FOCUS,
-                  "Focusing top window because focus window %s was deleted/killed\n",
-                  window->desc);
-      meta_screen_focus_top_window (window->screen, window);
-    }
-  else
+
+  if (META_ENABLE_FOCUS_HEURISTICS ())
     {
-      meta_topic (META_DEBUG_FOCUS,
-                  "Window %s was deleted/killed but didn't have focus\n",
-                  window->desc);
+      if (window->has_focus)
+        {
+          /* This is unfortunately going to result in weirdness
+           * if the window doesn't respond to the delete event.
+           * I don't know how to avoid that though.
+           */
+          meta_topic (META_DEBUG_FOCUS,
+                      "Focusing top window because focus window %s was deleted/killed\n",
+                      window->desc);
+          meta_screen_focus_top_window (window->screen, window);
+        }
+      else
+        {
+          meta_topic (META_DEBUG_FOCUS,
+                      "Window %s was deleted/killed but didn't have focus\n",
+                      window->desc);
+        }
     }
 }
 
