[mutter] window: add an appears-focused property, redraw shadows when it changes



commit f464b85ffc1f55e3551a0227fd614ea39bc33036
Author: Dan Winship <danw gnome org>
Date:   Thu Mar 24 21:36:47 2011 -0400

    window: add an appears-focused property, redraw shadows when it changes
    
    We need to redraw a window's shadow any time the value of
    meta_window_appears_focused() changes. So make that into a property so
    we can get notifications on it.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=636904

 src/compositor/meta-window-actor.c |   10 ++++
 src/core/window-private.h          |   12 +++--
 src/core/window-props.c            |    6 ++
 src/core/window.c                  |  101 +++++++++++++++++++++++-------------
 4 files changed, 89 insertions(+), 40 deletions(-)
---
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 83fcb49..1d8127a 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -374,6 +374,14 @@ window_decorated_notify (MetaWindow *mw,
 }
 
 static void
+window_appears_focused_notify (MetaWindow *mw,
+                               GParamSpec *arg1,
+                               gpointer    data)
+{
+  clutter_actor_queue_redraw (CLUTTER_ACTOR (data));
+}
+
+static void
 meta_window_actor_constructed (GObject *object)
 {
   MetaWindowActor        *self     = META_WINDOW_ACTOR (object);
@@ -422,6 +430,8 @@ meta_window_actor_constructed (GObject *object)
 
       g_signal_connect (priv->window, "notify::decorated",
                         G_CALLBACK (window_decorated_notify), self);
+      g_signal_connect (priv->window, "notify::appears-focused",
+                        G_CALLBACK (window_appears_focused_notify), self);
     }
   else
     {
diff --git a/src/core/window-private.h b/src/core/window-private.h
index ddd710c..cbac91d 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -253,11 +253,9 @@ struct _MetaWindow
   /* EWHH demands attention flag */
   guint wm_state_demands_attention : 1;
   
-  /* this flag tracks receipt of focus_in focus_out and
-   * determines whether we draw the focus
-   */
+  /* this flag tracks receipt of focus_in focus_out */
   guint has_focus : 1;
-  
+
   /* Have we placed this window? */
   guint placed : 1;
 
@@ -389,6 +387,9 @@ struct _MetaWindow
   MetaGroup *group;
 
   GObject *compositor_private;
+
+  /* Focused window that is (directly or indirectly) attached to this one */
+  MetaWindow *attached_focus_window;
 };
 
 struct _MetaWindowClass
@@ -634,4 +635,7 @@ void meta_window_update_net_wm_type (MetaWindow *window);
 void meta_window_update_monitor (MetaWindow *window);
 void meta_window_update_on_all_workspaces (MetaWindow *window);
 
+void meta_window_propagate_focus_appearance (MetaWindow *window,
+                                             gboolean    focused);
+
 #endif
diff --git a/src/core/window-props.c b/src/core/window-props.c
index cbc7826..ccea6b3 100644
--- a/src/core/window-props.c
+++ b/src/core/window-props.c
@@ -1466,6 +1466,9 @@ reload_transient_for (MetaWindow    *window,
                       MetaPropValue *value,
                       gboolean       initial)
 {
+  if (window->has_focus && window->xtransient_for != None)
+    meta_window_propagate_focus_appearance (window, FALSE);
+
   window->xtransient_for = None;
   
   if (value->type != META_PROP_VALUE_INVALID)
@@ -1509,6 +1512,9 @@ 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)
+    meta_window_propagate_focus_appearance (window, TRUE);
 }
 
 /**
diff --git a/src/core/window.c b/src/core/window.c
index 7f43aa3..69ed017 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -154,7 +154,8 @@ enum {
   PROP_USER_TIME,
   PROP_DEMANDS_ATTENTION,
   PROP_URGENT,
-  PROP_MUTTER_HINTS
+  PROP_MUTTER_HINTS,
+  PROP_APPEARS_FOCUSED
 };
 
 enum
@@ -239,6 +240,9 @@ meta_window_get_property(GObject         *object,
     case PROP_MUTTER_HINTS:
       g_value_set_string (value, win->mutter_hints);
       break;
+    case PROP_APPEARS_FOCUSED:
+      g_value_set_boolean (value, meta_window_appears_focused (win));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -366,6 +370,14 @@ meta_window_class_init (MetaWindowClass *klass)
                                                         "Contents of the _MUTTER_HINTS property of this window",
                                                         NULL,
                                                         G_PARAM_READABLE));
+  g_object_class_install_property (object_class,
+                                   PROP_APPEARS_FOCUSED,
+                                   g_param_spec_boolean ("appears-focused",
+                                                         "Appears focused",
+                                                         "Whether the window is drawn as being focused",
+                                                         FALSE,
+                                                         G_PARAM_READABLE));
+
   window_signals[WORKSPACE_CHANGED] =
     g_signal_new ("workspace-changed",
                   G_TYPE_FROM_CLASS (object_class),
@@ -856,6 +868,7 @@ meta_window_new_with_attrs (MetaDisplay       *display,
 
   window->frame = NULL;
   window->has_focus = FALSE;
+  window->attached_focus_window = NULL;
 
   window->maximized_horizontally = FALSE;
   window->maximized_vertically = FALSE;
@@ -1488,6 +1501,7 @@ 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)
     {
@@ -6359,20 +6373,46 @@ meta_window_client_message (MetaWindow *window,
   return FALSE;
 }
 
-static void
-check_ancestor_focus_appearance (MetaWindow *window)
+void
+meta_window_propagate_focus_appearance (MetaWindow *window,
+                                        gboolean    focused)
 {
-  MetaWindow *parent = meta_window_get_transient_for (window);
+  MetaWindow *child, *parent;
 
   if (!meta_prefs_get_attach_modal_dialogs ())
     return;
 
-  if (window->type != META_WINDOW_MODAL_DIALOG || !parent || parent == window)
-    return;
-  if (parent->frame)
-    meta_frame_queue_draw (parent->frame);
+  child = window;
+  parent = meta_window_get_transient_for (child);
+  while (child->type == META_WINDOW_MODAL_DIALOG && parent)
+    {
+      gboolean child_focus_state_changed;
+
+      if (focused)
+        {
+          if (parent->attached_focus_window == window)
+            break;
+          child_focus_state_changed = (parent->attached_focus_window == NULL);
+          parent->attached_focus_window = window;
+        }
+      else
+        {
+          if (parent->attached_focus_window != window)
+            break;
+          child_focus_state_changed = (parent->attached_focus_window != NULL);
+          parent->attached_focus_window = NULL;
+        }
+
+      if (child_focus_state_changed && !parent->has_focus)
+        {
+          g_object_notify (G_OBJECT (parent), "appears-focused");
+          if (parent->frame)
+            meta_frame_queue_draw (parent->frame);
+        }
 
-  check_ancestor_focus_appearance (parent);
+      child = parent;
+      parent = meta_window_get_transient_for (child);
+    }
 }
 
 gboolean
@@ -6517,11 +6557,16 @@ meta_window_notify_focus (MetaWindow *window,
               !meta_prefs_get_raise_on_click())
             meta_display_ungrab_focus_window_button (window->display, window);
 
-          /* parent window become active. */
-          check_ancestor_focus_appearance (window);
-
           g_signal_emit (window, window_signals[FOCUS], 0);
           g_object_notify (G_OBJECT (window->display), "focus-window");
+
+          if (!window->attached_focus_window)
+            {
+              g_object_notify (G_OBJECT (window), "appears-focused");
+              if (window->frame)
+                meta_frame_queue_draw (window->frame);
+            }
+          meta_window_propagate_focus_appearance (window, TRUE);
         }
     }
   else if (event->type == FocusOut ||
@@ -6549,11 +6594,14 @@ meta_window_notify_focus (MetaWindow *window,
           window->display->focus_window = NULL;
           g_object_notify (G_OBJECT (window->display), "focus-window");
           window->has_focus = FALSE;
-          /* parent window become inactive. */
-          check_ancestor_focus_appearance (window);
 
-          if (window->frame)
-            meta_frame_queue_draw (window->frame);
+          if (!window->attached_focus_window)
+            {
+              g_object_notify (G_OBJECT (window), "appears-focused");
+              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,
@@ -9692,16 +9740,6 @@ meta_window_get_frame (MetaWindow *window)
   return window->frame;
 }
 
-static gboolean
-transient_has_focus (MetaWindow *window,
-                     void       *data)
-{
-  if (window->type == META_WINDOW_MODAL_DIALOG && meta_window_appears_focused (window))
-    *((gboolean *)data) = TRUE;
-
-  return FALSE;
-}
-
 /**
  * meta_window_appears_focused:
  * @window: a #MetaWindow
@@ -9715,16 +9753,7 @@ transient_has_focus (MetaWindow *window,
 gboolean
 meta_window_appears_focused (MetaWindow *window)
 {
-  /* FIXME: meta_window_foreach_transient() iterates over all windows; we
-   *  should eat the complexity to cache a bit for this.
-   */
-  if (!window->has_focus && meta_prefs_get_attach_modal_dialogs ())
-    {
-      gboolean focus = FALSE;
-      meta_window_foreach_transient (window, transient_has_focus, &focus);
-      return focus;
-    }
-  return window->has_focus;
+  return window->has_focus || (window->attached_focus_window != NULL);
 }
 
 gboolean



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