[mutter] window: fix appears-focused propagation with attached grandchildren



commit 48cabd136439659d40947a6be54abdf19dbac5e4
Author: Dan Winship <danw gnome org>
Date:   Wed Apr 13 17:08:12 2011 -0400

    window: fix appears-focused propagation with attached grandchildren
    
    When detaching/attaching a dialog, we were only updating
    appears-focused on the parent if the child itself was focused, but in
    fact, we need to do it if the child has an attached child which is
    focused too.
    
    To simplify the case of detaching a focused subtree from its parent,
    we change meta_window_propagate_focus_appearance() to use
    @window->display->focus_window as the window to add/remove as the
    attached_focus_window, and @window only as the starting point to
    propagate from. That way we can propagate focus-removal up to
    @window's (soon-to-be-ex-)ancestors without having to remove it from
    its descendants as well.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=647712

 src/core/window-props.c |    4 ++--
 src/core/window.c       |   29 +++++++++++++++++++++++------
 2 files changed, 25 insertions(+), 8 deletions(-)
---
diff --git a/src/core/window-props.c b/src/core/window-props.c
index e970ffe..42438c2 100644
--- a/src/core/window-props.c
+++ b/src/core/window-props.c
@@ -1470,7 +1470,7 @@ reload_transient_for (MetaWindow    *window,
 {
   MetaWindow *parent = NULL;
 
-  if (window->has_focus && window->xtransient_for != None)
+  if (meta_window_appears_focused (window) && window->xtransient_for != None)
     meta_window_propagate_focus_appearance (window, FALSE);
 
   window->xtransient_for = None;
@@ -1536,7 +1536,7 @@ reload_transient_for (MetaWindow    *window,
   if (!window->constructing && !window->override_redirect)
     meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
 
-  if (window->has_focus && window->xtransient_for != None)
+  if (meta_window_appears_focused (window) && window->xtransient_for != None)
     meta_window_propagate_focus_appearance (window, TRUE);
 }
 
diff --git a/src/core/window.c b/src/core/window.c
index a069060..2857825 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -1520,6 +1520,8 @@ meta_window_unmanage (MetaWindow  *window,
    * on what gets focused, maintaining sloppy focus
    * invariants.
    */
+  if (meta_window_appears_focused (window))
+    meta_window_propagate_focus_appearance (window, FALSE);
   if (window->has_focus)
     {
       meta_topic (META_DEBUG_FOCUS,
@@ -1528,7 +1530,6 @@ meta_window_unmanage (MetaWindow  *window,
       meta_workspace_focus_default_window (window->screen->active_workspace,
                                            window,
                                            timestamp);
-      meta_window_propagate_focus_appearance (window, FALSE);
     }
   else if (window->display->expected_focus_window == window)
     {
@@ -6415,15 +6416,30 @@ meta_window_client_message (MetaWindow *window,
   return FALSE;
 }
 
+/**
+ * meta_window_propagate_focus_appearance:
+ * @window: the window to start propagating from
+ * @focused: %TRUE if @window's ancestors should appear focused,
+ *   %FALSE if they should not.
+ *
+ * Adjusts the value of #MetaWindow:appears-focused on @window's
+ * ancestors (but not @window itself). If @focused is %TRUE, each of
+ * @window's ancestors will have its %attached_focus_window field set
+ * to the current %focus_window. If @focused if %FALSE, each of
+ * @window's ancestors will have its %attached_focus_window field
+ * cleared if it is currently %focus_window.
+ */
 void
 meta_window_propagate_focus_appearance (MetaWindow *window,
                                         gboolean    focused)
 {
-  MetaWindow *child, *parent;
+  MetaWindow *child, *parent, *focus_window;
 
   if (!meta_prefs_get_attach_modal_dialogs ())
     return;
 
+  focus_window = window->display->focus_window;
+
   child = window;
   parent = meta_window_get_transient_for (child);
   while (parent && (!focused || child->type == META_WINDOW_MODAL_DIALOG))
@@ -6432,14 +6448,14 @@ meta_window_propagate_focus_appearance (MetaWindow *window,
 
       if (focused)
         {
-          if (parent->attached_focus_window == window)
+          if (parent->attached_focus_window == focus_window)
             break;
           child_focus_state_changed = (parent->attached_focus_window == NULL);
-          parent->attached_focus_window = window;
+          parent->attached_focus_window = focus_window;
         }
       else
         {
-          if (parent->attached_focus_window != window)
+          if (parent->attached_focus_window != focus_window)
             break;
           child_focus_state_changed = (parent->attached_focus_window != NULL);
           parent->attached_focus_window = NULL;
@@ -6634,6 +6650,8 @@ meta_window_notify_focus (MetaWindow *window,
           meta_topic (META_DEBUG_FOCUS,
                       "* Focus --> NULL (was %s)\n", window->desc);
 
+          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;
@@ -6644,7 +6662,6 @@ meta_window_notify_focus (MetaWindow *window,
               if (window->frame)
                 meta_frame_queue_draw (window->frame);
             }
-          meta_window_propagate_focus_appearance (window, FALSE);
 
           meta_error_trap_push (window->display);
           XUninstallColormap (window->display->xdisplay,



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