Don't translate g_warning messages
[platform/upstream/at-spi2-core.git] / atspi / atspi-accessible.c
index 1c441e1..dfeed59 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Copyright 2001, 2002 Sun Microsystems Inc.,
  * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2010, 2011 Novell, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  */
 
 #include "atspi-private.h"
+#include <string.h>
 
-G_DEFINE_TYPE (AtspiAccessible, atspi_accessible, G_TYPE_OBJECT)
+static void
+atspi_action_interface_init (AtspiAction *action)
+{
+}
+
+static void
+atspi_collection_interface_init (AtspiCollection *component)
+{
+}
+
+static void
+atspi_component_interface_init (AtspiComponent *component)
+{
+}
+
+static void
+atspi_document_interface_init (AtspiDocument *document)
+{
+}
+
+static void
+atspi_editable_text_interface_init (AtspiEditableText *editable_text)
+{
+}
+
+static void
+atspi_hypertext_interface_init (AtspiHypertext *hypertext)
+{
+}
+
+static void
+atspi_image_interface_init (AtspiImage *image)
+{
+}
+
+static void
+atspi_selection_interface_init (AtspiSelection *selection)
+{
+}
+
+static void
+atspi_table_interface_init (AtspiTable *table)
+{
+}
+
+static void
+atspi_text_interface_init (AtspiText *text)
+{
+}
+
+static void
+atspi_value_interface_init (AtspiValue *value)
+{
+}
+
+G_DEFINE_TYPE_WITH_CODE (AtspiAccessible, atspi_accessible, ATSPI_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (ATSPI_TYPE_ACTION, atspi_action_interface_init)
+                         G_IMPLEMENT_INTERFACE (ATSPI_TYPE_COLLECTION, atspi_collection_interface_init)
+                         G_IMPLEMENT_INTERFACE (ATSPI_TYPE_COMPONENT, atspi_component_interface_init)
+                         G_IMPLEMENT_INTERFACE (ATSPI_TYPE_DOCUMENT, atspi_document_interface_init)
+                         G_IMPLEMENT_INTERFACE (ATSPI_TYPE_EDITABLE_TEXT, atspi_editable_text_interface_init)
+                         G_IMPLEMENT_INTERFACE (ATSPI_TYPE_HYPERTEXT, atspi_hypertext_interface_init)
+                         G_IMPLEMENT_INTERFACE (ATSPI_TYPE_IMAGE, atspi_image_interface_init)
+                         G_IMPLEMENT_INTERFACE (ATSPI_TYPE_SELECTION, atspi_selection_interface_init)
+                         G_IMPLEMENT_INTERFACE (ATSPI_TYPE_TABLE, atspi_table_interface_init)
+                         G_IMPLEMENT_INTERFACE (ATSPI_TYPE_TEXT, atspi_text_interface_init)
+                         G_IMPLEMENT_INTERFACE (ATSPI_TYPE_VALUE, atspi_value_interface_init))
+
+#ifdef DEBUG_REF_COUNTS
+static gint accessible_count = 0;
+#endif
 
 static void
 atspi_accessible_init (AtspiAccessible *accessible)
 {
+#ifdef DEBUG_REF_COUNTS
+  accessible_count++;
+  printf("at-spi: init: %d objects\n", accessible_count);
+#endif
 }
 
 static void
-atspi_accessible_finalize (GObject *obj)
+atspi_accessible_dispose (GObject *object)
 {
-  AtspiAccessible *accessible = ATSPI_ACCESSIBLE (obj);
+  AtspiAccessible *accessible = ATSPI_ACCESSIBLE (object);
+  AtspiEvent e;
+  AtspiAccessible *parent;
 
-  if (accessible->app)
-    g_object_unref (accessible->app);
+  /* TODO: Only fire if object not already marked defunct */
+  memset (&e, 0, sizeof (e));
+  e.type = "object:state-change:defunct";
+  e.source = accessible;
+  e.detail1 = 1;
+  e.detail2 = 0;
+  _atspi_send_event (&e);
+
+  if (accessible->states)
+  {
+    g_object_unref (accessible->states);
+    accessible->states = NULL;
+  }
+
+  parent = accessible->accessible_parent;
+  if (parent && parent->children)
+  {
+    GList*ls = g_list_find (parent->children, accessible);
+    if(ls)
+    {
+      gboolean replace = (ls == parent->children);
+      ls = g_list_remove (ls, accessible);
+      if (replace)
+        parent->children = ls;
+      g_object_unref (object);
+    }
+  }
+
+  if (parent)
+  {
+    g_object_unref (parent);
+    accessible->accessible_parent = NULL;
+  }
 
-  g_free (accessible->path);
+  G_OBJECT_CLASS (atspi_accessible_parent_class) ->dispose (object);
+}
+
+static void
+atspi_accessible_finalize (GObject *object)
+{
+  AtspiAccessible *accessible = ATSPI_ACCESSIBLE (object);
+
+    g_free (accessible->description);
+    g_free (accessible->name);
+
+#ifdef DEBUG_REF_COUNTS
+  accessible_count--;
+  printf("at-spi: finalize: %d objects\n", accessible_count);
+#endif
+
+  G_OBJECT_CLASS (atspi_accessible_parent_class)
+    ->finalize (object);
 }
 
 static void
@@ -46,8 +172,10 @@ atspi_accessible_class_init (AtspiAccessibleClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
+  object_class->dispose = atspi_accessible_dispose;
   object_class->finalize = atspi_accessible_finalize;
 }
+
 /* TODO: Generate following from spec? */
 static const char *role_names [] =
 {
@@ -178,12 +306,13 @@ atspi_role_get_name (AtspiRole role)
 gchar *
 atspi_accessible_get_name (AtspiAccessible *obj, GError **error)
 {
-  g_return_val_if_fail (obj != NULL, NULL);
-  if (!obj->cached_properties & ATSPI_CACHE_NAME)
+  g_return_val_if_fail (obj != NULL, g_strdup (""));
+  if (!(obj->cached_properties & ATSPI_CACHE_NAME))
   {
-    if (!_atspi_dbus_call (obj, atspi_interface_accessible, "GetName", NULL, "=>s", &obj->name))
-      return NULL;
-    obj->cached_properties |= ATSPI_CACHE_NAME;
+    if (!_atspi_dbus_get_property (obj, atspi_interface_accessible, "Name", error,
+                                   "s", &obj->name))
+      return g_strdup ("");
+    _atspi_accessible_add_cache (obj, ATSPI_CACHE_NAME);
   }
   return g_strdup (obj->name);
 }
@@ -200,17 +329,21 @@ atspi_accessible_get_name (AtspiAccessible *obj, GError **error)
 gchar *
 atspi_accessible_get_description (AtspiAccessible *obj, GError **error)
 {
-  g_return_val_if_fail (obj != NULL, NULL);
+  g_return_val_if_fail (obj != NULL, g_strdup (""));
 
-  if (!obj->cached_properties & ATSPI_CACHE_DESCRIPTION)
+  if (!(obj->cached_properties & ATSPI_CACHE_DESCRIPTION))
   {
-    if (!_atspi_dbus_call (obj, atspi_interface_accessible, "GetDescription", NULL, "=>s", &obj->description))
-      return NULL;
-    obj->cached_properties |= ATSPI_CACHE_DESCRIPTION;
+    if (!_atspi_dbus_get_property (obj, atspi_interface_accessible,
+                                   "Description", error, "s",
+                                   &obj->description))
+      return g_strdup ("");
+    _atspi_accessible_add_cache (obj, ATSPI_CACHE_DESCRIPTION);
   }
   return g_strdup (obj->description);
 }
 
+const char *str_parent = "Parent";
+
 /**
  * atspi_accessible_get_parent:
  * @obj: a pointer to the #AtspiAccessible object to query.
@@ -227,6 +360,34 @@ atspi_accessible_get_parent (AtspiAccessible *obj, GError **error)
 {
   g_return_val_if_fail (obj != NULL, NULL);
 
+  if (obj->parent.app && !(obj->cached_properties & ATSPI_CACHE_PARENT))
+  {
+    DBusMessage *message, *reply;
+    DBusMessageIter iter, iter_variant;
+    message = dbus_message_new_method_call (obj->parent.app->bus_name,
+                                            obj->parent.path,
+                                            DBUS_INTERFACE_PROPERTIES, "Get");
+    if (!message)
+      return NULL;
+    dbus_message_append_args (message, DBUS_TYPE_STRING, &atspi_interface_accessible,
+                               DBUS_TYPE_STRING, &str_parent,
+                              DBUS_TYPE_INVALID);
+    reply = _atspi_dbus_send_with_reply_and_block (message, error);
+    if (!reply)
+      return NULL;
+    if (strcmp (dbus_message_get_signature (reply), "v") != 0)
+    {
+      dbus_message_unref (reply);
+      return NULL;
+    }
+    dbus_message_iter_init (reply, &iter);
+    dbus_message_iter_recurse (&iter, &iter_variant);
+    obj->accessible_parent = _atspi_dbus_return_accessible_from_iter (&iter_variant);
+    dbus_message_unref (reply);
+    _atspi_accessible_add_cache (obj, ATSPI_CACHE_PARENT);
+  }
+  if (!obj->accessible_parent)
+    return NULL;
   return g_object_ref (obj->accessible_parent);
 }
 
@@ -241,11 +402,19 @@ atspi_accessible_get_parent (AtspiAccessible *obj, GError **error)
  *
  **/
 gint
-atspi_accessible_get_child_count (AtspiAccessible *obj, GError *error)
+atspi_accessible_get_child_count (AtspiAccessible *obj, GError **error)
 {
   g_return_val_if_fail (obj != NULL, -1);
 
-  /* TODO: MANAGES_DESCENDANTS */
+  if (!(obj->cached_properties & ATSPI_CACHE_CHILDREN))
+  {
+    dbus_int32_t ret;
+    if (!_atspi_dbus_get_property (obj, atspi_interface_accessible,
+                                   "ChildCount", error, "i", &ret))
+      return -1;
+    return ret;
+  }
+
   return g_list_length (obj->children);
 }
 
@@ -268,7 +437,15 @@ atspi_accessible_get_child_at_index (AtspiAccessible *obj,
 
   g_return_val_if_fail (obj != NULL, NULL);
 
-  /* TODO: ManagesDescendants */
+  if (!(obj->cached_properties & ATSPI_CACHE_CHILDREN))
+  {
+    DBusMessage *reply;
+    reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible,
+                                     "GetChildAtIndex", error, "i",
+                                     child_index);
+    return _atspi_dbus_return_accessible_from_message (reply);
+  }
+
   child = g_list_nth_data (obj->children, child_index);
   if (!child)
     return NULL;
@@ -289,10 +466,18 @@ gint
 atspi_accessible_get_index_in_parent (AtspiAccessible *obj, GError **error)
 {
   GList *l;
-  gint i;
+  gint i = 0;
 
   g_return_val_if_fail (obj != NULL, -1);
   if (!obj->accessible_parent) return -1;
+  if (!(obj->accessible_parent->cached_properties & ATSPI_CACHE_CHILDREN))
+  {
+    dbus_uint32_t ret = -1;
+    _atspi_dbus_call (obj, atspi_interface_accessible,
+                      "GetIndexInParent", NULL, "=>u", &ret);
+    return ret;
+  }
+
   l = obj->accessible_parent->children;
   while (l)
   {
@@ -316,22 +501,38 @@ typedef struct
  * Get the set of #AtspiRelation objects which describe this #AtspiAccessible object's
  *       relationships with other #AtspiAccessible objects.
  *
- * Returns: an array of #AtspiAccessibleRelation pointers. or NULL on exception
- * TODO:: Annotate array type
+ * Returns: (element-type AtspiAccessible*) (transfer full): an array of
+ *          #AtspiAccessibleRelation pointers. or NULL on exception
  **/
 GArray *
 atspi_accessible_get_relation_set (AtspiAccessible *obj, GError **error)
 {
-  int i;
-  int n_relations;
-  GArray *relation_set;
+  DBusMessage *reply;
+  DBusMessageIter iter, iter_array;
+  GArray *ret;
 
   g_return_val_if_fail (obj != NULL, NULL);
 
-  if (!_atspi_dbus_call (obj, atspi_interface_accessible, "GetRelationSet", error, "=>a(uao)", &relation_set))
+  reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetRelationSet", error, "");
+  if (!reply)
     return NULL;
+  _ATSPI_DBUS_CHECK_SIG (reply, "a(ua(so))", error, NULL);
 
-  return relation_set;
+  ret = g_array_new (TRUE, TRUE, sizeof (AtspiRelation *));
+  dbus_message_iter_init (reply, &iter);
+  dbus_message_iter_recurse (&iter, &iter_array);
+  while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+  {
+    GArray *new_array;
+    AtspiRelation *relation;
+    relation = _atspi_relation_new_from_iter (&iter_array);
+    new_array = g_array_append_val (ret, relation);
+    if (new_array)
+      ret = new_array;
+    dbus_message_iter_next (&iter_array);
+  }
+  dbus_message_unref (reply);
+  return ret;
 }
 
 /**
@@ -349,13 +550,14 @@ atspi_accessible_get_role (AtspiAccessible *obj, GError **error)
 {
   g_return_val_if_fail (obj != NULL, ATSPI_ROLE_INVALID);
 
-  if (!obj->cached_properties & ATSPI_CACHE_ROLE)
+  if (!(obj->cached_properties & ATSPI_CACHE_ROLE))
   {
     dbus_uint32_t role;
-    if (_atspi_dbus_call (obj, atspi_interface_accessible, "GetRole", NULL, "=>u", &role))
+    /* TODO: Make this a property */
+    if (_atspi_dbus_call (obj, atspi_interface_accessible, "GetRole", error, "=>u", &role))
     {
-      obj->cached_properties |= ATSPI_CACHE_ROLE;
       obj->role = role;
+    _atspi_accessible_add_cache (obj, ATSPI_CACHE_ROLE);
     }
   }
   return obj->role;
@@ -377,10 +579,13 @@ atspi_accessible_get_role_name (AtspiAccessible *obj, GError **error)
 {
   char *retval = NULL;
 
-  g_return_val_if_fail (obj != NULL, g_strdup ("invalid"));
+  g_return_val_if_fail (obj != NULL, NULL);
 
   _atspi_dbus_call (obj, atspi_interface_accessible, "GetRoleName", error, "=>s", &retval);
 
+  if (!retval)
+    retval = g_strdup ("");
+
   return retval;
 }
 
@@ -400,13 +605,24 @@ atspi_accessible_get_localized_role_name (AtspiAccessible *obj, GError **error)
 {
   char *retval = NULL;
 
-  g_return_val_if_fail (obj != NULL, g_strdup ("invalid"));
+  g_return_val_if_fail (obj != NULL, NULL);
 
   _atspi_dbus_call (obj, atspi_interface_accessible, "GetLocalizedRoleName", error, "=>s", &retval);
 
+  if (!retval)
+    return g_strdup ("");
+
   return retval;
 }
 
+static AtspiStateSet *
+defunct_set ()
+{
+  AtspiStateSet *set = atspi_state_set_new (NULL);
+  atspi_state_set_add (set, ATSPI_STATE_DEFUNCT);
+  return set;
+}
+
 /**
  * atspi_accessible_get_state_set:
  * @obj: a pointer to the #AtspiAccessible object on which to operate.
@@ -419,7 +635,24 @@ atspi_accessible_get_localized_role_name (AtspiAccessible *obj, GError **error)
 AtspiStateSet *
 atspi_accessible_get_state_set (AtspiAccessible *obj)
 {
-  return obj->states;
+  if (!obj->parent.app || !obj->parent.app->bus)
+    return defunct_set ();
+
+
+  if (!(obj->cached_properties & ATSPI_CACHE_STATES))
+  {
+    DBusMessage *reply;
+    DBusMessageIter iter;
+    reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible,
+                                      "GetState", NULL, "");
+    _ATSPI_DBUS_CHECK_SIG (reply, "au", NULL, defunct_set ());
+    dbus_message_iter_init (reply, &iter);
+    _atspi_dbus_set_state (obj, &iter);
+    dbus_message_unref (reply);
+    _atspi_accessible_add_cache (obj, ATSPI_CACHE_STATES);
+  }
+
+  return g_object_ref (obj->states);
 }
 
 /**
@@ -438,14 +671,11 @@ GHashTable *
 atspi_accessible_get_attributes (AtspiAccessible *obj, GError **error)
 {
   DBusMessage *message;
-  GHashTable *ret;
 
     g_return_val_if_fail (obj != NULL, NULL);
 
   message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetAttributes", error, "");
-  ret = _atspi_dbus_hash_from_message (message);
-  dbus_message_unref (message);
-  return ret;
+  return _atspi_dbus_return_hash_from_message (message);
 }
 
 /**
@@ -464,18 +694,15 @@ GArray *
 atspi_accessible_get_attributes_as_array (AtspiAccessible *obj, GError **error)
 {
   DBusMessage *message;
-  GArray *ret;
 
     g_return_val_if_fail (obj != NULL, NULL);
 
   message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetAttributes", error, "");
-  ret = _atspi_dbus_attribute_array_from_message (message);
-  dbus_message_unref (message);
-  return ret;
+  return _atspi_dbus_return_attribute_array_from_message (message);
 }
 
 /**
- * atspi_accessible_get_host_application:
+ * atspi_accessible_get_application:
  * @obj: The #AtspiAccessible being queried.
  *
  * Get the containing #AtspiApplication for an object.
@@ -484,16 +711,136 @@ atspi_accessible_get_attributes_as_array (AtspiAccessible *obj, GError **error)
  *          this object.
  */
 AtspiAccessible *
-atspi_accessible_get_host_application (AtspiAccessible *obj, GError **error)
+atspi_accessible_get_application (AtspiAccessible *obj, GError **error)
+{
+  AtspiAccessible *parent;
+
+  g_object_ref (obj);
+  for (;;)
+  {
+    parent = atspi_accessible_get_parent (obj, NULL);
+    if (!parent && obj->parent.app &&
+        atspi_accessible_get_role (obj, NULL) != ATSPI_ROLE_APPLICATION)
+    {
+      AtspiAccessible *root = g_object_ref (obj->parent.app->root);
+      if (root)
+      {
+        g_object_unref (obj);
+        if (atspi_accessible_get_role (root, NULL) == ATSPI_ROLE_DESKTOP_FRAME)
+        {
+          g_object_unref (root);
+          return NULL;
+        }
+        return root;
+      }
+    }
+    if (!parent || parent == obj ||
+        atspi_accessible_get_role (parent, NULL) == ATSPI_ROLE_DESKTOP_FRAME)
+    return obj;
+    g_object_unref (obj);
+    obj = parent;
+  }
+}
+
+/* Application-specific methods */
+
+/**
+ * atspi_accessible_get_toolkit_name:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Get the toolkit for a #AtspiAccessible object.
+ * Only works on application root objects.
+ *
+ * Returns: a UTF-8 string indicating the toolkit name for the #AtspiAccessible object.
+ * or NULL on exception
+ **/
+gchar *
+atspi_accessible_get_toolkit_name (AtspiAccessible *obj, GError **error)
+{
+  gchar *ret = NULL;
+
+  g_return_val_if_fail (obj != NULL, NULL);
+
+  if (!_atspi_dbus_get_property (obj, atspi_interface_application, "ToolkitName", error, "s", &ret))
+      return NULL;
+  return g_strdup (ret);
+}
+
+/**
+ * atspi_accessible_get_toolkit_version:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Get the toolkit version for a #AtspiAccessible object.
+ * Only works on application root objects.
+ *
+ * Returns: a UTF-8 string indicating the toolkit ersion for the #AtspiAccessible object.
+ * or NULL on exception
+ **/
+gchar *
+atspi_accessible_get_toolkit_version (AtspiAccessible *obj, GError **error)
+{
+  gchar *ret = NULL;
+
+  g_return_val_if_fail (obj != NULL, NULL);
+
+  if (!_atspi_dbus_get_property (obj, atspi_interface_application, "ToolkitVersion", error, "s", &ret))
+      return NULL;
+  return g_strdup (ret);
+}
+/**
+ * atspi_accessible_get_toolkit_version:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Get the application id for a #AtspiAccessible object.
+ * Only works on application root objects.
+ *
+ * Returns: a gint indicating the id for the #AtspiAccessible object.
+ * or -1 on exception
+ **/
+gint
+atspi_accessible_get_id (AtspiAccessible *obj, GError **error)
 {
-  while (obj->accessible_parent && atspi_accessible_get_role (obj->accessible_parent, NULL) != ATSPI_ROLE_DESKTOP_FRAME)
-    obj = obj->accessible_parent;
-  return g_object_ref (obj);
+  gint ret = -1;
+
+  g_return_val_if_fail (obj != NULL, -1);
+
+  if (!_atspi_dbus_get_property (obj, atspi_interface_application, "Id", error, "i", &ret))
+      return -1;
+  return ret;
 }
 
-#if 0  // TODO: interfaces */
+
 /* Interface query methods */
 
+static gboolean
+_atspi_accessible_is_a (AtspiAccessible *accessible,
+                     const char *interface_name)
+{
+  int n;
+
+  if (accessible == NULL)
+    {
+      return FALSE;
+    }
+
+  if (!(accessible->cached_properties & ATSPI_CACHE_INTERFACES))
+  {
+    DBusMessage *reply;
+    DBusMessageIter iter;
+    reply = _atspi_dbus_call_partial (accessible, atspi_interface_accessible,
+                                      "GetInterfaces", NULL, "");
+    _ATSPI_DBUS_CHECK_SIG (reply, "as", NULL, FALSE);
+    dbus_message_iter_init (reply, &iter);
+    _atspi_dbus_set_interfaces (accessible, &iter);
+    dbus_message_unref (reply);
+    _atspi_accessible_add_cache (accessible, ATSPI_CACHE_INTERFACES);
+  }
+
+  n = _atspi_get_iface_num (interface_name);
+  if (n == -1) return FALSE;
+  return (gboolean) ((accessible->interfaces & (1 << n))? TRUE: FALSE);
+}
+
 /**
  * atspi_accessible_is_action:
  * @obj: a pointer to the #AtspiAccessible instance to query.
@@ -536,13 +883,8 @@ atspi_accessible_is_application (AtspiAccessible *obj)
 gboolean
 atspi_accessible_is_collection (AtspiAccessible *obj)
 {
-#if 0
-     g_warning ("Collections not implemented");
      return _atspi_accessible_is_a (obj,
                              atspi_interface_collection);
-#else
-     return FALSE;
-#endif
 }
 
 /**
@@ -610,6 +952,22 @@ atspi_accessible_is_hypertext (AtspiAccessible *obj)
 }
 
 /**
+ * atspi_accessible_is_hyperlink:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements #AtspiHyperlink.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiHypertext interface,
+ *          #FALSE otherwise.
+ **/
+gboolean
+atspi_accessible_is_hyperlink (AtspiAccessible *obj)
+{
+  return _atspi_accessible_is_a (obj,
+                             atspi_interface_hyperlink);
+}
+
+/**
  * atspi_accessible_is_image:
  * @obj: a pointer to the #AtspiAccessible instance to query.
  *
@@ -712,35 +1070,19 @@ atspi_accessible_is_value (AtspiAccessible *obj)
 }
 
 /**
- * atspi_accessible_get_application:
- * @obj: a pointer to the #AtspiAccessible instance to query.
- *
- * Get the #AtspiApplication interface for an #AtspiAccessible.
- *
- * Returns: a pointer to an #AtspiApplication interface instance, or
- *          NULL if @obj does not implement #AtspiApplication.
- **/
-AtspiApplication *
-atspi_accessible_get_application (AtspiAccessible *accessible)
-{
-  return (_atspi_accessible_is_a (accessible, atspi_interface_application) ?
-          accessible : NULL);  
-}
-
-/**
  * atspi_accessible_get_action:
  * @obj: a pointer to the #AtspiAccessible instance to query.
  *
  * Get the #AtspiAction interface for an #AtspiAccessible.
  *
- * Returns: a pointer to an #AtspiAction interface instance, or
- *          NULL if @obj does not implement #AtspiAction.
+ * Returns: (transfer full): a pointer to an #AtspiAction interface
+ *          instance, or NULL if @obj does not implement #AtspiAction.
  **/
 AtspiAction *
 atspi_accessible_get_action (AtspiAccessible *accessible)
 {
   return (_atspi_accessible_is_a (accessible, atspi_interface_action) ?
-          accessible : NULL);  
+          g_object_ref (ATSPI_ACTION (accessible)) : NULL);  
 }
 
 /**
@@ -749,16 +1091,15 @@ atspi_accessible_get_action (AtspiAccessible *accessible)
  *
  * Get the #AtspiCollection interface for an #AtspiAccessible.
  *
- * Returns: a pointer to an #AtspiCollection interface instance, or
- *          NULL if @obj does not implement #AtspiCollection.
+ * Returns: (transfer full): a pointer to an #AtspiCollection interface
+ *          instance, or NULL if @obj does not implement #AtspiCollection.
  **/
 AtspiCollection *
 atspi_accessible_get_collection (AtspiAccessible *accessible)
 {
   return (_atspi_accessible_is_a (accessible, atspi_interface_collection) ?
-          accessible : NULL);  
+          g_object_ref (ATSPI_COLLECTION (accessible)) : NULL);  
 }
-#endif
 
 /**
  * atspi_accessible_get_component:
@@ -766,31 +1107,30 @@ atspi_accessible_get_collection (AtspiAccessible *accessible)
  *
  * Get the #AtspiComponent interface for an #AtspiAccessible.
  *
- * Returns: a pointer to an #AtspiComponent interface instance, or
- *          NULL if @obj does not implement #AtspiComponent.
+ * Returns: (transfer full): a pointer to an #AtspiComponent interface
+ *          instance, or NULL if @obj does not implement #AtspiComponent.
  **/
 AtspiComponent *
-atspi_accessible_get_component (AtspiAccessible *accessible)
+atspi_accessible_get_component (AtspiAccessible *obj)
 {
-  return (_atspi_accessible_is_a (accessible, atspi_interface_component) ?
-          ATSPI_COMPONENT (accessible) : NULL);  
+  return (_atspi_accessible_is_a (obj, atspi_interface_component) ?
+          g_object_ref (ATSPI_COMPONENT (obj)) : NULL);
 }
 
-#if 0
 /**
  * atspi_accessible_get_document:
  * @obj: a pointer to the #AtspiAccessible instance to query.
  *
  * Get the #AtspiDocument interface for an #AtspiAccessible.
  *
- * Returns: a pointer to an #AtspiDocument interface instance, or
- *          NULL if @obj does not implement #AtspiDocument.
+ * Returns: (transfer full): a pointer to an #AtspiDocument interface
+ *          instance, or NULL if @obj does not implement #AtspiDocument.
  **/
 AtspiDocument *
 atspi_accessible_get_document (AtspiAccessible *accessible)
 {
   return (_atspi_accessible_is_a (accessible, atspi_interface_document) ?
-          accessible : NULL);  
+          g_object_ref (ATSPI_DOCUMENT (accessible)) : NULL);  
 }
 
 /**
@@ -799,14 +1139,31 @@ atspi_accessible_get_document (AtspiAccessible *accessible)
  *
  * Get the #AtspiEditableText interface for an #AtspiAccessible.
  *
- * Returns: a pointer to an #AtspiEditableText interface instance, or
- *          NULL if @obj does not implement #AtspiEditableText.
+ * Returns: (transfer full): a pointer to an #AtspiEditableText interface
+ *          instance, or NULL if @obj does not implement #AtspiEditableText.
  **/
 AtspiEditableText *
 atspi_accessible_get_editable_text (AtspiAccessible *accessible)
 {
   return (_atspi_accessible_is_a (accessible, atspi_interface_editable_text) ?
-          accessible : NULL);  
+          g_object_ref (ATSPI_EDITABLE_TEXT (accessible)) : NULL);  
+}
+
+/**
+ * atspi_accessible_get_hyperlink:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Get the #AtspiHyperlink associated with the given #AtspiAccessible, if
+ * supported.
+ *
+ * Returns: (transfer full): the #AtspiHyperlink object associated with
+ *          the given #AtspiAccessible, or NULL if not supported.
+ **/
+AtspiHyperlink *
+atspi_accessible_get_hyperlink (AtspiAccessible *accessible)
+{
+  return (_atspi_accessible_is_a (accessible, atspi_interface_hyperlink) ?
+          atspi_hyperlink_new (accessible->parent.app, accessible->parent.path) : NULL);
 }
 
 /**
@@ -815,14 +1172,14 @@ atspi_accessible_get_editable_text (AtspiAccessible *accessible)
  *
  * Get the #AtspiHypertext interface for an #AtspiAccessible.
  *
- * Returns: a pointer to an #AtspiHypertext interface instance, or
- *          NULL if @obj does not implement #AtspiHypertext.
+ * Returns: (transfer full): a pointer to an #AtspiHypertext interface
+ *          instance, or NULL if @obj does not implement #AtspiHypertext.
  **/
 AtspiHypertext *
 atspi_accessible_get_hypertext (AtspiAccessible *accessible)
 {
   return (_atspi_accessible_is_a (accessible, atspi_interface_hypertext) ?
-          accessible : NULL);  
+          g_object_ref (ATSPI_HYPERTEXT (accessible)) : NULL);  
 }
 
 /**
@@ -831,14 +1188,14 @@ atspi_accessible_get_hypertext (AtspiAccessible *accessible)
  *
  * Get the #AtspiImage interface for an #AtspiAccessible.
  *
- * Returns: a pointer to an #AtspiImage interface instance, or
+ * Returns: (transfer full): a pointer to an #AtspiImage interface instance, or
  *          NULL if @obj does not implement #AtspiImage.
  **/
 AtspiImage *
 atspi_accessible_get_image (AtspiAccessible *accessible)
 {
   return (_atspi_accessible_is_a (accessible, atspi_interface_image) ?
-          accessible : NULL);  
+          g_object_ref (ATSPI_IMAGE (accessible)) : NULL);  
 }
 
 /**
@@ -847,24 +1204,25 @@ atspi_accessible_get_image (AtspiAccessible *accessible)
  *
  * Get the #AtspiSelection interface for an #AtspiAccessible.
  *
- * Returns: a pointer to an #AtspiSelection interface instance, or
- *          NULL if @obj does not implement #AtspiSelection.
+ * Returns: (transfer full): a pointer to an #AtspiSelection interface
+ *          instance, or NULL if @obj does not implement #AtspiSelection.
  **/
 AtspiSelection *
 atspi_accessible_get_selection (AtspiAccessible *accessible)
 {
   return (_atspi_accessible_is_a (accessible, atspi_interface_selection) ?
-          accessible : NULL);  
+          g_object_ref (ATSPI_SELECTION (accessible)) : NULL);  
 }
 
+#if 0
 /**
  * atspi_accessible_get_streamable_content:
  * @obj: a pointer to the #AtspiAccessible instance to query.
  *
  * Get the #AtspiStreamableContent interface for an #AtspiAccessible.
  *
- * Returns: a pointer to an #AtspiStreamableContent interface instance, or
- *          NULL if @obj does not implement #AtspiStreamableContent.
+ * Returns: (transfer full): a pointer to an #AtspiStreamableContent interface
+ *          instance, or NULL if @obj does not implement #AtspiStreamableContent.
  **/
 AtspiStreamableContent *
 atspi_accessible_get_streamable_content (AtspiAccessible *accessible)
@@ -872,6 +1230,7 @@ atspi_accessible_get_streamable_content (AtspiAccessible *accessible)
   return (_atspi_accessible_is_a (accessible, atspi_interface_streamable_content) ?
           accessible : NULL);  
 }
+#endif
 
 /**
  * atspi_accessible_get_table:
@@ -879,14 +1238,14 @@ atspi_accessible_get_streamable_content (AtspiAccessible *accessible)
  *
  * Get the #AtspiTable interface for an #AtspiAccessible.
  *
- * Returns: a pointer to an #AtspiTable interface instance, or
+ * Returns: (transfer full): a pointer to an #AtspiTable interface instance, or
  *          NULL if @obj does not implement #AtspiTable.
  **/
 AtspiTable *
-atspi_accessible_get_table (AtspiAccessible *accessible)
+atspi_accessible_get_table (AtspiAccessible *obj)
 {
-  return (_atspi_accessible_is_a (accessible, atspi_interface_table) ?
-          accessible : NULL);  
+  return (_atspi_accessible_is_a (obj, atspi_interface_table) ?
+          g_object_ref (ATSPI_TABLE (obj)) : NULL);  
 }
 
 /**
@@ -895,14 +1254,14 @@ atspi_accessible_get_table (AtspiAccessible *accessible)
  *
  * Get the #AtspiTable interface for an #AtspiAccessible.
  *
- * Returns: a pointer to an #AtspiTable interface instance, or
- *          NULL if @obj does not implement #AtspiTable.
+ * Returns: (transfer full): a pointer to an #AtspiText interface instance, or
+ *          NULL if @obj does not implement #AtspiText.
  **/
-AtspiTable *
-atspi_accessible_get_text (AtspiAccessible *accessible)
+AtspiText *
+atspi_accessible_get_text (AtspiAccessible *obj)
 {
-  return (_atspi_accessible_is_a (accessible, atspi_interface_text) ?
-          accessible : NULL);  
+  return (_atspi_accessible_is_a (obj, atspi_interface_text) ?
+          g_object_ref (ATSPI_TEXT (obj)) : NULL);
 }
 
 /**
@@ -911,376 +1270,129 @@ atspi_accessible_get_text (AtspiAccessible *accessible)
  *
  * Get the #AtspiTable interface for an #AtspiAccessible.
  *
- * Returns: a pointer to an #AtspiTable interface instance, or
- *          NULL if @obj does not implement #AtspiTable.
+ * Returns: (transfer full): a pointer to an #AtspiValue interface instance, or
+ *          NULL if @obj does not implement #AtspiValue.
  **/
-AtspiTable *
+AtspiValue *
 atspi_accessible_get_value (AtspiAccessible *accessible)
 {
   return (_atspi_accessible_is_a (accessible, atspi_interface_value) ?
-          accessible : NULL);  
+          g_object_ref (ATSPI_VALUE (accessible)) : NULL);  
 }
 
-static gboolean
-cspi_init_relation_type_table (AccessibleRelationType *relation_type_table)
-{
-  int i;
-  for (i = 0; i < Accessibility_RELATION_LAST_DEFINED; ++i)
-    {
-      relation_type_table [i] = SPI_RELATION_NULL;
-    }
-  relation_type_table [Accessibility_RELATION_NULL] = SPI_RELATION_NULL;
-  relation_type_table [Accessibility_RELATION_LABEL_FOR] = SPI_RELATION_LABEL_FOR;
-  relation_type_table [Accessibility_RELATION_LABELLED_BY] = SPI_RELATION_LABELED_BY;
-  relation_type_table [Accessibility_RELATION_CONTROLLER_FOR] = SPI_RELATION_CONTROLLER_FOR;
-  relation_type_table [Accessibility_RELATION_CONTROLLED_BY] = SPI_RELATION_CONTROLLED_BY;
-  relation_type_table [Accessibility_RELATION_MEMBER_OF] = SPI_RELATION_MEMBER_OF;
-  relation_type_table [Accessibility_RELATION_TOOLTIP_FOR] = SPI_RELATION_NULL;
-  relation_type_table [Accessibility_RELATION_NODE_CHILD_OF] = SPI_RELATION_NODE_CHILD_OF;
-  relation_type_table [Accessibility_RELATION_EXTENDED] = SPI_RELATION_EXTENDED;
-  relation_type_table [Accessibility_RELATION_FLOWS_TO] = SPI_RELATION_FLOWS_TO;
-  relation_type_table [Accessibility_RELATION_FLOWS_FROM] = SPI_RELATION_FLOWS_FROM;
-  relation_type_table [Accessibility_RELATION_SUBWINDOW_OF] = SPI_RELATION_SUBWINDOW_OF;
-  relation_type_table [Accessibility_RELATION_EMBEDS] = SPI_RELATION_EMBEDS;
-  relation_type_table [Accessibility_RELATION_EMBEDDED_BY] = SPI_RELATION_EMBEDDED_BY;
-  relation_type_table [Accessibility_RELATION_POPUP_FOR] = SPI_RELATION_POPUP_FOR;
-  relation_type_table [Accessibility_RELATION_PARENT_WINDOW_OF] = SPI_RELATION_PARENT_WINDOW_OF;
-  relation_type_table [Accessibility_RELATION_DESCRIBED_BY] = SPI_RELATION_DESCRIBED_BY;
-  relation_type_table [Accessibility_RELATION_DESCRIPTION_FOR] = SPI_RELATION_DESCRIPTION_FOR;
-  return TRUE;
-}
-
-static AccessibleRelationType
-cspi_relation_type_from_spi_relation_type (Accessibility_RelationType type)
-{
-  /* array is sized according to IDL RelationType because IDL RelationTypes are the index */   
-  static AccessibleRelationType cspi_relation_type_table [Accessibility_RELATION_LAST_DEFINED];
-  static gboolean is_initialized = FALSE;
-  AccessibleRelationType cspi_type;
-  if (!is_initialized)
-    {
-      is_initialized = cspi_init_relation_type_table (cspi_relation_type_table);           
-    }
-  if (type >= 0 && type < Accessibility_RELATION_LAST_DEFINED)
-    {
-      cspi_type = cspi_relation_type_table [type];         
-    }
-  else
-    {
-      cspi_type = SPI_RELATION_NULL;
-    }
-  return cspi_type; 
-}
-/**
- * AccessibleRelation_getRelationType:
- * @obj: a pointer to the #AtspiAccessibleRelation object to query.
- *
- * Get the type of relationship represented by an #AtspiAccessibleRelation.
- *
- * Returns: an #AtspiAccessibleRelationType indicating the type of relation
- *         encapsulated in this #AtspiAccessibleRelation object.
- *
- **/
-AccessibleRelationType
-AccessibleRelation_getRelationType (AccessibleRelation *obj)
-{
-  cspi_return_val_if_fail (obj, SPI_RELATION_NULL);
-  return cspi_relation_type_from_spi_relation_type (obj->type);
-}
-
-/**
- * AccessibleRelation_getNTargets:
- * @obj: a pointer to the #AtspiAccessibleRelation object to query.
- *
- * Get the number of objects which this relationship has as its
- *       target objects (the subject is the #AtspiAccessible from which this
- *       #AtspiAccessibleRelation originated).
- *
- * Returns: a short integer indicating how many target objects which the
- *       originating #AtspiAccessible object has the #AtspiAccessibleRelation
- *       relationship with.
- **/
-int
-AccessibleRelation_getNTargets (AccessibleRelation *obj)
-{
-  cspi_return_val_if_fail (obj, -1);
-  return obj->targets->len;
-}
-
-/**
- * AccessibleRelation_getTarget:
- * @obj: a pointer to the #AtspiAccessibleRelation object to query.
- * @i: a (zero-index) integer indicating which (of possibly several) target is requested.
- *
- * Get the @i-th target of a specified #AtspiAccessibleRelation relationship.
- *
- * Returns: an #AtspiAccessible which is the @i-th object with which the
- *      originating #AtspiAccessible has relationship specified in the
- *      #AtspiAccessibleRelation object.
- *
- **/
-Accessible *
-AccessibleRelation_getTarget (AccessibleRelation *obj, int i)
+static void
+append_const_val (GArray *array, const gchar *val)
 {
-  cspi_return_val_if_fail (obj, NULL);
+  gchar *dup = g_strdup (val);
 
-  if (i < 0 || i >= obj->targets->len) return NULL;
-  return cspi_object_add (
-                        g_array_index (obj->targets, Accessible *, i));
+  if (dup)
+    g_array_append_val (array, dup);
 }
 
 /**
- * AccessibleStateSet_ref:
- * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
+ * atspi_accessible_get_interfaces:
  *
- * Increment the reference count for an #AtspiAccessibleStateSet object.
+ * #obj: The #AtspiAccessible to query.
  *
+ * Returns: (element-type gchar*) (transfer full): A #GArray of strings
+ *          describing the interfaces supported by the object.  Interfaces are
+ *          denoted in short-hand (ie, "Component", "Text", etc.)
  **/
-void
-AccessibleStateSet_ref (AccessibleStateSet *obj)
-{
-  spi_state_set_cache_ref (obj);
-}
-
-/**
- * AccessibleStateSet_unref:
- * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
- *
- * Decrement the reference count for an #AtspiAccessibleStateSet object.
- *
- **/
-void
-AccessibleStateSet_unref (AccessibleStateSet *obj)
-{
-  spi_state_set_cache_unref (obj);
-}
-
-static Accessibility_StateType
-spi_state_to_dbus (AccessibleState state)
+GArray *
+atspi_accessible_get_interfaces (AtspiAccessible *obj)
 {
-#define MAP_STATE(a) \
-  case SPI_STATE_##a: \
-    return Accessibility_STATE_##a
+  GArray *ret = g_array_new (TRUE, TRUE, sizeof (gchar *));
 
-  switch (state)
-    {
-      MAP_STATE (INVALID);
-      MAP_STATE (ACTIVE);
-      MAP_STATE (ARMED);
-      MAP_STATE (BUSY);
-      MAP_STATE (CHECKED);
-      MAP_STATE (DEFUNCT);
-      MAP_STATE (EDITABLE);
-      MAP_STATE (ENABLED);
-      MAP_STATE (EXPANDABLE);
-      MAP_STATE (EXPANDED);
-      MAP_STATE (FOCUSABLE);
-      MAP_STATE (FOCUSED);
-      MAP_STATE (HORIZONTAL);
-      MAP_STATE (ICONIFIED);
-      MAP_STATE (MODAL);
-      MAP_STATE (MULTI_LINE);
-      MAP_STATE (MULTISELECTABLE);
-      MAP_STATE (OPAQUE);
-      MAP_STATE (PRESSED);
-      MAP_STATE (RESIZABLE);
-      MAP_STATE (SELECTABLE);
-      MAP_STATE (SELECTED);
-      MAP_STATE (SENSITIVE);
-      MAP_STATE (SHOWING);
-      MAP_STATE (SINGLE_LINE);
-      MAP_STATE (STALE);
-      MAP_STATE (TRANSIENT);
-      MAP_STATE (VERTICAL);
-      MAP_STATE (VISIBLE);
-      MAP_STATE (MANAGES_DESCENDANTS);
-      MAP_STATE (INDETERMINATE);
-      MAP_STATE (TRUNCATED);
-      MAP_STATE (REQUIRED);
-      MAP_STATE (INVALID_ENTRY);
-      MAP_STATE (SUPPORTS_AUTOCOMPLETION);
-      MAP_STATE (SELECTABLE_TEXT);
-      MAP_STATE (IS_DEFAULT);
-      MAP_STATE (VISITED);
-    default:
-      return Accessibility_STATE_INVALID;
-  }
-#undef MAP_STATE
-}            
+  if (!ret)
+    return NULL;
 
-/**
- * AccessibleStateSet_contains:
- * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
- * @state: an #AtspiAccessibleState for which the specified #AtspiAccessibleStateSet
- *       will be queried.
- *
- * Determine whether a given #AtspiAccessibleStateSet includes a given state; that is,
- *       whether @state is true for the stateset in question.
- *
- * Returns: #TRUE if @state is true/included in the given #AtspiAccessibleStateSet,
- *          otherwise #FALSE.
- *
- **/
-gboolean
-AccessibleStateSet_contains (AccessibleStateSet *obj,
-                            AccessibleState state)
-{
-  return spi_state_set_cache_contains (obj, spi_state_to_dbus (state));
-}
+  g_return_val_if_fail (obj != NULL, NULL);
 
-/**
- * AccessibleStateSet_add:
- * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
- * @state: an #AtspiAccessibleState to be added to the specified #AtspiAccessibleStateSet
- *
- * Add a particular #AtspiAccessibleState to an #AtspiAccessibleStateSet (i.e. set the
- *       given state to #TRUE in the stateset.
- *
- **/
-void
-AccessibleStateSet_add (AccessibleStateSet *obj,
-                       AccessibleState state)
-{
-  spi_state_set_cache_add (obj, spi_state_to_dbus (state));
-}
+  append_const_val (ret, "Accessible");
+  if (atspi_accessible_is_action (obj))
+    append_const_val (ret, "Action");
+  if (atspi_accessible_is_collection (obj))
+    append_const_val (ret, "Collection");
+  if (atspi_accessible_is_component (obj))
+    append_const_val (ret, "Component");
+  if (atspi_accessible_is_document (obj))
+    append_const_val (ret, "Document");
+  if (atspi_accessible_is_editable_text (obj))
+    append_const_val (ret, "EditableText");
+  if (atspi_accessible_is_hypertext (obj))
+    append_const_val (ret, "Hypertext");
+  if (atspi_accessible_is_hyperlink (obj))
+    append_const_val (ret, "Hyperlink");
+  if (atspi_accessible_is_image (obj))
+    append_const_val (ret, "Image");
+  if (atspi_accessible_is_selection (obj))
+    append_const_val (ret, "Selection");
+  if (atspi_accessible_is_table (obj))
+    append_const_val (ret, "Table");
+  if (atspi_accessible_is_text (obj))
+    append_const_val (ret, "Text");
+  if (atspi_accessible_is_value (obj))
+    append_const_val (ret, "Value");
 
-/**
- * AccessibleStateSet_remove:
- * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
- * @state: an #AtspiAccessibleState to be removed from the specified #AtspiAccessibleStateSet
- *
- * Remove a particular #AtspiAccessibleState to an #AtspiAccessibleStateSet (i.e. set the
- *       given state to #FALSE in the stateset.)
- *
- **/
-void
-AccessibleStateSet_remove (AccessibleStateSet *obj,
-                          AccessibleState state)
-{
-  spi_state_set_cache_remove (obj, spi_state_to_dbus (state));
+  return ret;
 }
 
-/**
- * AccessibleStateSet_equals:
- * @obj: a pointer to the first #AtspiAccessibleStateSet object on which to operate.
- * @obj2: a pointer to the second #AtspiAccessibleStateSet object on which to operate.
- *
- * Determine whether two instances of #AtspiAccessibleStateSet are equivalent (i.e.
- *         consist of the same #AtspiAccessibleStates).  Useful for checking multiple
- *         state variables at once; construct the target state then compare against it.
- *
- * @see AccessibleStateSet_compare().
- *
- * Returns: #TRUE if the two #AtspiAccessibleStateSets are equivalent,
- *          otherwise #FALSE.
- *
- **/
-gboolean
-AccessibleStateSet_equals (AccessibleStateSet *obj,
-                           AccessibleStateSet *obj2)
+AtspiAccessible *
+atspi_accessible_new (AtspiApplication *app, const gchar *path)
 {
-  gboolean   eq;
-  AtkStateSet *cmp;
-
-  if (obj == obj2)
-    {
-      return TRUE;
-    }
+  AtspiAccessible *accessible;
+  
+  accessible = g_object_new (ATSPI_TYPE_ACCESSIBLE, NULL);
+  g_return_val_if_fail (accessible != NULL, NULL);
 
-  cmp = spi_state_set_cache_xor (obj, obj2);
-  eq = spi_state_set_cache_is_empty (cmp);
-  spi_state_set_cache_unref (cmp);
+  accessible->parent.app = g_object_ref (app);
+  accessible->parent.path = g_strdup (path);
 
-  return eq;
-}
-
-/**
- * AccessibleStateSet_compare:
- * @obj: a pointer to the first #AtspiAccessibleStateSet object on which to operate.
- * @obj2: a pointer to the second #AtspiAccessibleStateSet object on which to operate.
- *
- * Determine the differences between two instances of #AtspiAccessibleStateSet.
- * Not Yet Implemented.
- *.
- * @see AccessibleStateSet_equals().
- *
- * Returns: an #AtspiAccessibleStateSet object containing all states contained on one of
- *          the two sets but not the other.
- *
- **/
-AccessibleStateSet *
-AccessibleStateSet_compare (AccessibleStateSet *obj,
-                            AccessibleStateSet *obj2)
-{
-  return spi_state_set_cache_xor (obj, obj2);
+  return accessible;
 }
 
 /**
- * AccessibleStateSet_isEmpty:
- * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
+ * atspi_accessible_set_cache_mask:
  *
- * Determine whether a given #AtspiAccessibleStateSet is the empty set.
+ * @accessible: The #AtspiAccessible to operate on.  Must be the desktop or
+ *             the root of an application.
+ * @mask: An #AtspiCache specifying a bit mask of the types of data to cache.
  *
- * Returns: #TRUE if the given #AtspiAccessibleStateSet contains no (true) states,
- *          otherwise #FALSE.
+ * Sets the type of data to cache for accessibles.
+ * If this is not set for an application or is reset to ATSPI_CACHE_UNDEFINED,
+ * then the desktop's cache flag will be used.
+ * If the desktop's cache flag is also undefined, then all possible data will
+ * be cached.
+ * This function is intended to work around bugs in toolkits where the proper
+ * events are not raised / to aid in testing for such bugs.
  *
+ * Note: This function has no effect on data that has already been cached.
  **/
-gboolean
-AccessibleStateSet_isEmpty (AccessibleStateSet *obj)
+void
+atspi_accessible_set_cache_mask (AtspiAccessible *accessible, AtspiCache mask)
 {
-  return spi_state_set_cache_is_empty (obj);
+  g_return_if_fail (accessible != NULL);
+  g_return_if_fail (accessible->parent.app != NULL);
+  g_return_if_fail (accessible == accessible->parent.app->root);
+  accessible->parent.app->cache = mask;
 }
-#endif
 
-gboolean
-_atspi_accessible_is_a (AtspiAccessible *accessible,
-                     const char *interface_name)
+void
+_atspi_accessible_add_cache (AtspiAccessible *accessible, AtspiCache flag)
 {
-  int n;
-
-  if (accessible == NULL)
-    {
-      return FALSE;
-    }
-
-  n = _atspi_get_iface_num (interface_name);
-  if (n == -1) return FALSE;
-  return (gboolean) ((accessible->interfaces & (1 << n))? TRUE: FALSE);
-}
+  AtspiCache mask = accessible->parent.app->cache;
 
-/* TODO: Move to a finalizer */
-static void
-cspi_object_destroyed (AtspiAccessible *accessible)
-{
-  gboolean cached;
-  AtspiEvent e;
-
-  /* TODO: Only fire if object not already marked defunct */
-  e.type = "object:state-change:defunct";
-  e.source = accessible;
-  e.detail1 = 1;
-  e.detail2 = 0;
-  g_value_unset (&e.any);
-  _atspi_send_event (&e);
-
-    g_free (accessible->path);
-
-    if (accessible->states)
-      g_object_unref (accessible->states);
-    g_free (accessible->description);
-    g_free (accessible->name);
-}
-
-AtspiAccessible *
-atspi_accessible_new (AtspiApplication *app, const gchar *path)
-{
-  AtspiAccessible *accessible;
-  
-  accessible = g_object_new (ATSPI_TYPE_ACCESSIBLE, NULL);
-  g_return_val_if_fail (accessible != NULL, NULL);
+  if (mask == ATSPI_CACHE_UNDEFINED &&
+      accessible->parent.app->root &&
+      accessible->parent.app->root->accessible_parent)
+  {
+    AtspiAccessible *desktop = atspi_get_desktop (0);
+    mask = desktop->parent.app->cache;
+    g_object_unref (desktop);
+  }
 
-  accessible->app = g_object_ref (app);
-  accessible->path = g_strdup (path);
+  if (mask == ATSPI_CACHE_UNDEFINED)
+    mask = ATSPI_CACHE_ALL;
 
-  return accessible;
+  accessible->cached_properties |= flag & mask;
 }