[mutter] Don't read most properties for override-redirect windows



commit fd27647440ca0068450a5a74aadaae15dc065e00
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Sun Jun 14 08:37:57 2009 -0400

    Don't read most properties for override-redirect windows
    
    Skipping handling of properties for override redirect windows has
    two advantages: first it reduces the amount of work needed to get
    an override-redirect window (menu, tooltip, drag icon) onto the
    screen. But more importantly, it reduces the number of code-paths
    for an override-redirect to get into some code portion where it
    isn't expected.
    
    * Integrate the list of properties we load initially with the
      list of property hooks; this avoids having two separate lists
      that we have to keep in sync.
    
    * Add a flag to MetaWindowPropHooks to indicate whether the
      property should be handled for override-redirect windows;
      currently we load a) properties that identify the window -
      useful for debugging purposes b) WM_TRANSIENT_FOR (could be
      used to associate menus with toplevels.)
    
    * For properties that aren't always loaded through window-props.c,
      add !window->override checks to places that trigger loading,
      and add g_return_if_fail(!window->override) to the load
      functions as a double-check.
    
    http://bugzilla.gnome.org/show_bug.cgi?id=582639

 src/core/display-private.h |    4 +-
 src/core/window-props.c    |  141 ++++++++++++++++++++++++++++++++-----------
 src/core/window-props.h    |    9 +++
 src/core/window.c          |   58 +++++++------------
 4 files changed, 138 insertions(+), 74 deletions(-)
---
diff --git a/src/core/display-private.h b/src/core/display-private.h
index 8aeb12f..85277c8 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -52,6 +52,7 @@ typedef struct _MetaStack      MetaStack;
 typedef struct _MetaUISlave    MetaUISlave;
 
 typedef struct _MetaGroupPropHooks  MetaGroupPropHooks;
+typedef struct _MetaWindowPropHooks MetaWindowPropHooks;
 
 typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
 
@@ -235,8 +236,9 @@ struct _MetaDisplay
   MetaWindow *window_with_menu;
 
   /* Managed by window-props.c */
-  gpointer *prop_hooks_table;
+  MetaWindowPropHooks *prop_hooks_table;
   GHashTable *prop_hooks;
+  int n_prop_hooks;
 
   /* Managed by group-props.c */
   MetaGroupPropHooks *group_prop_hooks;
diff --git a/src/core/window-props.c b/src/core/window-props.c
index 2b99494..773eaeb 100644
--- a/src/core/window-props.c
+++ b/src/core/window-props.c
@@ -56,14 +56,16 @@ typedef void (* ReloadValueFunc) (MetaWindow    *window,
                                   MetaPropValue *value,
                                   gboolean       initial);
 
-typedef struct MetaWindowPropHooks
+struct _MetaWindowPropHooks
 {
   Atom property;
   MetaPropValueType type;
   ReloadValueFunc reload_func;
-} MetaWindowPropHooks;
+  gboolean load_initially;
+  gboolean include_override_redirect;
+};
 
-static void init_prop_value            (MetaDisplay         *display,
+static void init_prop_value            (MetaWindow          *window,
                                         MetaWindowPropHooks *hooks,
                                         MetaPropValue       *value);
 static void reload_prop_value          (MetaWindow          *window,
@@ -124,7 +126,7 @@ meta_window_reload_properties_from_xwindow (MetaWindow *window,
   while (i < n_properties)
     {
       MetaWindowPropHooks *hooks = find_hooks (window->display, properties[i]);
-      init_prop_value (window->display, hooks, &values[i]);
+      init_prop_value (window, hooks, &values[i]);
       ++i;
     }
   
@@ -145,13 +147,59 @@ meta_window_reload_properties_from_xwindow (MetaWindow *window,
   g_free (values);
 }
 
+void
+meta_window_load_initial_properties (MetaWindow *window)
+{
+  int i, j;
+  MetaPropValue *values;
+  int n_properties = 0;
+
+  values = g_new0 (MetaPropValue, window->display->n_prop_hooks);
+
+  j = 0;
+  for (i = 0; i < window->display->n_prop_hooks; i++)
+    {
+      MetaWindowPropHooks *hooks = &window->display->prop_hooks_table[i];
+      if (hooks->load_initially)
+        {
+          init_prop_value (window, hooks, &values[j]);
+          ++j;
+        }
+    }
+  n_properties = j;
+
+  meta_prop_get_values (window->display, window->xwindow,
+                        values, n_properties);
+
+  j = 0;
+  for (i = 0; i < window->display->n_prop_hooks; i++)
+    {
+      MetaWindowPropHooks *hooks = &window->display->prop_hooks_table[i];
+      if (hooks->load_initially)
+        {
+          /* If we didn't actually manage to load anything then we don't need
+           * to call the reload function; this is different from a notification
+           * where disappearance of a previously present value is significant.
+           */
+          if (values[j].type != META_PROP_VALUE_INVALID)
+            reload_prop_value (window, hooks, &values[j], TRUE);
+          ++j;
+        }
+    }
+
+  meta_prop_free_values (values, n_properties);
+
+  g_free (values);
+}
+
 /* Fill in the MetaPropValue used to get the value of "property" */
 static void
-init_prop_value (MetaDisplay         *display,
+init_prop_value (MetaWindow          *window,
                  MetaWindowPropHooks *hooks,
                  MetaPropValue       *value)
 {
-  if (!hooks || hooks->type == META_PROP_VALUE_INVALID)
+  if (!hooks || hooks->type == META_PROP_VALUE_INVALID ||
+      (window->override_redirect && !hooks->include_override_redirect))
     {
       value->type = META_PROP_VALUE_INVALID;
       value->atom = None;
@@ -169,7 +217,8 @@ reload_prop_value (MetaWindow          *window,
                    MetaPropValue       *value,
                    gboolean             initial)
 {
-  if (hooks && hooks->reload_func != NULL)
+  if (hooks && hooks->reload_func != NULL &&
+      !(window->override_redirect && !hooks->include_override_redirect))
     (* hooks->reload_func) (window, value, initial);
 }
 
@@ -1418,35 +1467,51 @@ reload_transient_for (MetaWindow    *window,
 void
 meta_display_init_window_prop_hooks (MetaDisplay *display)
 {
-  MetaWindowPropHooks hooks[] = {
-    { display->atom_WM_STATE,          META_PROP_VALUE_INVALID,  NULL },
-    { display->atom_WM_CLIENT_MACHINE, META_PROP_VALUE_STRING,   reload_wm_client_machine },
-    { display->atom__NET_WM_PID,       META_PROP_VALUE_CARDINAL, reload_net_wm_pid },
-    { display->atom__NET_WM_USER_TIME, META_PROP_VALUE_CARDINAL, reload_net_wm_user_time },
-    { display->atom__NET_WM_NAME,      META_PROP_VALUE_UTF8,     reload_net_wm_name },
-    { XA_WM_NAME,                      META_PROP_VALUE_TEXT_PROPERTY, reload_wm_name },
-    { display->atom__NET_WM_ICON,      META_PROP_VALUE_INVALID,  reload_net_wm_icon },
-    { display->atom__KWM_WIN_ICON,     META_PROP_VALUE_INVALID,  reload_kwm_win_icon },
-    { display->atom__NET_WM_ICON_NAME, META_PROP_VALUE_UTF8,     reload_net_wm_icon_name },
-    { XA_WM_ICON_NAME,                 META_PROP_VALUE_TEXT_PROPERTY, reload_wm_icon_name },
-    { display->atom__NET_WM_STATE,     META_PROP_VALUE_ATOM_LIST, reload_net_wm_state },
-    { display->atom__MOTIF_WM_HINTS,   META_PROP_VALUE_MOTIF_HINTS, reload_mwm_hints },
-    { display->atom__NET_WM_ICON_GEOMETRY, META_PROP_VALUE_INVALID, NULL },
-    { XA_WM_CLASS,                     META_PROP_VALUE_CLASS_HINT, reload_wm_class },
-    { display->atom_WM_CLIENT_LEADER,  META_PROP_VALUE_INVALID, complain_about_broken_client },
-    { display->atom_SM_CLIENT_ID,      META_PROP_VALUE_INVALID, complain_about_broken_client },
-    { display->atom_WM_WINDOW_ROLE,    META_PROP_VALUE_INVALID, reload_wm_window_role },
-    { display->atom__NET_WM_WINDOW_TYPE, META_PROP_VALUE_INVALID, reload_net_wm_window_type },
-    { display->atom__NET_WM_DESKTOP,   META_PROP_VALUE_CARDINAL, reload_net_wm_desktop },
-    { display->atom__NET_WM_STRUT,         META_PROP_VALUE_INVALID, reload_struts },
-    { display->atom__NET_WM_STRUT_PARTIAL, META_PROP_VALUE_INVALID, reload_struts },
-    { display->atom__NET_STARTUP_ID,  META_PROP_VALUE_UTF8,     reload_net_startup_id },
-    { display->atom__NET_WM_SYNC_REQUEST_COUNTER, META_PROP_VALUE_SYNC_COUNTER, reload_update_counter },
-    { XA_WM_NORMAL_HINTS,              META_PROP_VALUE_SIZE_HINTS, reload_normal_hints },
-    { display->atom_WM_PROTOCOLS,      META_PROP_VALUE_ATOM_LIST, reload_wm_protocols },
-    { XA_WM_HINTS,                     META_PROP_VALUE_WM_HINTS,  reload_wm_hints },
-    { XA_WM_TRANSIENT_FOR,             META_PROP_VALUE_WINDOW,    reload_transient_for },
-    { display->atom__NET_WM_USER_TIME_WINDOW, META_PROP_VALUE_WINDOW, reload_net_wm_user_time_window },
+  /* INIT: load initially
+   * O-R:  fetch for override-redirect windows
+   *
+   * The ordering here is significant for the properties we load
+   * initially: they are roughly ordered in the order we want them to
+   * be gotten. We want to get window name and class first so we can
+   * use them in error messages and such. However, name is modified
+   * depending on wm_client_machine, so push it slightly sooner.
+   *
+   * For override-redirect windows, we pay attention to:
+   *
+   *  - properties that identify the window: useful for debugging
+   *    purposes.
+   *  - NET_WM_WINDOW_TYPE: can be used to do appropriate handling
+   *    for different types of override-redirect windows.
+   */
+  MetaWindowPropHooks hooks[] = {                                                       /* INIT   O-R     */
+    { display->atom_WM_CLIENT_MACHINE, META_PROP_VALUE_STRING,   reload_wm_client_machine, TRUE,  TRUE },
+    { display->atom__NET_WM_NAME,      META_PROP_VALUE_UTF8,     reload_net_wm_name,       TRUE,  TRUE },
+    { XA_WM_CLASS,                     META_PROP_VALUE_CLASS_HINT, reload_wm_class,        TRUE,  TRUE },
+    { display->atom__NET_WM_PID,       META_PROP_VALUE_CARDINAL, reload_net_wm_pid,        TRUE,  TRUE },
+    { XA_WM_NAME,                      META_PROP_VALUE_TEXT_PROPERTY, reload_wm_name,      TRUE,  TRUE },
+    { display->atom__NET_WM_ICON_NAME, META_PROP_VALUE_UTF8,     reload_net_wm_icon_name,  TRUE,  FALSE },
+    { XA_WM_ICON_NAME,                 META_PROP_VALUE_TEXT_PROPERTY, reload_wm_icon_name, TRUE,  FALSE },
+    { display->atom__NET_WM_DESKTOP,   META_PROP_VALUE_CARDINAL, reload_net_wm_desktop,    TRUE,  FALSE },
+    { display->atom__NET_STARTUP_ID,   META_PROP_VALUE_UTF8,     reload_net_startup_id,    TRUE,  FALSE },
+    { display->atom__NET_WM_SYNC_REQUEST_COUNTER, META_PROP_VALUE_SYNC_COUNTER, reload_update_counter, TRUE, FALSE },
+    { XA_WM_NORMAL_HINTS,              META_PROP_VALUE_SIZE_HINTS, reload_normal_hints,    TRUE,  FALSE },
+    { display->atom_WM_PROTOCOLS,      META_PROP_VALUE_ATOM_LIST, reload_wm_protocols,     TRUE,  FALSE },
+    { XA_WM_HINTS,                     META_PROP_VALUE_WM_HINTS,  reload_wm_hints,         TRUE,  FALSE },
+    { display->atom__NET_WM_USER_TIME, META_PROP_VALUE_CARDINAL, reload_net_wm_user_time,  TRUE,  FALSE },
+    { display->atom__NET_WM_STATE,     META_PROP_VALUE_ATOM_LIST, reload_net_wm_state,     TRUE,  FALSE },
+    { display->atom__MOTIF_WM_HINTS,   META_PROP_VALUE_MOTIF_HINTS, reload_mwm_hints,      TRUE,  FALSE },
+    { XA_WM_TRANSIENT_FOR,             META_PROP_VALUE_WINDOW,    reload_transient_for,    TRUE,  FALSE },
+    { display->atom__NET_WM_USER_TIME_WINDOW, META_PROP_VALUE_WINDOW, reload_net_wm_user_time_window, TRUE, FALSE },
+    { display->atom_WM_STATE,          META_PROP_VALUE_INVALID,  NULL,                     FALSE, FALSE },
+    { display->atom__NET_WM_ICON,      META_PROP_VALUE_INVALID,  reload_net_wm_icon,       FALSE, FALSE },
+    { display->atom__KWM_WIN_ICON,     META_PROP_VALUE_INVALID,  reload_kwm_win_icon,      FALSE, FALSE },
+    { display->atom__NET_WM_ICON_GEOMETRY, META_PROP_VALUE_INVALID, NULL,                  FALSE, FALSE },
+    { display->atom_WM_CLIENT_LEADER,  META_PROP_VALUE_INVALID, complain_about_broken_client, FALSE, FALSE },
+    { display->atom_SM_CLIENT_ID,      META_PROP_VALUE_INVALID, complain_about_broken_client, FALSE, FALSE },
+    { display->atom_WM_WINDOW_ROLE,    META_PROP_VALUE_INVALID, reload_wm_window_role,        FALSE, FALSE },
+    { display->atom__NET_WM_WINDOW_TYPE, META_PROP_VALUE_INVALID, reload_net_wm_window_type,  FALSE, TRUE },
+    { display->atom__NET_WM_STRUT,         META_PROP_VALUE_INVALID, reload_struts,            FALSE, FALSE },
+    { display->atom__NET_WM_STRUT_PARTIAL, META_PROP_VALUE_INVALID, reload_struts,            FALSE, FALSE },
     { 0 },
   };
 
@@ -1460,6 +1525,9 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
 
   while (cursor->property)
     {
+      /* Doing initial loading doesn't make sense if we just want notification */
+      g_assert (!(hooks->load_initially && hooks->type == META_PROP_VALUE_INVALID));
+
       /* Atoms are safe to use with GINT_TO_POINTER because it's safe with
        * anything 32 bits or less, and atoms are 32 bits with the top three
        * bits clear.  (Scheifler & Gettys, 2e, p372)
@@ -1469,6 +1537,7 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
                            cursor);
       cursor++;
     }
+  display->n_prop_hooks = cursor - table;
 }
 
 void
diff --git a/src/core/window-props.h b/src/core/window-props.h
index 1e60eff..273dc7f 100644
--- a/src/core/window-props.h
+++ b/src/core/window-props.h
@@ -96,6 +96,15 @@ void meta_window_reload_properties_from_xwindow
                                     gboolean    initial);
 
 /**
+ * Requests the current values for standard properties for a given
+ * window from the server, and deals with them appropriately.
+ * Does not return them to the caller (they've been dealt with!)
+ *
+ * \param window      The window.
+ */
+void meta_window_load_initial_properties (MetaWindow *window);
+
+/**
  * Initialises the hooks used for the reload_propert* functions
  * on a particular display, and stores a pointer to them in the
  * display.
diff --git a/src/core/window.c b/src/core/window.c
index 7850315..09fc8d7 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -426,14 +426,10 @@ meta_window_new_with_attrs (MetaDisplay       *display,
   gulong existing_wm_state;
   gulong event_mask;
   MetaMoveResizeFlags flags;
-#define N_INITIAL_PROPS 19
-  Atom initial_props[N_INITIAL_PROPS];
-  int i;
   gboolean has_shape;
   MetaScreen *screen;
 
   g_assert (attrs != NULL);
-  g_assert (N_INITIAL_PROPS == (int) G_N_ELEMENTS (initial_props));
 
   meta_verbose ("Attempting to manage 0x%lx\n", xwindow);
 
@@ -777,39 +773,15 @@ meta_window_new_with_attrs (MetaDisplay       *display,
   window->xgroup_leader = None;
   meta_window_compute_group (window);
 
-  /* Fill these in the order we want them to be gotten.  we want to
-   * get window name and class first so we can use them in error
-   * messages and such.  However, name is modified depending on
-   * wm_client_machine, so push it slightly sooner.
-   */
-  i = 0;
-  initial_props[i++] = display->atom_WM_CLIENT_MACHINE;
-  initial_props[i++] = display->atom__NET_WM_NAME;
-  initial_props[i++] = XA_WM_CLASS;
-  initial_props[i++] = display->atom__NET_WM_PID;
-  initial_props[i++] = XA_WM_NAME;
-  initial_props[i++] = display->atom__NET_WM_ICON_NAME;
-  initial_props[i++] = XA_WM_ICON_NAME;
-  initial_props[i++] = display->atom__NET_WM_DESKTOP;
-  initial_props[i++] = display->atom__NET_STARTUP_ID;
-  initial_props[i++] = display->atom__NET_WM_SYNC_REQUEST_COUNTER;
-  initial_props[i++] = XA_WM_NORMAL_HINTS;
-  initial_props[i++] = display->atom_WM_PROTOCOLS;
-  initial_props[i++] = XA_WM_HINTS;
-  initial_props[i++] = display->atom__NET_WM_USER_TIME;
-  initial_props[i++] = display->atom__NET_WM_STATE;
-  initial_props[i++] = display->atom__MOTIF_WM_HINTS;
-  initial_props[i++] = XA_WM_TRANSIENT_FOR;
-  initial_props[i++] = display->atom__NET_WM_USER_TIME_WINDOW;
-  initial_props[i++] = display->atom__NET_WM_FULLSCREEN_MONITORS;
-  g_assert (N_INITIAL_PROPS == i);
-
-  meta_window_reload_properties (window, initial_props, N_INITIAL_PROPS, TRUE);
+  meta_window_load_initial_properties (window);
 
   if (!window->override_redirect)
-    update_sm_hints (window); /* must come after transient_for */
+    {
+      update_sm_hints (window); /* must come after transient_for */
+
+      meta_window_update_role (window);
+    }
 
-  meta_window_update_role (window);
   meta_window_update_net_wm_type (window);
 
   if (!window->override_redirect)
@@ -846,7 +818,7 @@ meta_window_new_with_attrs (MetaDisplay       *display,
    * much we can do...except record the current time so that any children
    * can use this time as a fallback.
    */
-  if (!window->net_wm_user_time_set) {
+  if (!window->override_redirect && !window->net_wm_user_time_set) {
     MetaWindow *parent = NULL;
     if (window->xtransient_for)
       parent = meta_display_lookup_x_window (window->display,
@@ -963,9 +935,11 @@ meta_window_new_with_attrs (MetaDisplay       *display,
 
   /* for the various on_all_workspaces = TRUE possible above */
   if (!window->override_redirect)
-    meta_window_set_current_workspace_hint (window);
+    {
+      meta_window_set_current_workspace_hint (window);
 
-  meta_window_update_struts (window);
+      meta_window_update_struts (window);
+    }
 
   /* Must add window to stack before doing move/resize, since the
    * window might have fullscreen size (i.e. should have been
@@ -6010,6 +5984,8 @@ meta_window_get_icon_geometry (MetaWindow    *window,
   gulong *geometry = NULL;
   int nitems;
 
+  g_return_val_if_fail (!window->override_redirect, FALSE);
+
   if (meta_prop_get_cardinal_list (window->display,
                                    window->xwindow,
                                    window->display->atom__NET_WM_ICON_GEOMETRY,
@@ -6144,6 +6120,8 @@ meta_window_update_role (MetaWindow *window)
 {
   char *str;
 
+  g_return_if_fail (!window->override_redirect);
+
   if (window->role)
     g_free (window->role);
   window->role = NULL;
@@ -6245,6 +6223,8 @@ meta_window_update_icon_now (MetaWindow *window)
   GdkPixbuf *icon;
   GdkPixbuf *mini_icon;
 
+  g_return_if_fail (!window->override_redirect);
+
   icon = NULL;
   mini_icon = NULL;
 
@@ -6353,6 +6333,8 @@ meta_window_update_struts (MetaWindow *window)
   int nitems;
   gboolean changed;
 
+  g_return_if_fail (!window->override_redirect);
+
   meta_verbose ("Updating struts for %s\n", window->desc);
 
   old_struts = window->struts;
@@ -8545,6 +8527,8 @@ meta_window_set_user_time (MetaWindow *window,
    * a future time.
    */
 
+  g_return_if_fail (!window->override_redirect);
+
   /* Only update the time if this timestamp is newer... */
   if (window->net_wm_user_time_set &&
       XSERVER_TIME_IS_BEFORE (timestamp, window->net_wm_user_time))



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