metacity r4097 - in trunk: . src/core



Author: tthurman
Date: Thu Jan 29 14:32:31 2009
New Revision: 4097
URL: http://svn.gnome.org/viewvc/metacity?rev=4097&view=rev

Log:
        Window properties are looked up in a hash table rather than
        by iteration over an array.  Saves ~44us per window, but
        also makes the code cleaner.
	* src/core/display-private.h:
	* src/core/window-props.c:



Modified:
   trunk/ChangeLog
   trunk/src/core/display-private.h
   trunk/src/core/window-props.c

Modified: trunk/src/core/display-private.h
==============================================================================
--- trunk/src/core/display-private.h	(original)
+++ trunk/src/core/display-private.h	Thu Jan 29 14:32:31 2009
@@ -51,7 +51,6 @@
 typedef struct _MetaUISlave    MetaUISlave;
 typedef struct _MetaWorkspace  MetaWorkspace;
 
-typedef struct _MetaWindowPropHooks MetaWindowPropHooks;
 typedef struct _MetaGroupPropHooks  MetaGroupPropHooks;
 
 typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
@@ -232,7 +231,8 @@
   MetaWindow *window_with_menu;
 
   /* Managed by window-props.c */
-  MetaWindowPropHooks *prop_hooks;
+  gpointer *prop_hooks_table;
+  GHashTable *prop_hooks;
 
   /* Managed by group-props.c */
   MetaGroupPropHooks *group_prop_hooks;

Modified: trunk/src/core/window-props.c
==============================================================================
--- trunk/src/core/window-props.c	(original)
+++ trunk/src/core/window-props.c	Thu Jan 29 14:32:31 2009
@@ -9,13 +9,15 @@
  * Note that all the meta_window_reload_propert* functions require a
  * round trip to the server.
  *
- * \bug Not all the properties have moved over from their original
- * handler in window.c yet.
+ * The guts of this system are in meta_display_init_window_prop_hooks().
+ * Reading this function will give you insight into how this all fits
+ * together.
  */
 
 /* 
  * Copyright (C) 2001, 2002, 2003 Red Hat, Inc.
  * Copyright (C) 2004, 2005 Elijah Newren
+ * Copyright (C) 2009 Thomas Thurman
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -50,19 +52,16 @@
 #define HOST_NAME_MAX 255
 #endif
 
-typedef void (* InitValueFunc)   (MetaDisplay   *display,
-                                  Atom           property,
-                                  MetaPropValue *value);
 typedef void (* ReloadValueFunc) (MetaWindow    *window,
                                   MetaPropValue *value,
                                   gboolean       initial);
 
-struct _MetaWindowPropHooks
+typedef struct MetaWindowPropHooks
 {
-  Atom property;
-  InitValueFunc   init_func;
-  ReloadValueFunc reload_func;
-};
+  Atom              property;
+  MetaPropValueType type;
+  ReloadValueFunc   reload_func;
+} MetaWindowPropHooks;
 
 static void init_prop_value            (MetaDisplay   *display,
                                         Atom           property,
@@ -149,14 +148,18 @@
                  Atom           property,
                  MetaPropValue *value)
 {
-  MetaWindowPropHooks *hooks;  
-
-  value->type = META_PROP_VALUE_INVALID;
-  value->atom = None;
-  
-  hooks = find_hooks (display, property);
-  if (hooks && hooks->init_func != NULL)
-    (* hooks->init_func) (display, property, value);
+  MetaWindowPropHooks *hooks = find_hooks (display, property);
+    
+  if (!hooks || hooks->type == META_PROP_VALUE_INVALID)
+    {
+      value->type = META_PROP_VALUE_INVALID;
+      value->atom = None;
+    }
+  else
+    {
+      value->type = hooks->type;
+      value->atom = property;
+    }
 }
 
 static void
@@ -164,23 +167,13 @@
                    MetaPropValue *value,
                    gboolean       initial)
 {
-  MetaWindowPropHooks *hooks;  
-  
-  hooks = find_hooks (window->display, value->atom);
+  MetaWindowPropHooks *hooks = find_hooks (window->display, value->atom);
+
   if (hooks && hooks->reload_func != NULL)
     (* hooks->reload_func) (window, value, initial);
 }
 
 static void
-init_wm_client_machine (MetaDisplay   *display,
-                        Atom           property,
-                        MetaPropValue *value)
-{
-  value->type = META_PROP_VALUE_STRING;
-  value->atom = display->atom_WM_CLIENT_MACHINE;
-}
-
-static void
 reload_wm_client_machine (MetaWindow    *window,
                           MetaPropValue *value,
                           gboolean       initial)
@@ -255,15 +248,6 @@
 }
 
 static void
-init_net_wm_pid (MetaDisplay   *display,
-                 Atom           property,
-                 MetaPropValue *value)
-{
-  value->type = META_PROP_VALUE_CARDINAL;
-  value->atom = display->atom__NET_WM_PID;
-}
-
-static void
 reload_net_wm_pid (MetaWindow    *window,
                    MetaPropValue *value,
                    gboolean       initial)
@@ -285,15 +269,6 @@
 }
 
 static void
-init_net_wm_user_time (MetaDisplay   *display,
-                       Atom           property,
-                       MetaPropValue *value)
-{
-  value->type = META_PROP_VALUE_CARDINAL;
-  value->atom = display->atom__NET_WM_USER_TIME;
-}
-
-static void
 reload_net_wm_user_time (MetaWindow    *window,
                          MetaPropValue *value,
                          gboolean       initial)
@@ -306,15 +281,6 @@
 }
 
 static void
-init_net_wm_user_time_window (MetaDisplay   *display,
-                              Atom           property,
-                              MetaPropValue *value)
-{
-  value->type = META_PROP_VALUE_WINDOW;
-  value->atom = display->atom__NET_WM_USER_TIME_WINDOW;
-}
-
-static void
 reload_net_wm_user_time_window (MetaWindow    *window,
                                 MetaPropValue *value,
                                 gboolean       initial)
@@ -460,15 +426,6 @@
 }
 
 static void
-init_net_wm_name (MetaDisplay   *display,
-                  Atom           property,
-                  MetaPropValue *value)
-{
-  value->type = META_PROP_VALUE_UTF8;
-  value->atom = display->atom__NET_WM_NAME;
-}
-
-static void
 reload_net_wm_name (MetaWindow    *window,
                     MetaPropValue *value,
                     gboolean       initial)
@@ -490,16 +447,6 @@
     }
 }
 
-
-static void
-init_wm_name (MetaDisplay   *display,
-              Atom           property,
-              MetaPropValue *value)
-{
-  value->type = META_PROP_VALUE_TEXT_PROPERTY;
-  value->atom = XA_WM_NAME;
-}
-
 static void
 reload_wm_name (MetaWindow    *window,
                 MetaPropValue *value,
@@ -539,15 +486,6 @@
 }
 
 static void
-init_net_wm_icon_name (MetaDisplay   *display,
-                  Atom           property,
-                  MetaPropValue *value)
-{
-  value->type = META_PROP_VALUE_UTF8;
-  value->atom = display->atom__NET_WM_ICON_NAME;
-}
-
-static void
 reload_net_wm_icon_name (MetaWindow    *window,
                          MetaPropValue *value,
                          gboolean       initial)
@@ -569,16 +507,6 @@
     }
 }
 
-
-static void
-init_wm_icon_name (MetaDisplay   *display,
-                  Atom           property,
-                  MetaPropValue *value)
-{
-  value->type = META_PROP_VALUE_TEXT_PROPERTY;
-  value->atom = XA_WM_ICON_NAME;
-}
-
 static void
 reload_wm_icon_name (MetaWindow    *window,
                      MetaPropValue *value,
@@ -605,15 +533,6 @@
 }
 
 static void
-init_net_wm_state (MetaDisplay    *display,
-                   Atom            property,
-                   MetaPropValue  *value)
-{
-  value->type = META_PROP_VALUE_ATOM_LIST;
-  value->atom = display->atom__NET_WM_STATE;
-}
-
-static void
 reload_net_wm_state (MetaWindow    *window,
                      MetaPropValue *value,
                      gboolean       initial)
@@ -682,15 +601,6 @@
 }
 
 static void
-init_mwm_hints (MetaDisplay    *display,
-                Atom            property,
-                MetaPropValue  *value)
-{
-  value->type = META_PROP_VALUE_MOTIF_HINTS;
-  value->atom = display->atom__MOTIF_WM_HINTS;
-}
-
-static void
 reload_mwm_hints (MetaWindow    *window,
                   MetaPropValue *value,
                   gboolean       initial)
@@ -816,15 +726,6 @@
 }
 
 static void
-init_wm_class (MetaDisplay    *display,
-               Atom            property,
-               MetaPropValue  *value)
-{
-  value->type = META_PROP_VALUE_CLASS_HINT;
-  value->atom = XA_WM_CLASS;
-}
-
-static void
 reload_wm_class (MetaWindow    *window,
                  MetaPropValue *value,
                  gboolean       initial)
@@ -853,15 +754,6 @@
 }
 
 static void
-init_net_wm_desktop (MetaDisplay   *display,
-                     Atom           property,
-                     MetaPropValue *value)
-{
-  value->type = META_PROP_VALUE_CARDINAL;
-  value->atom = display->atom__NET_WM_DESKTOP;
-}
-
-static void
 reload_net_wm_desktop (MetaWindow    *window,
                        MetaPropValue *value,
                        gboolean       initial)
@@ -877,15 +769,6 @@
 }
 
 static void
-init_net_startup_id (MetaDisplay   *display,
-                     Atom           property,
-                     MetaPropValue *value)
-{
-  value->type = META_PROP_VALUE_UTF8;
-  value->atom = display->atom__NET_STARTUP_ID;
-}
-
-static void
 reload_net_startup_id (MetaWindow    *window,
                        MetaPropValue *value,
                        gboolean       initial)
@@ -924,15 +807,6 @@
 }
 
 static void
-init_update_counter (MetaDisplay   *display,
-                     Atom           property,
-                     MetaPropValue *value)
-{
-  value->type = META_PROP_VALUE_SYNC_COUNTER;
-  value->atom = display->atom__NET_WM_SYNC_REQUEST_COUNTER;
-}
-
-static void
 reload_update_counter (MetaWindow    *window,
                        MetaPropValue *value,
                        gboolean       initial)
@@ -949,17 +823,6 @@
     }
 }
 
-
-static void
-init_normal_hints (MetaDisplay   *display,
-                   Atom           property,
-                   MetaPropValue *value)
-{
-  value->type = META_PROP_VALUE_SIZE_HINTS;
-  value->atom = XA_WM_NORMAL_HINTS;
-}
-
-
 #define FLAG_TOGGLED_ON(old,new,flag) \
  (((old)->flags & (flag)) == 0 &&     \
   ((new)->flags & (flag)) != 0)
@@ -1386,16 +1249,6 @@
     }
 }
 
-
-static void
-init_wm_protocols (MetaDisplay   *display,
-                   Atom           property,
-                   MetaPropValue *value)
-{
-  value->type = META_PROP_VALUE_ATOM_LIST;
-  value->atom = display->atom_WM_PROTOCOLS;
-}
-
 static void
 reload_wm_protocols (MetaWindow    *window,
                      MetaPropValue *value,
@@ -1431,15 +1284,6 @@
 }
 
 static void
-init_wm_hints (MetaDisplay   *display,
-               Atom           property,
-               MetaPropValue *value)
-{
-  value->type = META_PROP_VALUE_WM_HINTS;
-  value->atom = XA_WM_HINTS;
-}
-
-static void
 reload_wm_hints (MetaWindow    *window,
                  MetaPropValue *value,
                  gboolean       initial)
@@ -1497,15 +1341,6 @@
 }
 
 static void
-init_transient_for (MetaDisplay   *display,
-                    Atom           property,
-                    MetaPropValue *value)
-{
-  value->type = META_PROP_VALUE_WINDOW;
-  value->atom = XA_WM_TRANSIENT_FOR;
-}
-
-static void
 reload_transient_for (MetaWindow    *window,
                       MetaPropValue *value,
                       gboolean       initial)
@@ -1554,173 +1389,83 @@
     meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
 }
 
-#define N_HOOKS 28
-
+/**
+ * Initialises the property hooks system.  Each row in the table named "hooks"
+ * represents an action to take when a property is found on a newly-created
+ * window, or when a property changes its value.
+ *
+ * The first column shows which atom the row concerns.
+ * The second gives the type of the property data.  The property will be
+ * queried for its new value, unless the type is given as
+ * META_PROP_VALUE_INVALID, in which case nothing will be queried.
+ * The third column gives the name of a callback which gets called with the
+ * new value.  (If the new value was not retrieved because the second column
+ * was META_PROP_VALUE_INVALID, the callback still gets called anyway.)
+ * This value may be NULL, in which case no callback will be called.
+ */
 void
 meta_display_init_window_prop_hooks (MetaDisplay *display)
 {
-  int i;
-  MetaWindowPropHooks *hooks;
-  
-  g_assert (display->prop_hooks == NULL);
+  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 },
+    { 0 },
+  };
 
-  display->prop_hooks = g_new0 (MetaWindowPropHooks, N_HOOKS); 
-  hooks = display->prop_hooks;
-  
-  i = 0;
+  MetaWindowPropHooks *table = g_memdup (hooks, sizeof (hooks)),
+    *cursor = table;
+
+  g_assert (display->prop_hooks == NULL);
 
-  hooks[i].property = display->atom_WM_STATE;
-  hooks[i].init_func = NULL;
-  hooks[i].reload_func = NULL;
-  ++i;
-
-  hooks[i].property = display->atom_WM_CLIENT_MACHINE;
-  hooks[i].init_func = init_wm_client_machine;
-  hooks[i].reload_func = reload_wm_client_machine;
-  ++i;
-
-  hooks[i].property = display->atom__NET_WM_PID;
-  hooks[i].init_func = init_net_wm_pid;
-  hooks[i].reload_func = reload_net_wm_pid;
-  ++i;
-
-  hooks[i].property = display->atom__NET_WM_USER_TIME;
-  hooks[i].init_func = init_net_wm_user_time;
-  hooks[i].reload_func = reload_net_wm_user_time;
-  ++i;
-
-  hooks[i].property = display->atom__NET_WM_NAME;
-  hooks[i].init_func = init_net_wm_name;
-  hooks[i].reload_func = reload_net_wm_name;
-  ++i;
-
-  hooks[i].property = XA_WM_NAME;
-  hooks[i].init_func = init_wm_name;
-  hooks[i].reload_func = reload_wm_name;
-  ++i;
-
-  hooks[i].property = display->atom__NET_WM_ICON;
-  hooks[i].init_func = NULL;
-  hooks[i].reload_func = reload_net_wm_icon;
-  ++i;
-
-  hooks[i].property = display->atom__KWM_WIN_ICON;
-  hooks[i].init_func = NULL;
-  hooks[i].reload_func = reload_kwm_win_icon;
-  ++i;
-
-  hooks[i].property = display->atom__NET_WM_ICON_NAME;
-  hooks[i].init_func = init_net_wm_icon_name;
-  hooks[i].reload_func = reload_net_wm_icon_name;
-  ++i;
-
-  hooks[i].property = XA_WM_ICON_NAME;
-  hooks[i].init_func = init_wm_icon_name;
-  hooks[i].reload_func = reload_wm_icon_name;
-  ++i;
-
-  hooks[i].property = display->atom__NET_WM_STATE;
-  hooks[i].init_func = init_net_wm_state;
-  hooks[i].reload_func = reload_net_wm_state;
-  ++i;
-  
-  hooks[i].property = display->atom__MOTIF_WM_HINTS;
-  hooks[i].init_func = init_mwm_hints;
-  hooks[i].reload_func = reload_mwm_hints;
-  ++i;
-
-  hooks[i].property = display->atom__NET_WM_ICON_GEOMETRY;
-  hooks[i].init_func = NULL;
-  hooks[i].reload_func = NULL;
-  ++i;
-
-  hooks[i].property = XA_WM_CLASS;
-  hooks[i].init_func = init_wm_class;
-  hooks[i].reload_func = reload_wm_class;
-  ++i;
-
-  hooks[i].property = display->atom_WM_CLIENT_LEADER;
-  hooks[i].init_func = NULL;
-  hooks[i].reload_func = complain_about_broken_client;
-  ++i;
-
-  hooks[i].property = display->atom_SM_CLIENT_ID;
-  hooks[i].init_func = NULL;
-  hooks[i].reload_func = complain_about_broken_client;
-  ++i;
-
-  hooks[i].property = display->atom_WM_WINDOW_ROLE;
-  hooks[i].init_func = NULL;
-  hooks[i].reload_func = reload_wm_window_role;
-  ++i;
-
-  hooks[i].property = display->atom__NET_WM_WINDOW_TYPE;
-  hooks[i].init_func = NULL;
-  hooks[i].reload_func = reload_net_wm_window_type;
-  ++i;
-
-  hooks[i].property = display->atom__NET_WM_DESKTOP;
-  hooks[i].init_func = init_net_wm_desktop;
-  hooks[i].reload_func = reload_net_wm_desktop;
-  ++i;
-
-  hooks[i].property = display->atom__NET_WM_STRUT;
-  hooks[i].init_func = NULL;
-  hooks[i].reload_func = reload_struts;
-  ++i;
-
-  hooks[i].property = display->atom__NET_WM_STRUT_PARTIAL;
-  hooks[i].init_func = NULL;
-  hooks[i].reload_func = reload_struts;
-  ++i;
-
-  hooks[i].property = display->atom__NET_STARTUP_ID;
-  hooks[i].init_func = init_net_startup_id;
-  hooks[i].reload_func = reload_net_startup_id;
-  ++i;
-
-  hooks[i].property = display->atom__NET_WM_SYNC_REQUEST_COUNTER;
-  hooks[i].init_func = init_update_counter;
-  hooks[i].reload_func = reload_update_counter;
-  ++i;
-
-  hooks[i].property = XA_WM_NORMAL_HINTS;
-  hooks[i].init_func = init_normal_hints;
-  hooks[i].reload_func = reload_normal_hints;
-  ++i;
-
-  hooks[i].property = display->atom_WM_PROTOCOLS;
-  hooks[i].init_func = init_wm_protocols;
-  hooks[i].reload_func = reload_wm_protocols;
-  ++i;
-
-  hooks[i].property = XA_WM_HINTS;
-  hooks[i].init_func = init_wm_hints;
-  hooks[i].reload_func = reload_wm_hints;
-  ++i;
-  
-  hooks[i].property = XA_WM_TRANSIENT_FOR;
-  hooks[i].init_func = init_transient_for;
-  hooks[i].reload_func = reload_transient_for;
-  ++i;
-
-  hooks[i].property = display->atom__NET_WM_USER_TIME_WINDOW;
-  hooks[i].init_func = init_net_wm_user_time_window;
-  hooks[i].reload_func = reload_net_wm_user_time_window;
-  ++i;
+  display->prop_hooks_table = (gpointer) table;
+  display->prop_hooks = g_hash_table_new (NULL, NULL);
 
-  if (i != N_HOOKS)
+  while (cursor->property)
     {
-      g_error ("Initialized %d hooks should have been %d\n", i, N_HOOKS);
+      /* 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)
+       */
+      g_hash_table_insert (display->prop_hooks,
+                           GINT_TO_POINTER (cursor->property),
+                           cursor);
+      cursor++;
     }
 }
 
 void
 meta_display_free_window_prop_hooks (MetaDisplay *display)
 {
-  g_assert (display->prop_hooks != NULL);
-  
-  g_free (display->prop_hooks);
+  g_hash_table_unref (display->prop_hooks);
+  display->prop_hooks_table = NULL;
+
+  g_free (display->prop_hooks_table);
   display->prop_hooks = NULL;
 }
 
@@ -1728,20 +1473,6 @@
 find_hooks (MetaDisplay *display,
             Atom         property)
 {
-  int i;
-
-  /* FIXME we could sort the array and do binary search or
-   * something
-   */
-  
-  i = 0;
-  while (i < N_HOOKS)
-    {
-      if (display->prop_hooks[i].property == property)
-        return &display->prop_hooks[i];
-      
-      ++i;
-    }
-
-  return NULL;
+  return g_hash_table_lookup (display->prop_hooks,
+                              GINT_TO_POINTER (property));
 }



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