[mutter] display: clean up focus_window vs expected_focus_window



commit 7a4c808e43d4136cdd499820de68baebc2891a01
Author: Dan Winship <danw gnome org>
Date:   Tue Apr 26 08:12:04 2011 -0400

    display: clean up focus_window vs expected_focus_window
    
    Mutter previously defined display->focus_window as the window that the
    server says is focused, but kept display->expected_focus_window to
    indicate the window that we have requested to be focused. But it turns
    out that "expected_focus_window" was almost always what we wanted.
    
    Make MetaDisplay do a better job of tracking focus-related requests
    and events, and change display->focus_window to be our best guess of
    the "currently" focused window (ie, the window that will be focused at
    the time when the server processes the next request we send it).
    
    https://bugzilla.gnome.org/show_bug.cgi?id=647706

 src/core/display-private.h |   20 ++--
 src/core/display.c         |  275 ++++++++++++++++++++++++++++++++++++--------
 src/core/stack.c           |   10 +-
 src/core/window-private.h  |    7 +-
 src/core/window.c          |  163 ++------------------------
 src/meta/display.h         |    4 +
 src/ui/tabpopup.c          |    5 +-
 7 files changed, 261 insertions(+), 223 deletions(-)
---
diff --git a/src/core/display-private.h b/src/core/display-private.h
index 1f73fc3..3415c84 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -103,19 +103,17 @@ struct _MetaDisplay
 #include <meta/atomnames.h>
 #undef item
 
-  /* This is the actual window from focus events,
-   * not the one we last set
+  /* The window and serial of the most recent FocusIn event. */
+  Window server_focus_window;
+  gulong server_focus_serial;
+
+  /* Our best guess as to the "currently" focused window (that is, the
+   * window that we expect will be focused at the point when the X
+   * server processes our next request), and the serial of the request
+   * or event that caused this.
    */
   MetaWindow *focus_window;
-
-  /* window we are expecting a FocusIn event for or the current focus
-   * window if we are not expecting any FocusIn/FocusOut events; not
-   * perfect because applications can call XSetInputFocus directly.
-   * (It could also be messed up if a timestamp later than current
-   * time is sent to meta_display_set_input_focus_window, though that
-   * would be a programming error).  See bug 154598 for more info.
-   */
-  MetaWindow *expected_focus_window;
+  gulong focus_serial;
 
   /* last timestamp passed to XSetInputFocus */
   guint32 last_focus_time;
diff --git a/src/core/display.c b/src/core/display.c
index f4f7e63..7ee9c59 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -519,7 +519,9 @@ meta_display_open (void)
   the_display->autoraise_timeout_id = 0;
   the_display->autoraise_window = NULL;
   the_display->focus_window = NULL;
-  the_display->expected_focus_window = NULL;
+  the_display->focus_serial = 0;
+  the_display->server_focus_window = None;
+  the_display->server_focus_serial = 0;
   the_display->grab_old_window_stacking = NULL;
 
   the_display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
@@ -1632,12 +1634,12 @@ meta_display_mouse_mode_focus (MetaDisplay *display,
        * alternative mechanism works great.
        */
       if (meta_prefs_get_focus_mode() == G_DESKTOP_FOCUS_MODE_MOUSE &&
-          display->expected_focus_window != NULL)
+          display->focus_window != NULL)
         {
           meta_topic (META_DEBUG_FOCUS,
                       "Unsetting focus from %s due to mouse entering "
                       "the DESKTOP window\n",
-                      display->expected_focus_window->desc);
+                      display->focus_window->desc);
           meta_display_focus_the_no_focus_window (display,
                                                   window->screen,
                                                   timestamp);
@@ -1851,6 +1853,163 @@ get_input_event (MetaDisplay *display,
   return NULL;
 }
 
+static void
+set_focus_window (MetaDisplay *display,
+                  MetaWindow  *window,
+                  gulong       serial)
+{
+  display->focus_serial = serial;
+
+  if (window == display->focus_window)
+    return;
+
+  if (display->focus_window)
+    {
+      MetaWindow *previous;
+
+      meta_topic (META_DEBUG_FOCUS,
+                  "%s is now the previous focus window due to being focused out or unmapped\n",
+                  display->focus_window->desc);
+
+      /* Make sure that signals handlers invoked by
+       * meta_window_set_focused_internal() don't see
+       * display->focus_window->has_focus == FALSE
+       */
+      previous = display->focus_window;
+      display->focus_window = NULL;
+
+      meta_window_set_focused_internal (previous, FALSE);
+    }
+
+  display->focus_window = window;
+
+  if (display->focus_window)
+    {
+      meta_topic (META_DEBUG_FOCUS, "* Focus --> %s with serial %lu\n",
+                  display->focus_window->desc, serial);
+      meta_window_set_focused_internal (display->focus_window, TRUE);
+    }
+  else
+    meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial);
+
+  g_object_notify (G_OBJECT (display), "focus-window");
+  meta_display_update_active_window_hint (display);
+}
+
+static void
+handle_window_focus_event (MetaDisplay  *display,
+                           MetaWindow   *window,
+                           XIEnterEvent *event,
+                           unsigned long serial)
+{
+  MetaWindow *focus_window;
+#ifdef WITH_VERBOSE_MODE
+  const char *window_type;
+
+  /* Note the event can be on either the window or the frame,
+   * we focus the frame for shaded windows
+   */
+  if (window)
+    {
+      if (event->event == window->xwindow)
+        window_type = "client window";
+      else if (window->frame && event->event == window->frame->xwindow)
+        window_type = "frame window";
+      else
+        window_type = "unknown client window";
+    }
+  else if (meta_display_xwindow_is_a_no_focus_window (display, event->event))
+    window_type = "no_focus_window";
+  else if (meta_display_screen_for_root (display, event->event))
+    window_type = "root window";
+  else
+    window_type = "unknown window";
+
+  meta_topic (META_DEBUG_FOCUS,
+              "Focus %s event received on %s 0x%lx (%s) "
+              "mode %s detail %s serial %lu\n",
+              event->evtype == XI_FocusIn ? "in" :
+              event->evtype == XI_FocusOut ? "out" :
+              "???",
+              window ? window->desc : "",
+              event->event, window_type,
+              meta_event_mode_to_string (event->mode),
+              meta_event_detail_to_string (event->mode),
+              event->serial);
+#endif
+
+  /* FIXME our pointer tracking is broken; see how
+   * gtk+/gdk/x11/gdkevents-x11.c or XFree86/xc/programs/xterm/misc.c
+   * for how to handle it 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 mutter'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
+   */
+
+  /* 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.
+   */
+
+  if (event->mode == NotifyGrab ||
+      event->mode == NotifyUngrab ||
+      /* From WindowMaker, ignore all funky pointer root events */
+      event->detail > NotifyNonlinearVirtual)
+    {
+      meta_topic (META_DEBUG_FOCUS,
+                  "Ignoring focus event generated by a grab or other weirdness\n");
+      return;
+    }
+
+  if (event->evtype == XI_FocusIn)
+    {
+      display->server_focus_window = event->event;
+      display->server_focus_serial = serial;
+
+      if (window && window->override_redirect)
+        focus_window = NULL;
+      else
+        focus_window = window;
+    }
+  else if (event->evtype == XI_FocusOut)
+    {
+      if (event->detail == NotifyInferior)
+        {
+          /* This event means the client moved focus to a subwindow */
+          meta_topic (META_DEBUG_FOCUS,
+                      "Ignoring focus out with NotifyInferior\n");
+          return;
+        }
+
+      display->server_focus_window = None;
+      display->server_focus_serial = serial;
+      focus_window = NULL;
+    }
+  else
+    g_return_if_reached ();
+
+  if (display->server_focus_serial >= display->focus_serial)
+    {
+      set_focus_window (display, focus_window,
+                        display->server_focus_serial);
+    }
+}
+
 /**
  * event_callback:
  * @event: The event that just happened
@@ -1893,7 +2052,18 @@ event_callback (XEvent   *event,
   filter_out_event = FALSE;
   display->current_time = event_get_time (display, event);
   display->monitor_cache_invalidated = TRUE;
-  
+
+  if (event->xany.serial > display->focus_serial &&
+      display->focus_window &&
+      display->focus_window->xwindow != display->server_focus_window)
+    {
+      meta_topic (META_DEBUG_FOCUS, "Earlier attempt to focus %s failed\n",
+                  display->focus_window->desc);
+      set_focus_window (display,
+                        meta_display_lookup_x_window (display, display->server_focus_window),
+                        display->server_focus_serial);
+    }
+
   modified = event_get_modified_window (display, event);
 
   input_event = get_input_event (display, event);
@@ -2350,40 +2520,19 @@ event_callback (XEvent   *event,
           break;
         case XI_FocusIn:
         case XI_FocusOut:
-          if (window)
-            {
-              meta_window_notify_focus (window, enter_event);
-            }
-          else if (meta_display_xwindow_is_a_no_focus_window (display,
-                                                              enter_event->event))
-            {
-              meta_topic (META_DEBUG_FOCUS,
-                          "Focus %s event received on no_focus_window 0x%lx "
-                          "mode %s detail %s\n",
-                          enter_event->evtype == XI_FocusIn ? "in" :
-                          enter_event->evtype == XI_FocusOut ? "out" :
-                          "???",
-                          enter_event->event,
-                          meta_event_mode_to_string (enter_event->mode),
-                          meta_event_detail_to_string (enter_event->detail));
-            }
-          else
+          /* libXi does not properly copy the serial to the XIEnterEvent, so pull it
+           * from the parent XAnyEvent.
+           * See: https://bugs.freedesktop.org/show_bug.cgi?id=64687
+           */
+          handle_window_focus_event (display, window, enter_event, event->xany.serial);
+          if (!window)
             {
+              /* Check if the window is a root window. */
               MetaScreen *screen =
                 meta_display_screen_for_root(display,
                                              enter_event->event);
               if (screen == NULL)
                 break;
-
-              meta_topic (META_DEBUG_FOCUS,
-                          "Focus %s event received on root window 0x%lx "
-                          "mode %s detail %s\n",
-                          enter_event->evtype == XI_FocusIn ? "in" :
-                          enter_event->evtype == XI_FocusOut ? "out" :
-                          "???",
-                          enter_event->event,
-                          meta_event_mode_to_string (enter_event->mode),
-                          meta_event_detail_to_string (enter_event->detail));
           
               if (enter_event->evtype == XI_FocusIn &&
                   enter_event->mode == XINotifyDetailNone)
@@ -2521,13 +2670,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_lost_focus (window);
             }
           break;
         case MapNotify:
@@ -5622,18 +5764,57 @@ meta_display_set_input_focus_window (MetaDisplay *display,
     return;
 
   meta_error_trap_push (display);
+  display->focus_serial = XNextRequest (display->xdisplay);
+  meta_topic (META_DEBUG_FOCUS, "XSetInputFocus(%s, %u) with serial %lu\n",
+              window->desc, timestamp, display->focus_serial);
   XSetInputFocus (display->xdisplay,
                   focus_frame ? window->frame->xwindow : window->xwindow,
                   RevertToPointerRoot,
                   timestamp);
   meta_error_trap_pop (display);
 
-  display->expected_focus_window = window;
   display->last_focus_time = timestamp;
   display->active_screen = window->screen;
 
   if (window != display->autoraise_window)
     meta_display_remove_autoraise_callback (window->display);
+
+  set_focus_window (display, window, display->focus_serial);
+}
+
+void
+meta_display_request_take_focus (MetaDisplay *display,
+                                 MetaWindow  *window,
+                                 guint32      timestamp)
+{
+  if (timestamp_too_old (display, window, &timestamp))
+    return;
+
+  meta_topic (META_DEBUG_FOCUS, "WM_TAKE_FOCUS(%s, %u)\n",
+              window->desc, timestamp);
+
+  if (window != display->focus_window)
+    {
+      /* The "Globally Active Input" window case, where the window
+       * doesn't want us to call XSetInputFocus on it, but does
+       * want us to send a WM_TAKE_FOCUS.
+       *
+       * We can't just set display->focus_window to @window, since we
+       * we don't know when (or even if) the window will actually take
+       * focus, so we could end up being wrong for arbitrarily long.
+       * But we also can't leave it set to the current window, or else
+       * bug #597352 would come back. So we focus the no_focus_window
+       * now (and set display->focus_window to that), send the
+       * WM_TAKE_FOCUS, and then just forget about @window
+       * until/unless we get a FocusIn.
+       */
+      meta_display_focus_the_no_focus_window (display,
+                                              window->screen,
+                                              timestamp);
+    }
+  meta_window_send_icccm_message (window,
+                                  display->atom_WM_TAKE_FOCUS,
+                                  timestamp);
 }
 
 void
@@ -5644,15 +5825,19 @@ meta_display_focus_the_no_focus_window (MetaDisplay *display,
   if (timestamp_too_old (display, NULL, &timestamp))
     return;
 
+  display->focus_serial = XNextRequest (display->xdisplay);
+  meta_topic (META_DEBUG_FOCUS, "Focusing no_focus_window at %u with serial %lu\n",
+              timestamp, display->focus_serial);
   XSetInputFocus (display->xdisplay,
                   screen->no_focus_window,
                   RevertToPointerRoot,
                   timestamp);
-  display->expected_focus_window = NULL;
   display->last_focus_time = timestamp;
   display->active_screen = screen;
 
   meta_display_remove_autoraise_callback (display);
+
+  set_focus_window (display, NULL, display->focus_serial);
 }
 
 void
@@ -5762,11 +5947,9 @@ meta_display_has_shape (MetaDisplay *display)
  * meta_display_get_focus_window:
  * @display: a #MetaDisplay
  *
- * Get the window that, according to events received from X server,
- * currently has the input focus. We may have already sent a request
- * to the X server to move the focus window elsewhere. (The
- * expected_focus_window records where we've last set the input
- * focus.)
+ * Get our best guess as to the "currently" focused window (that is,
+ * the window that we expect will be focused at the point when the X
+ * server processes our next request).
  *
  * Return Value: (transfer none): The current focus window
  */
diff --git a/src/core/stack.c b/src/core/stack.c
index e91094d..3b05cdb 100644
--- a/src/core/stack.c
+++ b/src/core/stack.c
@@ -278,7 +278,7 @@ static gboolean
 is_focused_foreach (MetaWindow *window,
                     void       *data)
 {
-  if (window == window->display->expected_focus_window)
+  if (window->has_focus)
     {
       *((gboolean*) data) = TRUE;
       return FALSE;
@@ -335,11 +335,11 @@ get_standalone_layer (MetaWindow *window)
         layer = META_LAYER_BOTTOM;
       else if (window->fullscreen &&
                (focused_transient ||
-                window == window->display->expected_focus_window ||
-                window->display->expected_focus_window == NULL ||
-                (window->display->expected_focus_window != NULL &&
+                window == window->display->focus_window ||
+                window->display->focus_window == NULL ||
+                (window->display->focus_window != NULL &&
                  windows_on_different_monitor (window,
-                                               window->display->expected_focus_window))))
+                                               window->display->focus_window))))
         layer = META_LAYER_FULLSCREEN;
       else if (window->wm_state_above && !META_WINDOW_MAXIMIZED (window))
         layer = META_LAYER_TOP;
diff --git a/src/core/window-private.h b/src/core/window-private.h
index e9f935f..ec94cca 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -277,7 +277,7 @@ struct _MetaWindow
   /* EWHH demands attention flag */
   guint wm_state_demands_attention : 1;
   
-  /* this flag tracks receipt of focus_in focus_out */
+  /* TRUE iff window == window->display->focus_window */
   guint has_focus : 1;
 
   /* Have we placed this window? */
@@ -590,9 +590,8 @@ gboolean meta_window_property_notify   (MetaWindow *window,
                                         XEvent     *event);
 gboolean meta_window_client_message    (MetaWindow *window,
                                         XEvent     *event);
-gboolean meta_window_notify_focus      (MetaWindow *window,
-                                        XIEnterEvent *event);
-void     meta_window_lost_focus        (MetaWindow *window);
+void     meta_window_set_focused_internal (MetaWindow *window,
+                                           gboolean    focused);
 
 void     meta_window_set_current_workspace_hint (MetaWindow *window);
 
diff --git a/src/core/window.c b/src/core/window.c
index e6dd691..9ed387e 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -1754,16 +1754,6 @@ meta_window_unmanage (MetaWindow  *window,
                                            window,
                                            timestamp);
     }
-  else if (window->display->expected_focus_window == window)
-    {
-      meta_topic (META_DEBUG_FOCUS,
-                  "Focusing default window since expected focus window freed %s\n",
-                  window->desc);
-      window->display->expected_focus_window = NULL;
-      meta_workspace_focus_default_window (window->screen->active_workspace,
-                                           window,
-                                           timestamp);
-    }
   else
     {
       meta_topic (META_DEBUG_FOCUS,
@@ -1771,6 +1761,8 @@ meta_window_unmanage (MetaWindow  *window,
                   window->desc);
     }
 
+  g_assert (window->display->focus_window != window);
+
   if (window->struts)
     {
       meta_free_gslist_and_elements (window->struts);
@@ -1793,12 +1785,6 @@ meta_window_unmanage (MetaWindow  *window,
 
   g_assert (window->display->grab_window != window);
 
-  if (window->display->focus_window == window)
-    {
-      window->display->focus_window = NULL;
-      g_object_notify (G_OBJECT (window->display), "focus-window");
-    }
-
   if (window->maximized_horizontally || window->maximized_vertically)
     unmaximize_window_before_freeing (window);
 
@@ -3332,14 +3318,7 @@ meta_window_hide (MetaWindow *window)
       invalidate_work_areas (window);
     }
 
-  /* The check on expected_focus_window is a temporary workaround for
-   *  https://bugzilla.gnome.org/show_bug.cgi?id=597352
-   * We may have already switched away from this window but not yet
-   * gotten FocusIn/FocusOut events. A more complete comprehensive
-   * fix for these type of issues is described in the bug.
-   */
-  if (window->has_focus &&
-      window == window->display->expected_focus_window)
+  if (window->has_focus)
     {
       MetaWindow *not_this_one = NULL;
       MetaWorkspace *my_workspace = meta_window_get_workspace (window);
@@ -5975,10 +5954,10 @@ meta_window_focus (MetaWindow  *window,
           meta_topic (META_DEBUG_FOCUS,
                       "Sending WM_TAKE_FOCUS to %s since take_focus = true\n",
                       window->desc);
-          meta_window_send_icccm_message (window,
-                                          window->display->atom_WM_TAKE_FOCUS,
-                                          timestamp);
-          window->display->expected_focus_window = window;
+
+          meta_display_request_take_focus (window->display,
+                                           window,
+                                           timestamp);
         }
     }
 
@@ -6518,7 +6497,7 @@ meta_window_configure_request (MetaWindow *window,
   if (event->xconfigurerequest.value_mask & CWStackMode)
     {
       MetaWindow *active_window;
-      active_window = window->display->expected_focus_window;
+      active_window = window->display->focus_window;
       if (meta_prefs_get_disable_workarounds ())
         {
           meta_topic (META_DEBUG_STACK,
@@ -7197,8 +7176,7 @@ meta_window_propagate_focus_appearance (MetaWindow *window,
           parent->attached_focus_window = NULL;
         }
 
-      if (child_focus_state_changed && !parent->has_focus &&
-          parent != window->display->expected_focus_window)
+      if (child_focus_state_changed && !parent->has_focus)
         {
           meta_window_appears_focused_changed (parent);
         }
@@ -7208,18 +7186,12 @@ meta_window_propagate_focus_appearance (MetaWindow *window,
     }
 }
 
-static void
+void
 meta_window_set_focused_internal (MetaWindow *window,
                                   gboolean    focused)
 {
   if (focused)
     {
-      if (window == window->display->focus_window)
-        return;
-
-      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.
@@ -7278,7 +7250,6 @@ meta_window_set_focused_internal (MetaWindow *window,
         meta_display_ungrab_focus_window_button (window->display, window);
 
       g_signal_emit (window, window_signals[FOCUS], 0);
-      g_object_notify (G_OBJECT (window->display), "focus-window");
 
       if (!window->attached_focus_window)
         meta_window_appears_focused_changed (window);
@@ -7287,12 +7258,7 @@ meta_window_set_focused_internal (MetaWindow *window,
     }
   else
     {
-      if (window != window->display->focus_window)
-        return;
-
       meta_window_propagate_focus_appearance (window, FALSE);
-      window->display->focus_window = NULL;
-      g_object_notify (G_OBJECT (window->display), "focus-window");
       window->has_focus = FALSE;
 
       if (!window->attached_focus_window)
@@ -7313,115 +7279,6 @@ meta_window_set_focused_internal (MetaWindow *window,
     }
 }
 
-void
-meta_window_lost_focus (MetaWindow *window)
-{
-  meta_window_set_focused_internal (window, FALSE);
-}
-
-gboolean
-meta_window_notify_focus (MetaWindow   *window,
-                          XIEnterEvent *event)
-{
-  /* 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->evtype == XI_FocusIn ? "in" :
-              event->evtype == XI_FocusOut ? "out" :
-              "???",
-              window->desc, event->event,
-              event->event == window->xwindow ?
-              "client window" :
-              (window->frame && event->event == window->frame->xwindow) ?
-              "frame window" :
-              "unknown window",
-              meta_event_mode_to_string (event->mode),
-              meta_event_detail_to_string (event->detail));
-
-  /* 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 mutter'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->evtype == XI_FocusIn ||
-       event->evtype == XI_FocusOut) &&
-      (event->mode == NotifyGrab ||
-       event->mode == NotifyUngrab ||
-       /* From WindowMaker, ignore all funky pointer root events */
-       event->detail > NotifyNonlinearVirtual))
-    {
-      meta_topic (META_DEBUG_FOCUS,
-                  "Ignoring focus event generated by a grab or other weirdness\n");
-      return TRUE;
-    }
-
-  if (event->evtype == XI_FocusIn)
-    {
-      if (window->override_redirect)
-        {
-          window->display->focus_window = NULL;
-          g_object_notify (G_OBJECT (window->display), "focus-window");
-          return FALSE;
-        }
-      else
-        {
-          meta_window_set_focused_internal (window, TRUE);
-        }
-    }
-  else if (event->evtype == XI_FocusOut)
-    {
-      if (event->detail == NotifyInferior)
-        {
-          /* 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;
-        }
-      else
-        {
-          meta_window_set_focused_internal (window, FALSE);
-        }
-    }
-
-  /* Now set _NET_ACTIVE_WINDOW hint */
-  meta_display_update_active_window_hint (window->display);
-
-  return FALSE;
-}
-
 static gboolean
 process_property_notify (MetaWindow     *window,
                          XPropertyEvent *event)
diff --git a/src/meta/display.h b/src/meta/display.h
index d4c3aae..7ace858 100644
--- a/src/meta/display.h
+++ b/src/meta/display.h
@@ -165,6 +165,10 @@ void meta_display_set_input_focus_window   (MetaDisplay *display,
                                             gboolean     focus_frame,
                                             guint32      timestamp);
 
+void meta_display_request_take_focus       (MetaDisplay *display,
+                                            MetaWindow  *window,
+                                            guint32      timestamp);
+
 /* meta_display_focus_the_no_focus_window is called when the
  * designated no_focus_window should be focused, but is otherwise the
  * same as meta_display_set_input_focus_window
diff --git a/src/ui/tabpopup.c b/src/ui/tabpopup.c
index ac10294..c8dbeea 100644
--- a/src/ui/tabpopup.c
+++ b/src/ui/tabpopup.c
@@ -857,10 +857,7 @@ meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen)
   WnckWindowDisplayInfo wnck_window;
   wnck_window.icon = window->icon;
   wnck_window.mini_icon = window->mini_icon;
-  
-  wnck_window.is_active = FALSE;
-  if (window == window->display->expected_focus_window)
-    wnck_window.is_active = TRUE;
+  wnck_window.is_active = window->has_focus;
 
   if (window->frame)
     {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]