2009-02-10 Mark Doffman <mark.doffman@codethink.co.uk>
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / accessible-register.c
index 8b8e34a..f92c078 100644 (file)
 #include "bridge.h"
 #include "accessible-register.h"
 
-#define ATK_BRIDGE_OBJECT_PATH_PREFIX "/org/freedesktop/atspi/accessible"
-#define ATK_BRIDGE_OBJECT_REFERENCE_TEMPLATE ATK_BRIDGE_OBJECT_PATH_PREFIX "/%d"
-#define ATK_BRIDGE_PATH_PREFIX_LENGTH 33
-
 /*
  * This module is responsible for keeping track of all the AtkObjects in
  * the application, so that they can be accessed remotely and placed in
@@ -39,7 +35,7 @@
  *
  * To access an AtkObject remotely we need to provide a D-Bus object 
  * path for it. The D-Bus object paths used have a standard prefix
- * (ATK_BRIDGE_OBJECT_PATH_PREFIX). Appended to this prefix is a string
+ * (SPI_ATK_OBJECT_PATH_PREFIX). Appended to this prefix is a string
  * representation of an integer reference. So to access an AtkObject 
  * remotely we keep a Hashtable that maps the given reference to 
  * the AtkObject pointer. An object in this hash table is said to be 'registered'.
 /*
  * FIXME
  *
- * While traversing the ATK tree we may modify it unintentionally.
- * This is either a bug in the Gail implementation or this module.
- * If a change is caused that recurses, via a signal into this module
- * we should catch it.
+ * This code seems very brittle.
+ * I would prefer changes to be made to
+ * gail and the ATK interface so that all Accessible
+ * objects are registered with an exporting module.
  *
- * Things could also be changed that do not cause signal emission,
- * but do cause a failure. Not sure what these would be.
+ * This is the same system as Qt has with the QAccessibleBridge
+ * and QAccessibleBridgePlugin. It entails some rather
+ * large structural changes to ATK though:
  *
- * The other option is that there are threads that modify the GUI.
- * This IS A BUG IN THE PROGRAM. But it may happen. If seeing very 
- * odd bugs change this to take the GDK lock. Just to make sure.
+ * Removing infinite spaces (Child access no longer references child).
+ * Removing lazy creation of accessible objects.
  */
 
+#define SPI_ATK_OBJECT_PATH_PREFIX  "/org/freedesktop/atspi/accessible"
+#define SPI_ATK_OBJECT_PATH_DESKTOP "/root"
+
+#define SPI_ATK_PATH_PREFIX_LENGTH 33
+#define SPI_ATK_OBJECT_REFERENCE_TEMPLATE SPI_ATK_OBJECT_PATH_PREFIX "/%d"
+
+
 static GHashTable *ref2ptr = NULL; /* Used for converting a D-Bus path (Reference) to the object pointer */
 
 static guint counter = 1;
@@ -117,6 +120,7 @@ assign_reference(void)
   /* Reference of 0 not allowed as used as direct key in hash table */
   if (counter == 0)
     counter++;
+  return counter;
 }
 
 /*
@@ -134,7 +138,7 @@ object_to_ref (AtkObject *accessible)
 static gchar *
 ref_to_path (guint ref)
 {
-  return g_strdup_printf(ATK_BRIDGE_OBJECT_REFERENCE_TEMPLATE, ref);
+  return g_strdup_printf(SPI_ATK_OBJECT_REFERENCE_TEMPLATE, ref);
 }
 
 /*---------------------------------------------------------------------------*/
@@ -176,6 +180,7 @@ register_accessible (AtkObject *accessible)
 
 /*---------------------------------------------------------------------------*/
 
+#ifdef SPI_ATK_DEBUG
 /*
  * This function checks that the ref-count of an accessible
  * is greater than 1.
@@ -199,6 +204,7 @@ non_owned_accessible (AtkObject *accessible)
        return FALSE;
      }
 }
+#endif /* SPI_ATK_DEBUG */
 
 /*---------------------------------------------------------------------------*/
 
@@ -215,7 +221,9 @@ has_manages_descendants (AtkObject *accessible)
    state = atk_object_ref_state_set (accessible);
    if (atk_state_set_contains_state (state, ATK_STATE_MANAGES_DESCENDANTS))
      {
+#ifdef SPI_ATK_DEBUG
        g_warning ("AT-SPI: Object with 'Manages descendants' states not currently handled by AT-SPI");
+#endif
        result = TRUE;
      }
    g_object_unref (state);
@@ -269,8 +277,9 @@ register_subtree (AtkObject *accessible)
         {
           tmp = atk_object_ref_accessible_child (current, i);
 
-          /* TODO Add debug wrapper */
+#ifdef SPI_ATK_DEBUG
           non_owned_accessible (tmp);
+#endif
 
           if (object_to_ref (tmp))
             {
@@ -356,12 +365,12 @@ atk_dbus_path_to_object (const char *path)
 
   g_assert (path);
 
-  if (strncmp(path, ATK_BRIDGE_OBJECT_PATH_PREFIX, ATK_BRIDGE_PATH_PREFIX_LENGTH) != 0) 
+  if (strncmp(path, SPI_ATK_OBJECT_PATH_PREFIX, SPI_ATK_PATH_PREFIX_LENGTH) != 0)
     return NULL;
 
-  path += ATK_BRIDGE_PATH_PREFIX_LENGTH; /* Skip over the prefix */
+  path += SPI_ATK_PATH_PREFIX_LENGTH; /* Skip over the prefix */
 
-  if (path[0] == '\0')
+  if (!g_strcmp0 (SPI_ATK_OBJECT_PATH_DESKTOP, path))
      return atk_get_root();
   if (path[0] != '/')
      return NULL;
@@ -390,6 +399,12 @@ atk_dbus_object_to_path (AtkObject *accessible)
       return ref_to_path (ref);
 }
 
+gchar *
+atk_dbus_desktop_object_path ()
+{
+  return g_strdup (SPI_ATK_OBJECT_PATH_PREFIX SPI_ATK_OBJECT_PATH_DESKTOP);
+}
+
 /*---------------------------------------------------------------------------*/
 
 /*
@@ -421,9 +436,10 @@ tree_update_listener (GSignalInvocationHint *signal_hint,
 
   if (object_to_ref (accessible))
     {
-      /* TODO Add debug wrapper */
+#ifdef SPI_ATK_DEBUG
       if (recursion_check_and_set ())
           g_warning ("AT-SPI: Recursive use of registration module");
+#endif
 
       values = (AtkPropertyValues*) g_value_get_pointer (&param_values[1]);
       pname = values[0].property_name;
@@ -468,9 +484,10 @@ tree_update_children_listener (GSignalInvocationHint *signal_hint,
 
   if (object_to_ref (accessible))
     {
-      /* TODO Add debug wrapper */
+#ifdef SPI_ATK_DEBUG
       if (recursion_check_and_set ())
           g_warning ("AT-SPI: Recursive use of registration module");
+#endif
 
       if (signal_hint->detail)
           detail = g_quark_to_string (signal_hint->detail);
@@ -484,8 +501,9 @@ tree_update_children_listener (GSignalInvocationHint *signal_hint,
           if (!ATK_IS_OBJECT (child))
             {
               child = atk_object_ref_accessible_child (accessible, index);
-              /* TODO Add debug wrapper */
+#ifdef SPI_ATK_DEBUG
               non_owned_accessible (child);
+#endif
             }
           register_subtree (child);
         }
@@ -510,8 +528,10 @@ atk_dbus_initialize (AtkObject *root)
   if (!ref2ptr)
     ref2ptr = g_hash_table_new(g_direct_hash, g_direct_equal);
 
+#ifdef SPI_ATK_DEBUG
   if (g_thread_supported ())
       g_message ("AT-SPI: Threads enabled");
+#endif
 
   register_subtree (root);