? clamp-constrain.patch
? constraints-ideas.txt
? current.patch
? debug-167199.patch
? patches
? simple-example
? simple-example.c
? stamp-h1
? testit
? testit.c
Index: src/display.c
===================================================================
RCS file: /cvs/gnome/metacity/src/display.c,v
retrieving revision 1.250
diff -p -u -r1.250 display.c
--- src/display.c	9 Feb 2005 03:18:46 -0000	1.250
+++ src/display.c	13 Feb 2005 00:37:20 -0000
@@ -1846,7 +1846,15 @@ event_callback (XEvent   *event,
     case FocusOut:
       if (window)
         {
-          meta_window_notify_focus (window, event);
+          meta_topic (META_DEBUG_FOCUS,
+                      "Focus %s event received on %s "
+                      "mode %s detail %s\n",
+                      event->type == FocusIn ? "in" :
+                      event->type == FocusOut ? "out" :
+                      "???",
+                      window->desc,
+                      meta_event_mode_to_string (event->xfocus.mode),
+                      meta_event_detail_to_string (event->xfocus.detail));
         }
       else if (event->xany.window == display->no_focus_window)
         {
@@ -1957,13 +1965,6 @@ event_callback (XEvent   *event,
                               window->unmaps_pending);
                 }
             }
-
-          /* Unfocus on UnmapNotify, do this after the possible
-           * window_free above so that window_free can see if window->has_focus
-           * and move focus to another window
-           */
-          if (window)
-            meta_window_notify_focus (window, event);
         }
       break;
     case MapNotify:
@@ -4665,6 +4666,9 @@ meta_display_set_input_focus_window (Met
   else if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_focus_time))
     return;
 
+
+  meta_window_notify_focus (window, display);
+
   XSetInputFocus (display->xdisplay,
                   focus_frame ? window->frame->xwindow : window->xwindow,
                   RevertToPointerRoot,
@@ -4692,6 +4696,8 @@ meta_display_focus_the_no_focus_window (
       meta_warning ("Ignoring focus request for no_focus_window since %lu is less than %lu.\n", timestamp, display->last_focus_time);
     return;
     }
+
+  meta_window_notify_focus (NULL, display);
 
   XSetInputFocus (display->xdisplay,
                   display->no_focus_window,
Index: src/window.c
===================================================================
RCS file: /cvs/gnome/metacity/src/window.c,v
retrieving revision 1.377
diff -p -u -r1.377 window.c
--- src/window.c	12 Feb 2005 07:34:30 -0000	1.377
+++ src/window.c	13 Feb 2005 00:37:22 -0000
@@ -4330,177 +4330,101 @@ meta_window_client_message (MetaWindow *
   return FALSE;
 }
 
-gboolean
-meta_window_notify_focus (MetaWindow *window,
-                          XEvent     *event)
+void
+meta_window_notify_focus (MetaWindow  *window,
+                          MetaDisplay *display)
 {
-  /* note the event can be on either the window or the frame,
-   * we focus the frame for shaded windows
-   */
-  
-  /* The event can be FocusIn, FocusOut, or UnmapNotify.
-   * On UnmapNotify we have to pretend it's focus out,
-   * because we won't get a focus out if it occurs, apparently.
-   */
-
-  /* We ignore grabs, though this is questionable.
-   * It may be better to increase the intelligence of
-   * the focus window tracking.
-   *
-   * The problem is that keybindings for windows are done with
-   * XGrabKey, which means focus_window disappears and the front of
-   * the MRU list gets confused from what the user expects once a
-   * keybinding is used.
-   */  
-  meta_topic (META_DEBUG_FOCUS,
-              "Focus %s event received on %s 0x%lx (%s) "
-              "mode %s detail %s\n",
-              event->type == FocusIn ? "in" :
-              event->type == FocusOut ? "out" :
-              event->type == UnmapNotify ? "unmap" :
-              "???",
-              window->desc, event->xany.window,
-              event->xany.window == window->xwindow ?
-              "client window" :
-              (window->frame && event->xany.window == window->frame->xwindow) ?
-              "frame window" :
-              "unknown window",
-              event->type != UnmapNotify ?
-              meta_event_mode_to_string (event->xfocus.mode) : "n/a",
-              event->type != UnmapNotify ?
-              meta_event_detail_to_string (event->xfocus.detail) : "n/a");
-
-  /* FIXME our pointer tracking is broken; see how
-   * gtk+/gdk/x11/gdkevents-x11.c or XFree86/xc/programs/xterm/misc.c
-   * handle it for the correct way.  In brief you need to track
-   * pointer focus and regular focus, and handle EnterNotify in
-   * PointerRoot mode with no window manager.  However as noted above,
-   * accurate focus tracking will break things because we want to keep
-   * windows "focused" when using keybindings on them, and also we
-   * sometimes "focus" a window by focusing its frame or
-   * no_focus_window; so this all needs rethinking massively.
-   *
-   * My suggestion is to change it so that we clearly separate
-   * actual keyboard focus tracking using the xterm algorithm,
-   * and metacity's "pretend" focus window, and go through all
-   * the code and decide which one should be used in each place;
-   * a hard bit is deciding on a policy for that.
-   *
-   * http://bugzilla.gnome.org/show_bug.cgi?id=90382
-   */
-  
-  if ((event->type == FocusIn ||
-       event->type == FocusOut) &&
-      (event->xfocus.mode == NotifyGrab ||
-       event->xfocus.mode == NotifyUngrab ||
-       /* From WindowMaker, ignore all funky pointer root events */
-       event->xfocus.detail > NotifyNonlinearVirtual))
+  MetaWindow *focus_window;
+
+  focus_window = display->focus_window;
+  if (window == focus_window)
     {
       meta_topic (META_DEBUG_FOCUS,
-                  "Ignoring focus event generated by a grab or other weirdness\n");
-      return TRUE;
+                  "Exiting early from meta_window_notify_focus because the "
+                  "specified window, %s, already has the focus.\n",
+                  window ? window->desc : "NULL");
+      return;
     }
-    
-  if (event->type == FocusIn)
+
+  /* First, unfocus the previous focus_window */
+  if (focus_window)
     {
-      if (window != window->display->focus_window)
-        {
-          meta_topic (META_DEBUG_FOCUS,
-                      "* Focus --> %s\n", window->desc);
-          window->display->focus_window = window;
-          window->has_focus = TRUE;
-
-          /* Move to the front of the focusing workspace's MRU list.
-           * We should only be "removing" it from the MRU list if it's
-           * not already there.  Note that it's possible that we might
-           * be processing this FocusIn after we've changed to a
-           * different workspace; we should therefore update the MRU
-           * list only if the window is actually on the active
-           * workspace.
-           */
-          if (window->screen->active_workspace &&
-              meta_window_located_on_workspace (window, 
-                                                window->screen->active_workspace))
-            {
-              GList* link;
-              link = g_list_find (window->screen->active_workspace->mru_list, 
-                                  window);
-              g_assert (link);
-
-              window->screen->active_workspace->mru_list = 
-                g_list_remove_link (window->screen->active_workspace->mru_list,
-                                    link);
-              g_list_free (link);
-
-              window->screen->active_workspace->mru_list = 
-                g_list_prepend (window->screen->active_workspace->mru_list, 
-                                window);
-            }
-
-          if (window->frame)
-            meta_frame_queue_draw (window->frame);
-          
-          meta_error_trap_push (window->display);
-          XInstallColormap (window->display->xdisplay,
-                            window->colormap);
-          meta_error_trap_pop (window->display, FALSE);
-
-          /* move into FOCUSED_WINDOW layer */
-          meta_window_update_layer (window);
-
-          /* Ungrab click to focus button since the sync grab can interfere
-           * with some things you might do inside the focused window, by
-           * causing the client to get funky enter/leave events.
-           */
-          if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK)
-            meta_display_ungrab_focus_window_button (window->display, window);
-        }
+      meta_topic (META_DEBUG_FOCUS,
+                  "%s is now the previous focus window\n",
+                  focus_window->desc);
+
+      focus_window->has_focus = FALSE;
+      if (focus_window->frame)
+        meta_frame_queue_draw (focus_window->frame);
+
+      meta_error_trap_push (display);
+      XUninstallColormap (display->xdisplay,
+                          focus_window->colormap);
+      meta_error_trap_pop (display, FALSE);
+
+      /* move out of FOCUSED_WINDOW layer */
+      meta_window_update_layer (focus_window);
+
+      /* Re-grab for click to focus, if necessary */
+      if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK)
+        meta_display_grab_focus_window_button (display, focus_window);
     }
-  else if (event->type == FocusOut ||
-           event->type == UnmapNotify)
+
+  /* Next, focus the new focus window */
+  display->focus_window = window;
+  if (window)
     {
-      if (event->type == FocusOut &&
-          event->xfocus.detail == NotifyInferior)
+      meta_topic (META_DEBUG_FOCUS,
+                  "* Focus --> %s\n", window->desc);
+      window->has_focus = TRUE;
+
+      /* Move to the front of the focusing workspace's MRU list.
+       * We should only be "removing" it from the MRU list if it's
+       * not already there.  The sanity checks here are probably
+       * unnecessary (and are just a holdover from when this was
+       * called from a FocusIn event), but we leave them here just
+       * in case.
+       */
+      if (window->screen->active_workspace &&
+          meta_window_located_on_workspace (window, 
+                                            window->screen->active_workspace))
         {
-          /* This event means the client moved focus to a subwindow */
-          meta_topic (META_DEBUG_FOCUS,
-                      "Ignoring focus out on %s with NotifyInferior\n",
-                      window->desc);
-          return TRUE;
+          GList* link;
+          link = g_list_find (window->screen->active_workspace->mru_list, 
+                              window);
+          g_assert (link);
+
+          window->screen->active_workspace->mru_list = 
+            g_list_remove_link (window->screen->active_workspace->mru_list,
+                                link);
+          g_list_free (link);
+
+          window->screen->active_workspace->mru_list = 
+            g_list_prepend (window->screen->active_workspace->mru_list, 
+                            window);
         }
+
+      if (window->frame)
+        meta_frame_queue_draw (window->frame);
       
-      if (window == window->display->focus_window)
-        {
-          meta_topic (META_DEBUG_FOCUS,
-                      "%s is now the previous focus window due to being focused out or unmapped\n",
-                      window->desc);
-
-          meta_topic (META_DEBUG_FOCUS,
-                      "* Focus --> NULL (was %s)\n", window->desc);
-          
-          window->display->focus_window = NULL;
-          window->has_focus = FALSE;
-          if (window->frame)
-            meta_frame_queue_draw (window->frame);
-
-          meta_error_trap_push (window->display);
-          XUninstallColormap (window->display->xdisplay,
-                              window->colormap);
-          meta_error_trap_pop (window->display, FALSE);
-
-          /* move out of FOCUSED_WINDOW layer */
-          meta_window_update_layer (window);
-
-          /* Re-grab for click to focus, if necessary */
-          if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK)
-            meta_display_grab_focus_window_button (window->display, window);
-       }
+      meta_error_trap_push (display);
+      XInstallColormap (display->xdisplay,
+                        window->colormap);
+      meta_error_trap_pop (display, FALSE);
+
+      /* move into FOCUSED_WINDOW layer */
+      meta_window_update_layer (window);
+
+      /* Ungrab click to focus button since the sync grab can interfere
+       * with some things you might do inside the focused window, by
+       * causing the client to get funky enter/leave events.
+       */
+      if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK)
+        meta_display_ungrab_focus_window_button (display, window);
     }
 
   /* Now set _NET_ACTIVE_WINDOW hint */
-  meta_display_update_active_window_hint (window->display);
-  
-  return FALSE;
+  meta_display_update_active_window_hint (display);
 }
 
 static gboolean
Index: src/window.h
===================================================================
RCS file: /cvs/gnome/metacity/src/window.h,v
retrieving revision 1.114
diff -p -u -r1.114 window.h
--- src/window.h	11 Feb 2005 19:20:44 -0000	1.114
+++ src/window.h	13 Feb 2005 00:37:22 -0000
@@ -454,8 +454,8 @@ gboolean meta_window_property_notify   (
                                         XEvent     *event);
 gboolean meta_window_client_message    (MetaWindow *window,
                                         XEvent     *event);
-gboolean meta_window_notify_focus      (MetaWindow *window,
-                                        XEvent     *event);
+void     meta_window_notify_focus      (MetaWindow  *window,
+                                        MetaDisplay *display);
 
 void     meta_window_set_current_workspace_hint (MetaWindow *window);
 
