[at-spi2-atk] Integrate leasing scheme in-to atk-bridge.



commit 5713a8e46559b6de9fbf5fc3e073d0d482d8c7e1
Author: Mark Doffman <mark doffman codethink co uk>
Date:   Tue Jan 5 01:47:34 2010 -0800

    Integrate leasing scheme in-to atk-bridge.
    
    This involved:
    	Separating the 'cache' and registration
            of accessible objects. This is because
            the leased objects need to be available over
            D-Bus but are not cached.
    
            Separating the cache updating from the 'events'.
            This is because we should still recieve updates on
            leased accessibles, but they are not cached.

 Makefile.am                                       |    2 +-
 atk-adaptor/Makefile.am                           |    5 +-
 atk-adaptor/accessible-cache.c                    |  389 +++++++++
 atk-adaptor/accessible-cache.h                    |   63 ++
 atk-adaptor/accessible-leasing.c                  |    4 +-
 atk-adaptor/accessible-leasing.h                  |    8 +-
 atk-adaptor/accessible-register.c                 |  889 +++------------------
 atk-adaptor/accessible-register.h                 |   58 +-
 atk-adaptor/adaptors/Makefile.am                  |    5 +-
 atk-adaptor/adaptors/accessible-adaptor.c         |  173 +----
 atk-adaptor/adaptors/accessible-marshaller.c      |  445 -----------
 atk-adaptor/adaptors/accessible-marshaller.h      |   64 --
 atk-adaptor/adaptors/adaptors.h                   |    2 +-
 atk-adaptor/adaptors/cache-adaptor.c              |  301 +++++++
 atk-adaptor/adaptors/collection-adaptor.c         |   23 +-
 atk-adaptor/adaptors/component-adaptor.c          |    4 +-
 atk-adaptor/adaptors/document-adaptor.c           |    3 +-
 atk-adaptor/adaptors/hyperlink-adaptor.c          |    5 +-
 atk-adaptor/adaptors/hypertext-adaptor.c          |    5 +-
 atk-adaptor/adaptors/image-adaptor.c              |    1 +
 atk-adaptor/adaptors/selection-adaptor.c          |    4 +-
 atk-adaptor/adaptors/table-adaptor.c              |   16 +-
 atk-adaptor/adaptors/text-adaptor.c               |   23 +-
 atk-adaptor/adaptors/tree-adaptor.c               |  155 ----
 atk-adaptor/bridge.c                              |   71 +-
 atk-adaptor/bridge.h                              |   24 +-
 atk-adaptor/event.c                               |  328 ++++----
 atk-adaptor/object.c                              |  404 ++++++++++
 atk-adaptor/{adaptors/tree-adaptor.h => object.h} |   35 +-
 common/spi-dbus.c                                 |   38 +
 common/spi-dbus.h                                 |    2 +-
 common/spi-stateset.c                             |    2 +-
 common/spi-stateset.h                             |    2 +-
 configure.ac                                      |   25 +-
 droute/droute.c                                   |    2 +
 35 files changed, 1706 insertions(+), 1874 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 305d97d..31982fe 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1 +1 @@
-SUBDIRS=droute dbind common atk-adaptor tests
+SUBDIRS=droute common atk-adaptor
diff --git a/atk-adaptor/Makefile.am b/atk-adaptor/Makefile.am
index fea7091..140ede4 100644
--- a/atk-adaptor/Makefile.am
+++ b/atk-adaptor/Makefile.am
@@ -22,17 +22,20 @@ libatk_bridge_la_LIBADD = $(DBUS_GLIB_LIBS) \
 		          $(ATK_LIBS)       \
 			  $(X_LIBS)         \
 		          $(top_builddir)/droute/libdroute.la \
-		          $(top_builddir)/dbind/libdbind.la \
 		          $(top_builddir)/common/libspicommon.la \
 			  $(top_builddir)/atk-adaptor/adaptors/libatk-bridge-adaptors.la
 
 libatk_bridge_la_SOURCES =	\
         accessible-leasing.c    \
         accessible-leasing.h    \
+        accessible-cache.c      \
+        accessible-cache.h      \
 	accessible-register.c	\
 	accessible-register.h	\
 	bridge.c		\
 	bridge.h		\
+	object.c		\
+	object.h		\
 	event.c			\
 	event.h
 
diff --git a/atk-adaptor/accessible-cache.c b/atk-adaptor/accessible-cache.c
new file mode 100644
index 0000000..4f87b18
--- /dev/null
+++ b/atk-adaptor/accessible-cache.c
@@ -0,0 +1,389 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2009, 2010 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <atk/atk.h>
+
+#include "accessible-cache.h"
+#include "accessible-register.h"
+#include "bridge.h"
+
+SpiCache *spi_global_cache = NULL;
+
+static gboolean
+child_added_listener (GSignalInvocationHint * signal_hint,
+                      guint n_param_values,
+                      const GValue * param_values, gpointer data);
+
+static void
+toplevel_added_listener (AtkObject * accessible,
+                         guint index, AtkObject * child);
+
+static void
+remove_object (gpointer data, GObject * gobj);
+
+static void
+add_object (SpiCache * cache, GObject * gobj);
+
+static void
+add_subtree (SpiCache *cache, AtkObject * accessible);
+
+/*---------------------------------------------------------------------------*/
+
+static void
+spi_cache_finalize (GObject * object);
+
+static void
+spi_cache_dispose (GObject * object);
+
+/*---------------------------------------------------------------------------*/
+
+enum
+{
+  OBJECT_ADDED,
+  OBJECT_REMOVED,
+  LAST_SIGNAL
+};
+static guint cache_signals[LAST_SIGNAL] = { 0 };
+
+/*---------------------------------------------------------------------------*/
+
+G_DEFINE_TYPE (SpiCache, spi_cache, G_TYPE_OBJECT)
+
+static void spi_cache_class_init (SpiCacheClass * klass)
+{
+  GObjectClass *object_class = (GObjectClass *) klass;
+
+  spi_cache_parent_class = g_type_class_ref (G_TYPE_OBJECT);
+
+  object_class->finalize = spi_cache_finalize;
+  object_class->dispose = spi_cache_dispose;
+
+  cache_signals [OBJECT_ADDED] = \
+      g_signal_new ("object-added",
+                    SPI_CACHE_TYPE,
+                    G_SIGNAL_ACTION,
+                    0,
+                    NULL,
+                    NULL,
+                    g_cclosure_marshal_VOID__OBJECT,
+                    G_TYPE_NONE,
+                    1,
+                    G_TYPE_OBJECT);
+
+  cache_signals [OBJECT_REMOVED] = \
+      g_signal_new ("object-removed",
+                    SPI_CACHE_TYPE,
+                    G_SIGNAL_ACTION,
+                    0,
+                    NULL,
+                    NULL,
+                    g_cclosure_marshal_VOID__OBJECT,
+                    G_TYPE_NONE,
+                    1,
+                    G_TYPE_OBJECT);
+}
+
+static void
+spi_cache_init (SpiCache * cache)
+{
+  cache->objects = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+#ifdef SPI_ATK_DEBUG
+  if (g_thread_supported ())
+    g_message ("AT-SPI: Threads enabled");
+
+  g_debug ("AT-SPI: Initial Atk tree regisration");
+#endif
+
+  g_signal_connect (spi_global_register,
+                    "object-deregistered",
+                    (GCallback) remove_object, cache);
+
+  add_subtree (cache, spi_global_app_data->root);
+
+  atk_add_global_event_listener (child_added_listener,
+                                 "Gtk:AtkObject:children-changed");
+
+  g_signal_connect (G_OBJECT (spi_global_app_data->root),
+                    "children-changed::add",
+                    (GCallback) toplevel_added_listener, NULL);
+}
+
+static void
+spi_cache_finalize (GObject * object)
+{
+  SpiCache *cache = SPI_CACHE (object);
+
+  g_free (cache->objects);
+
+  G_OBJECT_CLASS (spi_cache_parent_class)->finalize (object);
+}
+
+static void
+spi_cache_dispose (GObject * object)
+{
+  SpiCache *cache = SPI_CACHE (object);
+
+  G_OBJECT_CLASS (spi_cache_parent_class)->dispose (object);
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void
+remove_object (gpointer data, GObject * gobj)
+{
+  SpiCache *cache = SPI_CACHE (data);
+  
+  if (spi_cache_in (cache, gobj))
+    {
+      g_signal_emit (cache, cache_signals [OBJECT_REMOVED], 0, gobj);
+      g_hash_table_remove (cache->objects, gobj);
+    }
+}
+
+static void
+add_object (SpiCache * cache, GObject * gobj)
+{
+  g_return_if_fail (G_IS_OBJECT (gobj));
+
+  g_hash_table_insert (cache->objects, gobj, NULL);
+
+  g_signal_emit (cache, cache_signals [OBJECT_ADDED], 0, gobj);
+}
+
+/*---------------------------------------------------------------------------*/
+
+static GStaticRecMutex cache_mutex        = G_STATIC_REC_MUTEX_INIT;
+static GStaticMutex recursion_check_guard = G_STATIC_MUTEX_INIT;
+
+static gboolean recursion_check = FALSE;
+
+static gboolean
+recursion_check_and_set ()
+{
+  gboolean ret;
+  g_static_mutex_lock (&recursion_check_guard);
+  ret = recursion_check;
+  recursion_check = TRUE;
+  g_static_mutex_unlock (&recursion_check_guard);
+  return ret;
+}
+
+static void
+recursion_check_unset ()
+{
+  g_static_mutex_lock (&recursion_check_guard);
+  recursion_check = FALSE;
+  g_static_mutex_unlock (&recursion_check_guard);
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void
+append_children (AtkObject * accessible, GQueue * traversal)
+{
+  AtkObject *current;
+  guint i;
+  gint count = atk_object_get_n_accessible_children (accessible);
+
+  if (count < 0)
+    count = 0;
+  for (i = 0; i < count; i++)
+    {
+      current = atk_object_ref_accessible_child (accessible, i);
+      if (current)
+        {
+          g_queue_push_tail (traversal, current);
+        }
+    }
+}
+
+/*
+ * Adds a subtree of accessible objects
+ * to the cache at the accessible object provided.
+ *
+ * The leaf nodes do not have their children
+ * registered. A node is considered a leaf
+ * if it has the state "manages-descendants"
+ * or if it has already been registered.
+ */
+static void
+add_subtree (SpiCache *cache, AtkObject * accessible)
+{
+  AtkObject *current;
+  GQueue *traversal;
+  GQueue *to_add;
+
+  g_return_if_fail (ATK_IS_OBJECT (accessible));
+
+  traversal = g_queue_new ();
+  to_add = g_queue_new ();
+
+  g_object_ref (accessible);
+  g_queue_push_tail (traversal, accessible);
+
+  while (!g_queue_is_empty (traversal))
+    {
+      AtkStateSet *set;
+      
+      current = g_queue_pop_head (traversal);
+      set = atk_object_ref_state_set (current);
+
+      if (!atk_state_set_contains_state (set, ATK_STATE_TRANSIENT))
+        {
+	  g_queue_push_tail (to_add, current);
+          if (!spi_cache_in (cache, G_OBJECT (current)) &&
+              !atk_state_set_contains_state  (set, ATK_STATE_MANAGES_DESCENDANTS))
+            {
+#ifdef SPI_ATK_DEBUG
+              g_debug ("REG  - %s - %d - %s", atk_object_get_name (current),
+                       atk_object_get_role (current),
+                       atk_dbus_object_to_path (current));
+#endif
+              append_children (current, traversal);
+            }
+        }
+
+      g_object_unref (set);
+    }
+
+  while (!g_queue_is_empty (to_add))
+    {
+      current = g_queue_pop_head (to_add);
+      add_object (cache, G_OBJECT(current));
+      g_object_unref (G_OBJECT (current));
+    }
+
+  g_queue_free (traversal);
+  g_queue_free (to_add);
+}
+
+/*---------------------------------------------------------------------------*/
+
+static gboolean
+child_added_listener (GSignalInvocationHint * signal_hint,
+                      guint n_param_values,
+                      const GValue * param_values, gpointer data)
+{
+  SpiCache *cache = spi_global_cache;
+
+  AtkObject *accessible;
+  AtkObject *child;
+
+  const gchar *detail = NULL;
+
+  g_static_rec_mutex_lock (&cache_mutex);
+
+  /* 
+   * Ensure that only accessibles already in the cache
+   * have their signals processed.
+   */
+  accessible = ATK_OBJECT (g_value_get_object (&param_values[0]));
+  g_return_val_if_fail (ATK_IS_OBJECT (accessible), TRUE);
+
+  if (spi_cache_in (cache, G_OBJECT(accessible)))
+    {
+#ifdef SPI_ATK_DEBUG
+      if (recursion_check_and_set ())
+        g_warning ("AT-SPI: Recursive use of cache module");
+
+      g_debug ("AT-SPI: Tree update listener");
+#endif
+      if (signal_hint->detail)
+        detail = g_quark_to_string (signal_hint->detail);
+
+      if (!strcmp (detail, "add"))
+        {
+          gpointer child;
+          int index = g_value_get_uint (param_values + 1);
+          child = g_value_get_pointer (param_values + 2);
+
+          if (!ATK_IS_OBJECT (child))
+           {
+             child = atk_object_ref_accessible_child (accessible, index);
+           }
+          add_subtree (cache, child);
+        }
+#ifdef SPI_ATK_DEBUG
+      recursion_check_unset ();
+#endif
+    }
+
+  g_static_rec_mutex_unlock (&cache_mutex);
+
+  return TRUE;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void
+toplevel_added_listener (AtkObject * accessible,
+                         guint index, AtkObject * child)
+{
+  SpiCache *cache = spi_global_cache;
+
+  g_static_rec_mutex_lock (&cache_mutex);
+
+  g_return_if_fail (ATK_IS_OBJECT (accessible));
+
+  if (spi_cache_in (cache, G_OBJECT(accessible)))
+    {
+#ifdef SPI_ATK_DEBUG
+      if (recursion_check_and_set ())
+        g_warning ("AT-SPI: Recursive use of registration module");
+
+      g_debug ("AT-SPI: Toplevel added listener");
+#endif
+      if (!ATK_IS_OBJECT (child))
+        {
+          child = atk_object_ref_accessible_child (accessible, index);
+        }
+      add_subtree (cache, child);
+#ifdef SPI_ATK_DEBUG
+      recursion_check_unset ();
+#endif
+    }
+
+  g_static_rec_mutex_unlock (&cache_mutex);
+}
+
+/*---------------------------------------------------------------------------*/
+
+void
+spi_cache_foreach (SpiCache * cache, GHFunc func, gpointer data)
+{
+  g_hash_table_foreach (cache->objects, func, data);
+}
+
+gboolean
+spi_cache_in (SpiCache * cache, GObject * object)
+{
+  if (g_hash_table_lookup_extended (cache->objects,
+                                    object,
+                                    NULL,
+                                    NULL))
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/*END------------------------------------------------------------------------*/
diff --git a/atk-adaptor/accessible-cache.h b/atk-adaptor/accessible-cache.h
new file mode 100644
index 0000000..8d75b5d
--- /dev/null
+++ b/atk-adaptor/accessible-cache.h
@@ -0,0 +1,63 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2010 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef ACCESSIBLE_CACHE_H
+#define ACCESSIBLE_CACHE_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+typedef struct _SpiCache SpiCache;
+typedef struct _SpiCacheClass SpiCacheClass;
+
+G_BEGIN_DECLS
+
+#define SPI_CACHE_TYPE        (spi_cache_get_type ())
+#define SPI_CACHE(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), SPI_CACHE_TYPE, SpiCache))
+#define SPI_CACHE_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), SPI_CACHE_TYPE, SpiCacheClass))
+#define SPI_IS_CACHE(o)       (G_TYPE_CHECK__INSTANCE_TYPE ((o), SPI_CACHE_TYPE))
+#define SPI_IS_CACHE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SPI_CACHE_TYPE))
+
+struct _SpiCache
+{
+  GObject parent;
+
+  GHashTable * objects;
+};
+
+struct _SpiCacheClass
+{
+  GObjectClass parent_class;
+};
+
+GType spi_cache_get_type (void);
+
+extern SpiCache *spi_global_cache;
+
+void
+spi_cache_foreach (SpiCache * cache, GHFunc func, gpointer data);
+
+gboolean
+spi_cache_in (SpiCache * cache, GObject * object);
+
+G_END_DECLS
+#endif /* ACCESSIBLE_CACHE_H */
diff --git a/atk-adaptor/accessible-leasing.c b/atk-adaptor/accessible-leasing.c
index 0bfd496..28d4099 100644
--- a/atk-adaptor/accessible-leasing.c
+++ b/atk-adaptor/accessible-leasing.c
@@ -24,10 +24,12 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <accessible-leasing.h>
+#include "accessible-leasing.h"
 
 /*---------------------------------------------------------------------------*/
 
+SpiLeasing *spi_global_leasing;
+
 typedef struct _ExpiryElement
 {
   guint expiry_s;
diff --git a/atk-adaptor/accessible-leasing.h b/atk-adaptor/accessible-leasing.h
index 50f1f3c..af01a78 100644
--- a/atk-adaptor/accessible-leasing.h
+++ b/atk-adaptor/accessible-leasing.h
@@ -21,8 +21,8 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#ifndef ACCESSIBLE_LEASING
-#define ACCESSIBLE_LEASING
+#ifndef ACCESSIBLE_LEASING_H
+#define ACCESSIBLE_LEASING_H
 
 #include <glib.h>
 #include <glib-object.h>
@@ -53,7 +53,9 @@ struct _SpiLeasingClass
 
 GType spi_leasing_get_type (void);
 
+extern SpiLeasing *spi_global_leasing;
+
 GObject *spi_leasing_take (SpiLeasing * leasing, GObject * object);
 
 G_END_DECLS
-#endif /* ACCESSIBLE_LEASING */
+#endif /* ACCESSIBLE_LEASING_H */
diff --git a/atk-adaptor/accessible-register.c b/atk-adaptor/accessible-register.c
index f0963af..ac93dee 100644
--- a/atk-adaptor/accessible-register.c
+++ b/atk-adaptor/accessible-register.c
@@ -3,7 +3,7 @@
  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
  *
  * Copyright 2008 Novell, Inc.
- * Copyright 2008, 2009 Codethink Ltd.
+ * Copyright 2008, 2009, 2010 Codethink Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -26,7 +26,6 @@
 #include <string.h>
 
 #include "bridge.h"
-#include "tree-adaptor.h"
 #include "accessible-register.h"
 
 /*
@@ -46,74 +45,95 @@
  * object destruction. When an object is destroyed it must be 'deregistered'
  * To do this lookup we keep a dbus-id attribute on each AtkObject.
  *
- * In addition to accessing the objects remotely we must be able to update
- * the client side cache. This is done using the 'update' signal of the 
- * org.freedesktop.atspi.Tree interface. The update signal should send out
- * all of the cacheable data for an Accessible object.
- *
  */
 
-/*
- * FIXME
- *
- * 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.
- *
- * This is the same system as Qt has with the QAccessibleBridge
- * and QAccessibleBridgePlugin. It entails some rather
- * large structural changes to ATK though:
- *
- * 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 "/desktop"
+#define SPI_ATK_PATH_PREFIX_LENGTH 22
+#define SPI_ATK_OBJECT_PATH_PREFIX  "/org/at_spi/accessible"
+#define SPI_ATK_OBJECT_PATH_DESKTOP SPI_ATK_OBJECT_PATH_PREFIX "/desktop"
 
-#define SPI_ATK_PATH_PREFIX_LENGTH 33
 #define SPI_ATK_OBJECT_REFERENCE_TEMPLATE SPI_ATK_OBJECT_PATH_PREFIX "/%d"
 
+#define SPI_DBUS_ID "spi-dbus-id"
+
+SpiRegister *spi_global_register = NULL;
+
+enum
+{
+  OBJECT_REGISTERED,
+  OBJECT_DEREGISTERED,
+  LAST_SIGNAL
+};
+static guint register_signals[LAST_SIGNAL] = { 0 };
 
-static GHashTable *ref2ptr = NULL;      /* Used for converting a D-Bus path (Reference) to the object pointer */
-static GHashTable *objects_with_subrefs = NULL;
-static GHashTable *leased_refs = NULL;
-static int leased_refs_count;
+/*---------------------------------------------------------------------------*/
 
-static guint reference_counter = 0;
+static void
+spi_register_finalize (GObject * object);
 
-static GStaticRecMutex registration_mutex = G_STATIC_REC_MUTEX_INIT;
+static void
+spi_register_dispose (GObject * object);
 
 /*---------------------------------------------------------------------------*/
 
-static GStaticMutex recursion_check_guard = G_STATIC_MUTEX_INIT;
-static gboolean recursion_check = FALSE;
-static int last_gc_time;
+G_DEFINE_TYPE (SpiRegister, spi_register, G_TYPE_OBJECT)
 
-static void deregister_sub_accessible (gpointer key, gpointer obj_data,
-                                       gpointer iter);
+static void spi_register_class_init (SpiRegisterClass * klass)
+{
+  GObjectClass *object_class = (GObjectClass *) klass;
 
-static void deregister_sub_hyperlink (gpointer key, gpointer obj_data,
-                                      gpointer iter);
+  spi_register_parent_class = g_type_class_ref (G_TYPE_OBJECT);
+
+  object_class->finalize = spi_register_finalize;
+  object_class->dispose = spi_register_dispose;
+
+  register_signals [OBJECT_REGISTERED] =
+      g_signal_new ("object-registered",
+                    SPI_REGISTER_TYPE,
+                    G_SIGNAL_ACTION,
+                    0,
+                    NULL,
+                    NULL,
+                    g_cclosure_marshal_VOID__OBJECT,
+                    G_TYPE_NONE,
+                    1,
+                    G_TYPE_OBJECT);
+
+  register_signals [OBJECT_DEREGISTERED] =
+      g_signal_new ("object-deregistered",
+                    SPI_REGISTER_TYPE,
+                    G_SIGNAL_ACTION,
+                    0,
+                    NULL,
+                    NULL,
+                    g_cclosure_marshal_VOID__OBJECT,
+                    G_TYPE_NONE,
+                    1,
+                    G_TYPE_OBJECT);
+}
 
-static gboolean
-recursion_check_and_set ()
+static void
+spi_register_init (SpiRegister * reg)
 {
-  gboolean ret;
-  g_static_mutex_lock (&recursion_check_guard);
-  ret = recursion_check;
-  recursion_check = TRUE;
-  g_static_mutex_unlock (&recursion_check_guard);
-  return ret;
+  reg->ref2ptr = g_hash_table_new (g_direct_hash, g_direct_equal);
+  reg->reference_counter = 0;
 }
 
 static void
-recursion_check_unset ()
+spi_register_finalize (GObject * object)
 {
-  g_static_mutex_lock (&recursion_check_guard);
-  recursion_check = FALSE;
-  g_static_mutex_unlock (&recursion_check_guard);
+  SpiRegister *reg = SPI_REGISTER (object);
+
+  g_free (reg->ref2ptr);
+
+  G_OBJECT_CLASS (spi_register_parent_class)->finalize (object);
+}
+
+static void
+spi_register_dispose (GObject * object)
+{
+  SpiRegister *reg = SPI_REGISTER (object);
+
+  G_OBJECT_CLASS (spi_register_parent_class)->dispose (object);
 }
 
 /*---------------------------------------------------------------------------*/
@@ -123,44 +143,35 @@ recursion_check_unset ()
  *
  * This function provides an integer reference for a new
  * AtkObject.
+ *
+ * TODO: Make this reference a little more unique, this is shoddy.
  */
 static guint
-assign_reference (void)
+assign_reference (SpiRegister * reg)
 {
-  reference_counter++;
+  reg->reference_counter++;
   /* Reference of 0 not allowed as used as direct key in hash table */
-  if (reference_counter == 0)
-    reference_counter++;
-  /* TODO: If we've wrapped, ensure that two objects don't have the same ref */
-  return reference_counter;
+  if (reg->reference_counter == 0)
+    reg->reference_counter++;
+  return reg->reference_counter;
 }
 
+/*---------------------------------------------------------------------------*/
+
 /*
  * Returns the reference of the object, or 0 if it is not registered.
  */
 static guint
-gobject_to_ref (GObject * gobj)
-{
-  return GPOINTER_TO_INT (g_object_get_data (gobj, "dbus-id"));
-}
-
-static guint
-object_to_ref (AtkObject * accessible)
+object_to_ref (GObject * gobj)
 {
-  return gobject_to_ref (G_OBJECT (accessible));
-}
-
-static guint
-hyperlink_to_ref (AtkHyperlink * link)
-{
-  return gobject_to_ref (G_OBJECT (link));
+  return GPOINTER_TO_INT (g_object_get_data (gobj, SPI_DBUS_ID));
 }
 
 /*
  * Converts the Accessible object reference to its D-Bus object path
  */
-gchar *
-atk_dbus_ref_to_path (guint ref)
+static gchar *
+ref_to_path (guint ref)
 {
   return g_strdup_printf (SPI_ATK_OBJECT_REFERENCE_TEMPLATE, ref);
 }
@@ -176,305 +187,44 @@ atk_dbus_ref_to_path (guint ref)
 static void
 deregister_object (gpointer data, GObject * gobj)
 {
+  SpiRegister *reg = SPI_REGISTER (data);
   guint ref;
-  GHashTable *subrefs_atk;
-  GHashTable *subrefs_hyperlink;
-  g_return_if_fail (ATK_IS_OBJECT (gobj) || ATK_IS_HYPERLINK (gobj));
-
-  subrefs_atk = (GHashTable *) g_object_get_data (gobj, "dbus-subrefs-atk");
-  subrefs_hyperlink =
-    (GHashTable *) g_object_get_data (gobj, "dbus-subrefs-hyperlink");
-
-  if (subrefs_atk)
-    {
-      g_hash_table_foreach (subrefs_atk, deregister_sub_accessible, data);
-      g_hash_table_unref (subrefs_atk);
-    }
-
-  if (subrefs_hyperlink)
-    {
-      g_hash_table_foreach (subrefs_hyperlink, deregister_sub_hyperlink,
-                            data);
-      g_hash_table_unref (subrefs_hyperlink);
-    }
-
-  if (subrefs_atk || subrefs_hyperlink)
-    g_hash_table_remove (objects_with_subrefs, gobj);
-
-  if (ATK_IS_OBJECT (gobj))
-    {
-      ref = object_to_ref (ATK_OBJECT (gobj));
-      if (ref != 0)
-        {
-          spi_emit_cache_removal (ref, atk_adaptor_app_data->bus);
-          g_hash_table_remove (ref2ptr, GINT_TO_POINTER (ref));
-        }
-    }
-}
-
-static void
-deregister_sub_accessible (gpointer key, gpointer obj_data, gpointer iter)
-{
-  GObject *obj = G_OBJECT (obj_data);
-  deregister_object (NULL, obj);
-  g_hash_table_remove (leased_refs, obj);
-  g_object_unref (obj);
-}
-
-static void
-deregister_sub_hyperlink (gpointer key, gpointer obj_data, gpointer iter)
-{
-  guint ref;
-  GObject *ghyperlink = G_OBJECT (obj_data);
 
-  g_return_if_fail (ATK_IS_HYPERLINK (ghyperlink));
-
-  ref = gobject_to_ref (ghyperlink);
+  ref = object_to_ref (gobj);
   if (ref != 0)
     {
-      g_hash_table_remove (ref2ptr, GINT_TO_POINTER (ref));
+      g_signal_emit (reg,
+                     register_signals [OBJECT_DEREGISTERED],
+                     0,
+                     gobj);
+      g_hash_table_remove (reg->ref2ptr, GINT_TO_POINTER (ref));
     }
-  g_object_unref (ghyperlink);
 }
 
 static void
-register_gobject (GObject * gobj, GObject * container)
+register_object (SpiRegister * reg, GObject * gobj)
 {
   guint ref;
   g_return_if_fail (G_IS_OBJECT (gobj));
 
-  ref = assign_reference ();
-
-  g_hash_table_insert (ref2ptr, GINT_TO_POINTER (ref), gobj);
-  g_object_set_data (G_OBJECT (gobj), "dbus-id", GINT_TO_POINTER (ref));
-  g_object_weak_ref (G_OBJECT (gobj), deregister_object, NULL);
-
-  if (container)
-    {
-      GHashTable *subrefs =
-        (GHashTable *) g_object_get_data (G_OBJECT (container),
-                                          "dbus-subrefs-atk");
-      if (!subrefs)
-        {
-          subrefs = g_hash_table_new (g_direct_hash, g_direct_equal);
-          g_object_set_data (G_OBJECT (container), "dbus-subrefs-atk",
-                             subrefs);
-        }
-      g_hash_table_insert (subrefs, GINT_TO_POINTER (ref), gobj);
-      g_hash_table_insert (objects_with_subrefs, gobj, subrefs);
-    }
-
-  if (ATK_IS_HYPERLINK (gobj))
-    g_object_ref (gobj);
-  else if (ATK_IS_OBJECT (gobj))
-    {
-      AtkObject *accessible = ATK_OBJECT (gobj);
-      AtkStateSet *state = atk_object_ref_state_set (accessible);
-      if (atk_state_set_contains_state (state, ATK_STATE_TRANSIENT))
-        {
-          g_object_ref (gobj);
-          /* We should only get here as the result of a query other than GetTree */
-          spi_emit_cache_update (accessible, atk_adaptor_app_data->bus);
-        }
-      g_object_unref (state);
-    }
-}
-
-/*
- * Called to register an AtkObject with AT-SPI and expose it over D-Bus.
- */
-static void
-register_accessible (AtkObject * accessible, AtkObject * container)
-{
-  g_return_if_fail (ATK_IS_OBJECT (accessible));
-
-  register_gobject (G_OBJECT (accessible), G_OBJECT (container));
-}
-
-static void
-register_hyperlink (AtkHyperlink * hyperlink, AtkObject * container)
-{
-  guint ref;
-  g_return_if_fail (ATK_IS_HYPERLINK (hyperlink));
-  g_return_if_fail (container);
-
-  ref = assign_reference ();
+  ref = assign_reference (reg);
 
-  g_hash_table_insert (ref2ptr, GINT_TO_POINTER (ref), hyperlink);
-  g_object_set_data (G_OBJECT (hyperlink), "dbus-id", GINT_TO_POINTER (ref));
-  g_object_ref (G_OBJECT (hyperlink));
+  g_hash_table_insert (reg->ref2ptr, GINT_TO_POINTER (ref), gobj);
+  g_object_set_data (G_OBJECT (gobj), SPI_DBUS_ID, GINT_TO_POINTER (ref));
+  g_object_weak_ref (G_OBJECT (gobj), deregister_object, reg);
 
-  GHashTable *subrefs =
-    (GHashTable *) g_object_get_data (G_OBJECT (container),
-                                      "dbus-subrefs-hyperlink");
-  if (!subrefs)
-    {
-      subrefs = g_hash_table_new (g_direct_hash, g_direct_equal);
-      g_object_set_data (G_OBJECT (container), "dbus-subrefs-hyperlink",
-                         GINT_TO_POINTER (ref));
-    }
-  g_hash_table_insert (subrefs, GINT_TO_POINTER (ref), hyperlink);
-}
-
-/*---------------------------------------------------------------------------*/
-
-#ifdef SPI_ATK_DEBUG
-/*
- * This function checks that the ref-count of an accessible
- * is greater than 1.
- *
- * There is not currently any remote reference counting
- * in AT-SPI D-Bus so objects that are remotely owned are not
- * allowed.
- *
- * TODO Add debug wrapper
- */
-static gboolean
-non_owned_accessible (AtkObject * accessible)
-{
-  if ((G_OBJECT (accessible))->ref_count <= 1)
-    {
-      g_warning ("AT-SPI: Child referenced that is not owned by its parent");
-      return TRUE;
-    }
-  else
-    {
-      return FALSE;
-    }
-}
-#endif /* SPI_ATK_DEBUG */
-
-/*---------------------------------------------------------------------------*/
-
-/* TRUE if we should not keep this object / tell the AT about it
- * Currently true if TRANSIENT and not SHOWING
- */
-static gboolean
-object_is_moot (AtkObject * accessible)
-{
-  AtkStateSet *state;
-  gboolean result = FALSE;
-
-  /* This is dangerous, refing the state set
-   * seems to do wierd things to the tree & cause recursion
-   * by modifying the tree alot.
-   */
-  state = atk_object_ref_state_set (accessible);
-  if (atk_state_set_contains_state (state, ATK_STATE_TRANSIENT) &&
-      !atk_state_set_contains_state (state, ATK_STATE_SHOWING))
-    {
-      result = TRUE;
-    }
-  g_object_unref (state);
-
-  return result;
-}
-
-static void
-append_children (AtkObject * accessible, GQueue * traversal)
-{
-  AtkObject *current;
-  guint i;
-  gint count = atk_object_get_n_accessible_children (accessible);
-
-  if (count < 0)
-    count = 0;
-  for (i = 0; i < count; i++)
-    {
-      current = atk_object_ref_accessible_child (accessible, i);
-      if (current)
-        {
-#ifdef SPI_ATK_DEBUG
-          non_owned_accessible (current);
-#endif
-          g_queue_push_tail (traversal, current);
-        }
-    }
-}
-
-/*
- * Registers a subtree of accessible objects
- * rooted at the accessible object provided.
- *
- * The leaf nodes do not have their children
- * registered. A node is considered a leaf
- * if it has the state "manages-descendants"
- * or if it has already been registered.
- */
-void
-register_subtree (AtkObject * accessible)
-{
-  AtkObject *current;
-  GQueue *traversal;
-  GQueue *emit_update;
-
-  g_return_if_fail (ATK_IS_OBJECT (accessible));
-
-  traversal = g_queue_new ();
-  emit_update = g_queue_new ();
-
-  g_object_ref (accessible);
-  g_queue_push_tail (traversal, accessible);
-
-  while (!g_queue_is_empty (traversal))
-    {
-      current = g_queue_pop_head (traversal);
-      g_queue_push_tail (emit_update, current);
-      if (!object_to_ref (current))
-        {
-          register_accessible (current, NULL);
-#ifdef SPI_ATK_DEBUG
-          g_debug ("REG  - %s - %d - %s", atk_object_get_name (current),
-                   atk_object_get_role (current),
-                   atk_dbus_object_to_path (current));
-#endif
-          append_children (current, traversal);
-        }
-    }
-
-  while (!g_queue_is_empty (emit_update))
-    {
-      current = g_queue_pop_head (emit_update);
-      spi_emit_cache_update (current, atk_adaptor_app_data->bus);
-      g_object_unref (G_OBJECT (current));
-    }
-
-  g_queue_free (traversal);
-  g_queue_free (emit_update);
-}
-
-/*---------------------------------------------------------------------------*/
-
-/*
- * Called when an already registered object is updated in such a
- * way that client side cache needs to be updated.
- */
-static void
-update_accessible (AtkObject * accessible)
-{
-  guint ref = 0;
-  g_return_if_fail (ATK_IS_OBJECT (accessible));
-
-  ref = object_to_ref (accessible);
-  if (ref)
-    {
-      spi_emit_cache_update (accessible, atk_adaptor_app_data->bus);
-    }
+  g_signal_emit (reg, register_signals [OBJECT_REGISTERED], 0, gobj);
 }
 
 /*---------------------------------------------------------------------------*/
 
-void
-atk_dbus_foreach_registered (GHFunc func, gpointer data)
-{
-  g_hash_table_foreach (ref2ptr, func, data);
-}
-
 /*
- * Used to lookup an AtkObject from its D-Bus path.
+ * Used to lookup an GObject from its D-Bus path.
+ * 
+ * If the D-Bus path is not found this function returns NULL.
  */
 GObject *
-atk_dbus_path_to_gobject (const char *path)
+spi_register_path_to_object (SpiRegister * reg, const char *path)
 {
   guint index;
   void *data;
@@ -494,447 +244,58 @@ atk_dbus_path_to_gobject (const char *path)
 
   path++;
   index = atoi (path);
-  data = g_hash_table_lookup (ref2ptr, GINT_TO_POINTER (index));
+  data = g_hash_table_lookup (reg->ref2ptr, GINT_TO_POINTER (index));
   if (data)
-    {
-      GObject *gobj = G_OBJECT (data);
-      g_object_set_data (gobj, "last-ref-time", (gpointer) time (NULL));
-      return gobj;
-    }
+    return G_OBJECT(data);
   else
     return NULL;
 }
 
-AtkObject *
-atk_dbus_path_to_object (const char *path)
+GObject *
+spi_global_register_path_to_object (const char * path)
 {
-  return ATK_OBJECT (atk_dbus_path_to_gobject (path));
+  return spi_register_path_to_object (spi_global_register, path);
 }
 
 /*
- * TODO WARNING HACK This function is dangerous.
- * It should only be called before sending an event on an
- * object that has not already been registered.
+ * Used to lookup a D-Bus path from the GObject.
+ * 
+ * If the objects is not already registered, 
+ * this function will register it.
  */
 gchar *
-atk_dbus_object_attempt_registration (AtkObject * accessible)
+spi_register_object_to_path (SpiRegister * reg, GObject * gobj)
 {
   guint ref;
 
-  ref = object_to_ref (accessible);
+  ref = object_to_ref (gobj);
   if (!ref)
     {
-      /* See if the object is attached to the main tree */
-      AtkObject *current, *prev = NULL;
-      guint cref = 0;
-
-      /* This should iterate until it hits a NULL or registered parent */
-      prev = accessible;
-      current = atk_object_get_parent (accessible);
-      if (current)
-        cref = object_to_ref (current);
-      while (current && !cref)
-        {
-          prev = current;
-          current = atk_object_get_parent (current);
-          if (current)
-            cref = object_to_ref (current);
-        }
-
-      /* A registered parent, with non-registered child, has been found */
-      if (current)
-        {
-          register_subtree (prev);
-        }
-
-      /* The object SHOULD be registered now. If it isn't - I give up */
-      ref = object_to_ref (accessible);
-      if (ref)
-        {
-          return atk_dbus_ref_to_path (ref);
-        }
-      else
-        {
-#ifdef SPI_ATK_DEBUG
-          g_debug
-            ("AT-SPI: Could not register a non-attached accessible object");
-#endif
-          return NULL;
-        }
-    }
-  else
-    {
-      return atk_dbus_ref_to_path (ref);
-    }
-}
-
-
-/*
- * Used to lookup a D-Bus path from the AtkObject.
- */
-static gchar *
-atk_dbus_gobject_to_path_internal (GObject * gobj, gboolean do_register,
-                                   GObject * container)
-{
-  guint ref;
-
-  ref = gobject_to_ref (gobj);
-  if (!ref && do_register)
-    {
-      register_gobject (gobj, container);
-      ref = gobject_to_ref (gobj);
+      register_object (reg, gobj);
+      ref = object_to_ref (gobj);
     }
 
   if (!ref)
     return NULL;
   else
-    return atk_dbus_ref_to_path (ref);
-}
-
-gchar *
-atk_dbus_object_to_path (AtkObject * accessible, gboolean do_register)
-{
-  AtkObject *container = (accessible
-                          && do_register ? atk_object_get_parent (accessible)
-                          : NULL);
-  return atk_dbus_gobject_to_path_internal (G_OBJECT (accessible),
-                                            do_register,
-                                            G_OBJECT (container));
-}
-
-gchar *
-atk_dbus_sub_object_to_path (GObject * gobj, GObject * container)
-{
-  return atk_dbus_gobject_to_path_internal (gobj, TRUE, container);
-}
-
-gchar *
-atk_dbus_hyperlink_to_path (AtkHyperlink * hyperlink, AtkObject * container)
-{
-  guint ref;
-
-  ref = gobject_to_ref (G_OBJECT (hyperlink));
-  if (!ref && container)
-    {
-      register_hyperlink (hyperlink, container);
-      ref = hyperlink_to_ref (hyperlink);
-    }
-
-  if (!ref)
-    return NULL;
-  else
-    return atk_dbus_ref_to_path (ref);
-}
-
-gchar *
-atk_dbus_desktop_object_path ()
-{
-  return g_strdup (SPI_ATK_OBJECT_PATH_PREFIX SPI_ATK_OBJECT_PATH_DESKTOP);
-}
-
-/*---------------------------------------------------------------------------*/
-
-typedef gboolean (*TreeUpdateAction) (GSignalInvocationHint * signal_hint,
-                                      guint n_param_values,
-                                      const GValue * param_values,
-                                      gpointer data, AtkObject * accessible);
-
-/*
- * Events are not evaluated for non-registered accessibles.
- *
- * When a property change is made on a registered accessible
- * the client side cache should be updated.
- *
- * When a parent is changed the subtree is de-registered
- * if the parent is not attached to the root accessible.
- */
-/* TODO Turn this function into a macro? */
-static gboolean
-tree_update_wrapper (GSignalInvocationHint * signal_hint,
-                     guint n_param_values,
-                     const GValue * param_values,
-                     gpointer data, TreeUpdateAction action)
-{
-  AtkObject *accessible;
-
-  g_static_rec_mutex_lock (&registration_mutex);
-
-  /* Ensure that only registered accessibles
-   * have their signals processed.
-   */
-  accessible = ATK_OBJECT (g_value_get_object (&param_values[0]));
-  g_return_val_if_fail (ATK_IS_OBJECT (accessible), TRUE);
-
-  if (object_to_ref (accessible))
-    {
-#ifdef SPI_ATK_DEBUG
-      if (recursion_check_and_set ())
-        g_warning ("AT-SPI: Recursive use of registration module");
-
-      g_debug ("AT-SPI: Tree update listener");
-#endif
-      action (signal_hint, n_param_values, param_values, data, accessible);
-
-      recursion_check_unset ();
-    }
-
-  g_static_rec_mutex_unlock (&registration_mutex);
-
-  return TRUE;
-}
-
-static gboolean
-maybe_expire_lease (gpointer key, gpointer obj_data, gpointer iter)
-{
-  time_t secs = time (NULL) - (time_t) obj_data;
-
-  if (secs < 30)
-    return FALSE;
-  deregister_sub_accessible (key, obj_data, iter);
-  return TRUE;
+    return ref_to_path (ref);
 }
 
-static void
-expire_old_leases_in (gpointer key, gpointer obj_data, gpointer iter)
-{
-  g_hash_table_foreach_remove ((GHashTable *) obj_data, maybe_expire_lease,
-                               NULL);
-}
-
-static void
-expire_old_leases ()
-{
-  g_hash_table_foreach (objects_with_subrefs, expire_old_leases_in, NULL);
-}
-
-static gboolean
-tree_update_state_action (GSignalInvocationHint * signal_hint,
-                          guint n_param_values,
-                          const GValue * param_values,
-                          gpointer data, AtkObject * accessible)
-{
-  const gchar *name;
-  gboolean state;
-
-  if (n_param_values < 3)
-    {
-      g_warning ("at-spi: Not enough params in state-changed signal");
-      return TRUE;
-    }
-
-  name = g_value_get_string (param_values + 1);
-  state = g_value_get_boolean (param_values + 2);
-  if (!strcmp (name, "visible"))
-    {
-      AtkStateSet *set = atk_object_ref_state_set (accessible);
-      if (atk_state_set_contains_state (set, ATK_STATE_TRANSIENT))
-        {
-          if (state == 0)
-            {
-              g_hash_table_insert (leased_refs, accessible,
-                                   (gpointer) time (NULL));
-              leased_refs_count++;
-              /* todo: Set to a high number: 5 for dbg. */
-              if (leased_refs_count > 5)
-                expire_old_leases ();
-            }
-          else
-            {
-              g_hash_table_remove (leased_refs, accessible);
-              leased_refs_count--;
-            }
-        }
-      g_object_unref (set);
-    }
-
-  update_accessible (accessible);
-  return TRUE;
-}
-
-static gboolean
-tree_update_state_listener (GSignalInvocationHint * signal_hint,
-                            guint n_param_values,
-                            const GValue * param_values, gpointer data)
+guint
+spi_register_object_to_ref (GObject * gobj)
 {
-  tree_update_wrapper (signal_hint, n_param_values, param_values, data,
-                       tree_update_state_action);
-  return TRUE;
-}
-
-static gboolean
-tree_update_property_action (GSignalInvocationHint * signal_hint,
-                             guint n_param_values,
-                             const GValue * param_values,
-                             gpointer data, AtkObject * accessible)
-{
-  AtkPropertyValues *values;
-  const gchar *pname = NULL;
-
-  values = (AtkPropertyValues *) g_value_get_pointer (&param_values[1]);
-  pname = values[0].property_name;
-  if (strcmp (pname, "accessible-name") == 0 ||
-      strcmp (pname, "accessible-description") == 0 ||
-      strcmp (pname, "accessible-parent") == 0 ||
-      strcmp (pname, "accessible-role") == 0)
-    {
-      update_accessible (accessible);
-    }
-  /* Parent value us updated by child-add signal of parent object */
-  return TRUE;
-}
-
-static gboolean
-tree_update_property_listener (GSignalInvocationHint * signal_hint,
-                               guint n_param_values,
-                               const GValue * param_values, gpointer data)
-{
-  tree_update_wrapper (signal_hint, n_param_values, param_values, data,
-                       tree_update_property_action);
-  return TRUE;
-}
-
-static gboolean
-tree_update_children_action (GSignalInvocationHint * signal_hint,
-                             guint n_param_values,
-                             const GValue * param_values,
-                             gpointer data, AtkObject * accessible)
-{
-  const gchar *detail = NULL;
-  AtkObject *child;
-
-  if (signal_hint->detail)
-    detail = g_quark_to_string (signal_hint->detail);
-
-  if (!strcmp (detail, "add"))
-    {
-      gpointer child;
-      int index = g_value_get_uint (param_values + 1);
-      child = g_value_get_pointer (param_values + 2);
-
-      if (!ATK_IS_OBJECT (child))
-        {
-          child = atk_object_ref_accessible_child (accessible, index);
-#ifdef SPI_ATK_DEBUG
-          non_owned_accessible (child);
-#endif
-        }
-      register_subtree (child);
-      update_accessible (accessible);
-    }
-  else if (!strcmp (detail, "remove"))
-    {
-      update_accessible (accessible);
-    }
-  return TRUE;
+  return object_to_ref (gobj);
 }
-
-static gboolean
-tree_update_children_listener (GSignalInvocationHint * signal_hint,
-                               guint n_param_values,
-                               const GValue * param_values, gpointer data)
-{
-  tree_update_wrapper (signal_hint, n_param_values, param_values, data,
-                       tree_update_children_action);
-  return TRUE;
-}
-
-/*---------------------------------------------------------------------------*/
-
-static void
-spi_atk_register_toplevel_added (AtkObject * accessible,
-                                 guint index, AtkObject * child)
-{
-  g_static_rec_mutex_lock (&registration_mutex);
-
-  g_return_if_fail (ATK_IS_OBJECT (accessible));
-
-  if (object_to_ref (accessible))
-    {
-#ifdef SPI_ATK_DEBUG
-      if (recursion_check_and_set ())
-        g_warning ("AT-SPI: Recursive use of registration module");
-
-      g_debug ("AT-SPI: Toplevel added listener");
-#endif
-      if (!ATK_IS_OBJECT (child))
-        {
-          child = atk_object_ref_accessible_child (accessible, index);
-#ifdef SPI_ATK_DEBUG
-          non_owned_accessible (child);
-#endif
-        }
-      register_subtree (child);
-      update_accessible (accessible);
-
-      recursion_check_unset ();
-    }
-
-  g_static_rec_mutex_unlock (&registration_mutex);
-}
-
-static void
-spi_atk_register_toplevel_removed (AtkObject * accessible,
-                                   guint index, AtkObject * child)
-{
-  g_static_rec_mutex_lock (&registration_mutex);
-
-  g_return_if_fail (ATK_IS_OBJECT (accessible));
-
-  if (object_to_ref (accessible))
-    {
-#ifdef SPI_ATK_DEBUG
-      if (recursion_check_and_set ())
-        g_warning ("AT-SPI: Recursive use of registration module");
-
-      g_debug ("AT-SPI: Toplevel removed listener");
-#endif
-      update_accessible (accessible);
-      recursion_check_unset ();
-    }
-
-  g_static_rec_mutex_unlock (&registration_mutex);
-}
-
+  
 /*
- * Initializes required global data. The update and removal lists
- * and the reference lookup tables.
- *
- * Initializes all of the required D-Bus interfaces.
+ * Gets the path that indicates the accessible desktop object.
+ * This object is logically located on the registry daemon and not
+ * within any particular application.
  */
-void
-atk_dbus_initialize (AtkObject * root)
+gchar *
+spi_register_desktop_object_path ()
 {
-  if (!ref2ptr)
-    ref2ptr = g_hash_table_new (g_direct_hash, g_direct_equal);
-
-  if (!objects_with_subrefs)
-    objects_with_subrefs = g_hash_table_new (g_direct_hash, g_direct_equal);
-
-  if (!leased_refs)
-    leased_refs = g_hash_table_new (g_direct_hash, g_direct_equal);
-
-#ifdef SPI_ATK_DEBUG
-  if (g_thread_supported ())
-    g_message ("AT-SPI: Threads enabled");
-
-  g_debug ("AT-SPI: Initial Atk tree regisration");
-#endif
-
-  register_subtree (root);
-
-  atk_add_global_event_listener (tree_update_property_listener,
-                                 "Gtk:AtkObject:property-change");
-  atk_add_global_event_listener (tree_update_children_listener,
-                                 "Gtk:AtkObject:children-changed");
-  atk_add_global_event_listener (tree_update_state_listener,
-                                 "Gtk:AtkObject:state-change");
-
-  g_signal_connect (root,
-                    "children-changed::add",
-                    (GCallback) spi_atk_register_toplevel_added, NULL);
-  g_signal_connect (root,
-                    "children-changed::remove",
-                    (GCallback) spi_atk_register_toplevel_removed, NULL);
+  return g_strdup (SPI_ATK_OBJECT_PATH_PREFIX SPI_ATK_OBJECT_PATH_DESKTOP);
 }
 
 /*END------------------------------------------------------------------------*/
diff --git a/atk-adaptor/accessible-register.h b/atk-adaptor/accessible-register.h
index fe1912d..dda103b 100644
--- a/atk-adaptor/accessible-register.h
+++ b/atk-adaptor/accessible-register.h
@@ -21,31 +21,57 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#ifndef ACCESSIBLE_REGISTER
-#define ACCESSIBLE_REGISTER
+#ifndef ACCESSIBLE_REGISTER_H
+#define ACCESSIBLE_REGISTER_H
 
-#include <atk/atk.h>
 #include <glib.h>
+#include <glib-object.h>
 
-void atk_dbus_foreach_registered (GHFunc func, gpointer data);
+typedef struct _SpiRegister SpiRegister;
+typedef struct _SpiRegisterClass SpiRegisterClass;
 
-/*---------------------------------------------------------------------------*/
+G_BEGIN_DECLS
+
+#define SPI_REGISTER_TYPE        (spi_register_get_type ())
+#define SPI_REGISTER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), SPI_REGISTER_TYPE, SpiRegister))
+#define SPI_REGISTER_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), SPI_REGISTER_TYPE, SpiRegisterClass))
+#define SPI_IS_REGISTER(o)       (G_TYPE_CHECK__INSTANCE_TYPE ((o), SPI_REGISTER_TYPE))
+#define SPI_IS_REGISTER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SPI_REGISTER_TYPE))
+
+struct _SpiRegister
+{
+  GObject parent;
+
+  GHashTable * ref2ptr;
+  guint reference_counter;
+};
 
-GObject *atk_dbus_path_to_gobject (const char *path);
+struct _SpiRegisterClass
+{
+  GObjectClass parent_class;
+};
 
-AtkObject *atk_dbus_path_to_object (const char *path);
+GType spi_register_get_type (void);
 
-gchar *atk_dbus_object_attempt_registration (AtkObject * accessible);
+extern SpiRegister *spi_global_register;
 
-gchar *atk_dbus_object_to_path (AtkObject * accessible, gboolean do_register);
+/*---------------------------------------------------------------------------*/
+
+GObject *
+spi_register_path_to_object (SpiRegister * reg, const char *path);
 
-gchar *atk_dbus_sub_object_to_path (GObject * accessible,
-                                    GObject * container);
+GObject *
+spi_global_register_path_to_object (const char * path);
 
-gchar *atk_dbus_hyperlink_to_path (AtkHyperlink * hyperlink,
-                                   AtkObject * container);
+gchar *
+spi_register_object_to_path (SpiRegister * reg, GObject * gobj);
 
-gchar *atk_dbus_desktop_object_path ();
+guint
+spi_register_object_to_ref (GObject * gobj);
+  
+gchar *
+spi_register_desktop_object_path ();
+
+/*---------------------------------------------------------------------------*/
 
-gchar *atk_dbus_ref_to_path (guint ref);
-#endif /* ACCESSIBLE_REGISTER */
+#endif /* ACCESSIBLE_REGISTER_H */
diff --git a/atk-adaptor/adaptors/Makefile.am b/atk-adaptor/adaptors/Makefile.am
index d130c80..e3f5cf9 100644
--- a/atk-adaptor/adaptors/Makefile.am
+++ b/atk-adaptor/adaptors/Makefile.am
@@ -14,11 +14,10 @@ libatk_bridge_adaptors_la_LIBADD =\
 
 libatk_bridge_adaptors_la_SOURCES =\
 	accessible-adaptor.c	\
-	accessible-marshaller.c	\
-	accessible-marshaller.h	\
 	action-adaptor.c	\
 	adaptors.h		\
 	application-adaptor.c	\
+	cache-adaptor.c		\
 	collection-adaptor.c	\
 	component-adaptor.c	\
 	document-adaptor.c	\
@@ -29,6 +28,4 @@ libatk_bridge_adaptors_la_SOURCES =\
 	selection-adaptor.c	\
 	table-adaptor.c		\
 	text-adaptor.c		\
-	tree-adaptor.c		\
-	tree-adaptor.h		\
 	value-adaptor.c
diff --git a/atk-adaptor/adaptors/accessible-adaptor.c b/atk-adaptor/adaptors/accessible-adaptor.c
index 434223e..6359fa7 100644
--- a/atk-adaptor/adaptors/accessible-adaptor.c
+++ b/atk-adaptor/adaptors/accessible-adaptor.c
@@ -27,8 +27,7 @@
 
 #include "common/spi-dbus.h"
 #include "common/spi-stateset.h"
-#include "accessible-marshaller.h"
-#include "accessible-register.h"
+#include "object.h"
 
 static dbus_bool_t
 impl_get_Name (DBusMessageIter * iter, void *user_data)
@@ -81,8 +80,8 @@ impl_get_Parent (DBusMessageIter * iter, void *user_data)
 
   g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
 
-  return spi_dbus_return_v_object (iter,
-                                   atk_object_get_parent (object), FALSE);
+  spi_object_append_v_reference (iter, atk_object_get_parent (object));
+  return TRUE;
 }
 
 static dbus_bool_t
@@ -115,7 +114,7 @@ impl_GetChildAtIndex (DBusConnection * bus,
       return droute_invalid_arguments_error (message);
     }
   child = atk_object_ref_accessible_child (object, i);
-  return spi_dbus_return_object (message, child, TRUE, TRUE);
+  return spi_object_return_reference (message, child);
 }
 
 static DBusMessage *
@@ -136,18 +135,12 @@ impl_GetChildren (DBusConnection * bus,
     goto oom;
   dbus_message_iter_init_append (reply, &iter);
   if (!dbus_message_iter_open_container
-      (&iter, DBUS_TYPE_ARRAY, "o", &iter_array))
+      (&iter, DBUS_TYPE_ARRAY, "(so)", &iter_array))
     goto oom;
   for (i = 0; i < count; i++)
     {
       AtkObject *child = atk_object_ref_accessible_child (object, i);
-      char *path = atk_dbus_object_to_path (child, FALSE);
-      if (path)
-        {
-          dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_OBJECT_PATH,
-                                          &path);
-          g_free (path);
-        }
+      spi_object_append_reference (&iter_array, child); 
       if (child)
         g_object_unref (child);
     }
@@ -169,13 +162,10 @@ impl_GetIndexInParent (DBusConnection * bus,
 
   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
                         droute_not_yet_handled_error (message));
+
   rv = atk_object_get_index_in_parent (object);
   reply = dbus_message_new_method_return (message);
-  if (reply)
-    {
-      dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
-                                DBUS_TYPE_INVALID);
-    }
+  dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv, DBUS_TYPE_INVALID);
   return reply;
 }
 
@@ -278,13 +268,7 @@ impl_GetRelationSet (DBusConnection * bus,
           char *path;
           if (!obj)
             continue;
-          path = atk_dbus_object_to_path (obj, FALSE);
-          if (!path)
-            {
-              g_warning ("Unknown object in relation type %d\n", type);
-              continue;
-            }
-          spi_dbus_append_name_and_path_inner (&iter_targets, NULL, path);
+          spi_object_append_reference (&iter_targets, obj);
         }
       dbus_message_iter_close_container (&iter_struct, &iter_targets);
       dbus_message_iter_close_container (&iter_array, &iter_struct);
@@ -295,133 +279,6 @@ oom:
   return reply;
 }
 
-static gboolean
-spi_init_role_lookup_table (Accessibility_Role * role_table)
-{
-  int i;
-  /* if it's not in the list below, dunno what it is */
-  for (i = 0; i < ATK_ROLE_LAST_DEFINED; ++i)
-    {
-      role_table[i] = Accessibility_ROLE_UNKNOWN;
-    }
-
-  role_table[ATK_ROLE_INVALID] = Accessibility_ROLE_INVALID;
-  role_table[ATK_ROLE_ACCEL_LABEL] = Accessibility_ROLE_ACCELERATOR_LABEL;
-  role_table[ATK_ROLE_ALERT] = Accessibility_ROLE_ALERT;
-  role_table[ATK_ROLE_ANIMATION] = Accessibility_ROLE_ANIMATION;
-  role_table[ATK_ROLE_ARROW] = Accessibility_ROLE_ARROW;
-  role_table[ATK_ROLE_CALENDAR] = Accessibility_ROLE_CALENDAR;
-  role_table[ATK_ROLE_CANVAS] = Accessibility_ROLE_CANVAS;
-  role_table[ATK_ROLE_CHECK_BOX] = Accessibility_ROLE_CHECK_BOX;
-  role_table[ATK_ROLE_CHECK_MENU_ITEM] = Accessibility_ROLE_CHECK_MENU_ITEM;
-  role_table[ATK_ROLE_COLOR_CHOOSER] = Accessibility_ROLE_COLOR_CHOOSER;
-  role_table[ATK_ROLE_COLUMN_HEADER] = Accessibility_ROLE_COLUMN_HEADER;
-  role_table[ATK_ROLE_COMBO_BOX] = Accessibility_ROLE_COMBO_BOX;
-  role_table[ATK_ROLE_DATE_EDITOR] = Accessibility_ROLE_DATE_EDITOR;
-  role_table[ATK_ROLE_DESKTOP_ICON] = Accessibility_ROLE_DESKTOP_ICON;
-  role_table[ATK_ROLE_DESKTOP_FRAME] = Accessibility_ROLE_DESKTOP_FRAME;
-  role_table[ATK_ROLE_DIAL] = Accessibility_ROLE_DIAL;
-  role_table[ATK_ROLE_DIALOG] = Accessibility_ROLE_DIALOG;
-  role_table[ATK_ROLE_DIRECTORY_PANE] = Accessibility_ROLE_DIRECTORY_PANE;
-  role_table[ATK_ROLE_DRAWING_AREA] = Accessibility_ROLE_DRAWING_AREA;
-  role_table[ATK_ROLE_FILE_CHOOSER] = Accessibility_ROLE_FILE_CHOOSER;
-  role_table[ATK_ROLE_FILLER] = Accessibility_ROLE_FILLER;
-  role_table[ATK_ROLE_FONT_CHOOSER] = Accessibility_ROLE_FONT_CHOOSER;
-  role_table[ATK_ROLE_FRAME] = Accessibility_ROLE_FRAME;
-  role_table[ATK_ROLE_GLASS_PANE] = Accessibility_ROLE_GLASS_PANE;
-  role_table[ATK_ROLE_HTML_CONTAINER] = Accessibility_ROLE_HTML_CONTAINER;
-  role_table[ATK_ROLE_ICON] = Accessibility_ROLE_ICON;
-  role_table[ATK_ROLE_IMAGE] = Accessibility_ROLE_IMAGE;
-  role_table[ATK_ROLE_INTERNAL_FRAME] = Accessibility_ROLE_INTERNAL_FRAME;
-  role_table[ATK_ROLE_LABEL] = Accessibility_ROLE_LABEL;
-  role_table[ATK_ROLE_LAYERED_PANE] = Accessibility_ROLE_LAYERED_PANE;
-  role_table[ATK_ROLE_LIST] = Accessibility_ROLE_LIST;
-  role_table[ATK_ROLE_LIST_ITEM] = Accessibility_ROLE_LIST_ITEM;
-  role_table[ATK_ROLE_MENU] = Accessibility_ROLE_MENU;
-  role_table[ATK_ROLE_MENU_BAR] = Accessibility_ROLE_MENU_BAR;
-  role_table[ATK_ROLE_MENU_ITEM] = Accessibility_ROLE_MENU_ITEM;
-  role_table[ATK_ROLE_OPTION_PANE] = Accessibility_ROLE_OPTION_PANE;
-  role_table[ATK_ROLE_PAGE_TAB] = Accessibility_ROLE_PAGE_TAB;
-  role_table[ATK_ROLE_PAGE_TAB_LIST] = Accessibility_ROLE_PAGE_TAB_LIST;
-  role_table[ATK_ROLE_PANEL] = Accessibility_ROLE_PANEL;
-  role_table[ATK_ROLE_PASSWORD_TEXT] = Accessibility_ROLE_PASSWORD_TEXT;
-  role_table[ATK_ROLE_POPUP_MENU] = Accessibility_ROLE_POPUP_MENU;
-  role_table[ATK_ROLE_PROGRESS_BAR] = Accessibility_ROLE_PROGRESS_BAR;
-  role_table[ATK_ROLE_PUSH_BUTTON] = Accessibility_ROLE_PUSH_BUTTON;
-  role_table[ATK_ROLE_RADIO_BUTTON] = Accessibility_ROLE_RADIO_BUTTON;
-  role_table[ATK_ROLE_RADIO_MENU_ITEM] = Accessibility_ROLE_RADIO_MENU_ITEM;
-  role_table[ATK_ROLE_ROOT_PANE] = Accessibility_ROLE_ROOT_PANE;
-  role_table[ATK_ROLE_ROW_HEADER] = Accessibility_ROLE_ROW_HEADER;
-  role_table[ATK_ROLE_SCROLL_BAR] = Accessibility_ROLE_SCROLL_BAR;
-  role_table[ATK_ROLE_SCROLL_PANE] = Accessibility_ROLE_SCROLL_PANE;
-  role_table[ATK_ROLE_SEPARATOR] = Accessibility_ROLE_SEPARATOR;
-  role_table[ATK_ROLE_SLIDER] = Accessibility_ROLE_SLIDER;
-  role_table[ATK_ROLE_SPIN_BUTTON] = Accessibility_ROLE_SPIN_BUTTON;
-  role_table[ATK_ROLE_SPLIT_PANE] = Accessibility_ROLE_SPLIT_PANE;
-  role_table[ATK_ROLE_STATUSBAR] = Accessibility_ROLE_STATUS_BAR;
-  role_table[ATK_ROLE_TABLE] = Accessibility_ROLE_TABLE;
-  role_table[ATK_ROLE_TABLE_CELL] = Accessibility_ROLE_TABLE_CELL;
-  role_table[ATK_ROLE_TABLE_COLUMN_HEADER] =
-    Accessibility_ROLE_TABLE_COLUMN_HEADER;
-  role_table[ATK_ROLE_TABLE_ROW_HEADER] = Accessibility_ROLE_TABLE_ROW_HEADER;
-  role_table[ATK_ROLE_TEAR_OFF_MENU_ITEM] =
-    Accessibility_ROLE_TEAROFF_MENU_ITEM;
-  role_table[ATK_ROLE_TERMINAL] = Accessibility_ROLE_TERMINAL;
-  role_table[ATK_ROLE_TEXT] = Accessibility_ROLE_TEXT;
-  role_table[ATK_ROLE_TOGGLE_BUTTON] = Accessibility_ROLE_TOGGLE_BUTTON;
-  role_table[ATK_ROLE_TOOL_BAR] = Accessibility_ROLE_TOOL_BAR;
-  role_table[ATK_ROLE_TOOL_TIP] = Accessibility_ROLE_TOOL_TIP;
-  role_table[ATK_ROLE_TREE] = Accessibility_ROLE_TREE;
-  role_table[ATK_ROLE_TREE_TABLE] = Accessibility_ROLE_TREE_TABLE;
-  role_table[ATK_ROLE_UNKNOWN] = Accessibility_ROLE_UNKNOWN;
-  role_table[ATK_ROLE_VIEWPORT] = Accessibility_ROLE_VIEWPORT;
-  role_table[ATK_ROLE_WINDOW] = Accessibility_ROLE_WINDOW;
-  role_table[ATK_ROLE_HEADER] = Accessibility_ROLE_HEADER;
-  role_table[ATK_ROLE_FOOTER] = Accessibility_ROLE_FOOTER;
-  role_table[ATK_ROLE_PARAGRAPH] = Accessibility_ROLE_PARAGRAPH;
-  role_table[ATK_ROLE_RULER] = Accessibility_ROLE_RULER;
-  role_table[ATK_ROLE_APPLICATION] = Accessibility_ROLE_APPLICATION;
-  role_table[ATK_ROLE_AUTOCOMPLETE] = Accessibility_ROLE_AUTOCOMPLETE;
-  role_table[ATK_ROLE_EDITBAR] = Accessibility_ROLE_EDITBAR;
-  role_table[ATK_ROLE_EMBEDDED] = Accessibility_ROLE_EMBEDDED;
-  role_table[ATK_ROLE_ENTRY] = Accessibility_ROLE_ENTRY;
-  role_table[ATK_ROLE_CHART] = Accessibility_ROLE_CHART;
-  role_table[ATK_ROLE_CAPTION] = Accessibility_ROLE_CAPTION;
-  role_table[ATK_ROLE_DOCUMENT_FRAME] = Accessibility_ROLE_DOCUMENT_FRAME;
-  role_table[ATK_ROLE_HEADING] = Accessibility_ROLE_HEADING;
-  role_table[ATK_ROLE_PAGE] = Accessibility_ROLE_PAGE;
-  role_table[ATK_ROLE_SECTION] = Accessibility_ROLE_SECTION;
-  role_table[ATK_ROLE_FORM] = Accessibility_ROLE_FORM;
-  role_table[ATK_ROLE_REDUNDANT_OBJECT] = Accessibility_ROLE_REDUNDANT_OBJECT;
-  role_table[ATK_ROLE_LINK] = Accessibility_ROLE_LINK;
-  role_table[ATK_ROLE_INPUT_METHOD_WINDOW] =
-    Accessibility_ROLE_INPUT_METHOD_WINDOW;
-  return TRUE;
-}
-
-Accessibility_Role
-spi_accessible_role_from_atk_role (AtkRole role)
-{
-  static gboolean is_initialized = FALSE;
-  static Accessibility_Role spi_role_table[ATK_ROLE_LAST_DEFINED];
-  Accessibility_Role spi_role;
-
-  if (!is_initialized)
-    {
-      is_initialized = spi_init_role_lookup_table (spi_role_table);
-    }
-
-  if (role >= 0 && role < ATK_ROLE_LAST_DEFINED)
-    {
-      spi_role = spi_role_table[role];
-    }
-  else
-    {
-      spi_role = Accessibility_ROLE_EXTENDED;
-    }
-  return spi_role;
-}
-
 static DBusMessage *
 impl_GetRole (DBusConnection * bus, DBusMessage * message, void *user_data)
 {
@@ -534,9 +391,8 @@ impl_GetAttributes (DBusConnection * bus,
                     DBusMessage * message, void *user_data)
 {
   AtkObject *object = (AtkObject *) user_data;
-  DBusMessage *reply = NULL;
-
   AtkAttributeSet *attributes;
+  DBusMessage *reply = NULL;
   DBusMessageIter iter;
 
   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
@@ -546,10 +402,9 @@ impl_GetAttributes (DBusConnection * bus,
 
   reply = dbus_message_new_method_return (message);
   dbus_message_iter_init_append (reply, &iter);
-  spi_atk_append_attribute_set (&iter, attributes);
+  spi_object_append_attribute_set (&iter, attributes);
 
-  if (attributes)
-    atk_attribute_set_free (attributes);
+  atk_attribute_set_free (attributes);
 
   return reply;
 }
@@ -559,7 +414,7 @@ impl_GetApplication (DBusConnection * bus,
                      DBusMessage * message, void *user_data)
 {
   AtkObject *root = atk_get_root ();
-  return spi_dbus_return_object (message, root, FALSE, FALSE);
+  return spi_object_return_reference (message, root);
 }
 
 static DBusMessage *
@@ -580,7 +435,7 @@ impl_GetInterfaces (DBusConnection * bus,
       dbus_message_iter_init_append (reply, &iter);
       dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s",
                                         &iter_array);
-      append_atk_object_interfaces (object, &iter_array);
+      spi_object_append_interfaces (&iter_array, object);
       dbus_message_iter_close_container (&iter, &iter_array);
     }
   return reply;
diff --git a/atk-adaptor/adaptors/adaptors.h b/atk-adaptor/adaptors/adaptors.h
index 7f8bdd9..ccc07ab 100644
--- a/atk-adaptor/adaptors/adaptors.h
+++ b/atk-adaptor/adaptors/adaptors.h
@@ -43,6 +43,6 @@ void spi_initialize_selection (DRoutePath * path);
 void spi_initialize_table (DRoutePath * path);
 void spi_initialize_text (DRoutePath * path);
 void spi_initialize_value (DRoutePath * path);
-void spi_initialize_tree (DRoutePath * path);
+void spi_initialize_cache (DRoutePath * path);
 
 #endif /* ADAPTORS_H */
diff --git a/atk-adaptor/adaptors/cache-adaptor.c b/atk-adaptor/adaptors/cache-adaptor.c
new file mode 100644
index 0000000..45eb41b
--- /dev/null
+++ b/atk-adaptor/adaptors/cache-adaptor.c
@@ -0,0 +1,301 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2008 Novell, Inc.
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2008, 2009 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+
+#include <atk/atk.h>
+#include <droute/droute.h>
+
+#include "common/spi-dbus.h"
+#include "accessible-cache.h"
+#include "bridge.h"
+#include "object.h"
+
+/* TODO - This should possibly be a common define */
+#define SPI_OBJECT_PREFIX "/org/at_spi"
+#define SPI_CACHE_OBJECT_SUFFIX "/cache"
+#define SPI_CACHE_OBJECT_PATH SPI_OBJECT_PREFIX SPI_CACHE_OBJECT_SUFFIX
+
+#define SPI_OBJECT_REFERENCE_SIGNATURE "(" \
+                                          DBUS_TYPE_STRING_AS_STRING \
+                                          DBUS_TYPE_OBJECT_PATH_AS_STRING \
+                                       ")"
+                                          
+#define SPI_CACHE_ITEM_SIGNATURE "(" \
+                                   DBUS_TYPE_OBJECT_PATH_AS_STRING \
+                                   SPI_OBJECT_REFERENCE_SIGNATURE \
+                                   SPI_OBJECT_REFERENCE_SIGNATURE \
+                                   DBUS_TYPE_ARRAY_AS_STRING \
+                                     SPI_OBJECT_REFERENCE_SIGNATURE \
+                                   DBUS_TYPE_ARRAY_AS_STRING \
+                                     DBUS_TYPE_STRING_AS_STRING \
+                                   DBUS_TYPE_STRING_AS_STRING \
+                                   DBUS_TYPE_UINT32_AS_STRING \
+                                   DBUS_TYPE_STRING_AS_STRING \
+                                   DBUS_TYPE_ARRAY_AS_STRING \
+                                     DBUS_TYPE_UINT32_AS_STRING \
+                                 ")"
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ * Marshals the given AtkObject into the provided D-Bus iterator.
+ *
+ * The object is marshalled including all its client side cache data.
+ * The format of the structure is (o(so)a(so)assusau).
+ */
+static void
+append_cache_item (AtkObject * obj, gpointer data)
+{
+  DBusMessageIter iter_struct, iter_sub_array;
+  dbus_uint32_t states[2];
+  int count;
+  AtkStateSet *set;
+  DBusMessageIter *iter_array = (DBusMessageIter *) data;
+
+  const char *name, *desc;
+  dbus_uint32_t role;
+
+  set = atk_object_ref_state_set (obj);
+  {
+    AtkObject *application, *parent;
+
+    dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL,
+                                      &iter_struct);
+
+    /* Marshall object path */
+    spi_object_append_reference (&iter_struct, obj);
+
+    role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));
+
+    /* Marshall application */
+    application = spi_global_app_data->root; 
+    spi_object_append_reference (&iter_struct, application);
+
+    /* Marshall parent */
+    parent = atk_object_get_parent (obj);
+    if (parent == NULL)
+      {
+        /* TODO: Support getting parent of an AtkPlug */
+#ifdef __ATK_PLUG_H__
+        if (role != Accessibility_ROLE_APPLICATION && !ATK_IS_PLUG (obj))
+#else
+        if (role != Accessibility_ROLE_APPLICATION)
+#endif
+          spi_object_append_null_reference (&iter_struct);
+        else
+          spi_object_append_desktop_reference (&iter_struct);
+      }
+    else
+      {
+        spi_object_append_reference (&iter_struct, parent);
+      }
+
+    /* Marshall children */
+    dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "(so)",
+                                      &iter_sub_array);
+    if (!atk_state_set_contains_state (set, ATK_STATE_MANAGES_DESCENDANTS))
+      {
+        gint childcount, i;
+
+        childcount = atk_object_get_n_accessible_children (obj);
+        for (i = 0; i < childcount; i++)
+          {
+            AtkObject *child;
+            gchar *child_path;
+
+            child = atk_object_ref_accessible_child (obj, i);
+            spi_object_append_reference (&iter_sub_array, child);
+            g_object_unref (G_OBJECT (child));
+          }
+      }
+#ifdef __ATK_PLUG_H__
+    if (ATK_IS_SOCKET (obj) && atk_socket_is_occupied (ATK_SOCKET (obj)))
+      {
+        AtkSocket *socket = ATK_SOCKET (obj);
+        gchar *child_name, *child_path;
+        child_name = g_strdup (socket->embedded_plug_id);
+        child_path = g_utf8_strchr (child_name + 1, -1, ':');
+        if (child_path)
+          {
+            DBusMessageIter iter_socket;
+            *(child_path++) = '\0';
+            dbus_message_iter_open_container (&iter_sub_array, DBUS_TYPE_STRUCT, NULL,
+                                              &iter_socket);
+            dbus_message_iter_append_basic (&iter_socket, DBUS_TYPE_STRING, &name);
+            dbus_message_iter_append_basic (&iter_socket, DBUS_TYPE_OBJECT_PATH, &path);
+            dbus_message_iter_close_container (&iter_sub_array, &iter_socket);
+          }
+        g_free (child_name);
+      }
+#endif
+
+    dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
+
+    /* Marshall interfaces */
+    dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s",
+                                      &iter_sub_array);
+    spi_object_append_interfaces (&iter_sub_array, obj);
+    dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
+
+    /* Marshall name */
+    name = atk_object_get_name (obj);
+    if (!name)
+      name = "";
+    dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
+
+    /* Marshall role */
+    dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role);
+
+    /* Marshall description */
+    desc = atk_object_get_description (obj);
+    if (!desc)
+      desc = "";
+    dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &desc);
+
+    /* Marshall state set */
+    spi_atk_state_set_to_dbus_array (set, states);
+    dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "u",
+                                      &iter_sub_array);
+    for (count = 0; count < 2; count++)
+      {
+        dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_UINT32,
+                                        &states[count]);
+      }
+    dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
+  }
+  dbus_message_iter_close_container (iter_array, &iter_struct);
+  g_object_unref (set);
+}
+
+/*---------------------------------------------------------------------------*/
+
+/* For use as a GHFunc */
+static void
+append_accessible_hf (gpointer key, gpointer obj_data, gpointer data)
+{
+  /* Make sure it isn't a hyperlink */
+  if (ATK_IS_OBJECT (obj_data))
+    append_cache_item (ATK_OBJECT (obj_data), data);
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void
+emit_cache_remove (SpiCache *cache, GObject * obj)
+{
+  DBusMessage *message;
+
+  if ((message = dbus_message_new_signal (SPI_CACHE_OBJECT_PATH,
+                                          SPI_DBUS_INTERFACE_CACHE,
+                                          "RemoveAccessible")))
+    {
+      DBusMessageIter iter;
+      gchar *path;
+
+      dbus_message_iter_init_append (message, &iter);
+
+      spi_object_append_reference (&iter, ATK_OBJECT (obj));
+
+      dbus_connection_send (spi_global_app_data->bus, message, NULL);
+
+      dbus_message_unref (message);
+    }
+}
+
+static void
+emit_cache_add (SpiCache *cache, GObject * obj)
+{
+  AtkObject *accessible = ATK_OBJECT (obj);
+  DBusMessage *message;
+
+  if ((message = dbus_message_new_signal (SPI_CACHE_OBJECT_PATH,
+                                          SPI_DBUS_INTERFACE_CACHE,
+                                          "AddAccessible")))
+    {
+      DBusMessageIter iter;
+
+      dbus_message_iter_init_append (message, &iter);
+      append_cache_item (accessible, &iter);
+
+      dbus_connection_send (spi_global_app_data->bus, message, NULL);
+
+      dbus_message_unref (message);
+    }
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+static DBusMessage *
+impl_GetRoot (DBusConnection * bus, DBusMessage * message, void *user_data)
+{
+  return spi_object_return_reference (message,
+                                      g_object_ref (G_OBJECT (spi_global_app_data->root)));
+}
+
+/*---------------------------------------------------------------------------*/
+
+static DBusMessage *
+impl_GetItems (DBusConnection * bus, DBusMessage * message, void *user_data)
+{
+  DBusMessage *reply;
+  DBusMessageIter iter, iter_array;
+
+  reply = dbus_message_new_method_return (message);
+
+  dbus_message_iter_init_append (reply, &iter);
+  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
+                                    SPI_CACHE_ITEM_SIGNATURE, &iter_array);
+  spi_cache_foreach (spi_global_cache, append_accessible_hf, &iter_array);
+  dbus_message_iter_close_container (&iter, &iter_array);
+  return reply;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static DRouteMethod methods[] = {
+  {impl_GetRoot, "GetRoot"},
+  {impl_GetItems, "GetItems"},
+  {NULL, NULL}
+};
+
+void
+spi_initialize_cache (DRoutePath * path)
+{
+  droute_path_add_interface (path, SPI_DBUS_INTERFACE_CACHE, methods, NULL);
+
+  g_signal_connect (spi_global_cache,
+                    "object-added",
+                    (GCallback) emit_cache_add,
+                    NULL);
+
+  g_signal_connect (spi_global_cache,
+                    "object-removed",
+                    (GCallback) emit_cache_remove,
+                    NULL);
+};
+
+/*END------------------------------------------------------------------------*/
diff --git a/atk-adaptor/adaptors/collection-adaptor.c b/atk-adaptor/adaptors/collection-adaptor.c
index e920545..1702ee7 100644
--- a/atk-adaptor/adaptors/collection-adaptor.c
+++ b/atk-adaptor/adaptors/collection-adaptor.c
@@ -27,13 +27,13 @@
 #include <atk/atk.h>
 #include <droute/droute.h>
 
-#include "accessible-register.h"
-#include "accessible-marshaller.h"
-
 #include "common/bitarray.h"
 #include "common/spi-dbus.h"
 #include "common/spi-stateset.h"
 
+#include "accessible-register.h"
+#include "object.h"
+
 typedef struct _MatchRulePrivate MatchRulePrivate;
 struct _MatchRulePrivate
 {
@@ -762,8 +762,7 @@ return_and_free_list (DBusMessage * message, GList * ls)
     goto oom;
   for (item = ls; item; item = g_list_next (item))
     {
-      spi_dbus_append_name_and_path (message, &iter_array,
-                                     ATK_OBJECT (item->data), TRUE, FALSE);
+      spi_object_append_reference (&iter_array, ATK_OBJECT (item->data));
     }
   if (!dbus_message_iter_close_container (&iter, &iter_array))
     goto oom;
@@ -871,7 +870,7 @@ GetMatchesInOrder (DBusMessage * message,
 
   ls = g_list_append (ls, current_object);
 
-  obj = atk_dbus_path_to_object (dbus_message_get_path (message));
+  obj = ATK_OBJECT(spi_register_path_to_object (spi_global_register, dbus_message_get_path (message)));
 
   kount = inorder (obj, mrp, ls, 0, count,
                    current_object, TRUE, NULL, traverse);
@@ -903,7 +902,7 @@ GetMatchesInBackOrder (DBusMessage * message,
 
   ls = g_list_append (ls, current_object);
 
-  collection = atk_dbus_path_to_object (dbus_message_get_path (message));
+  collection = ATK_OBJECT(spi_register_path_to_object (spi_global_register, dbus_message_get_path (message)));
 
   kount = sort_order_rev_canonical (mrp, ls, 0, count, current_object,
                                     FALSE, collection);
@@ -933,13 +932,13 @@ GetMatchesTo (DBusMessage * message,
 
   if (recurse)
     {
-      obj = atk_object_get_parent (current_object);
+      obj = ATK_OBJECT (atk_object_get_parent (current_object));
       kount = query_exec (mrp, sortby, ls, 0, count,
                           obj, 0, TRUE, current_object, TRUE, traverse);
     }
   else
     {
-      obj = atk_dbus_path_to_object (dbus_message_get_path (message));
+      obj = ATK_OBJECT (spi_register_path_to_object (spi_global_register, dbus_message_get_path (message)));
       kount = query_exec (mrp, sortby, ls, 0, count,
                           obj, 0, TRUE, current_object, TRUE, traverse);
 
@@ -978,7 +977,7 @@ impl_GetMatchesFrom (DBusConnection * bus, DBusMessage * message,
 
   dbus_message_iter_init (message, &iter);
   dbus_message_iter_get_basic (&iter, &current_object_path);
-  current_object = atk_dbus_path_to_object (current_object_path);
+  current_object = ATK_OBJECT (spi_register_path_to_object (spi_global_register, current_object_path));
   if (!current_object)
     {
       // TODO: object-not-found error
@@ -1042,7 +1041,7 @@ impl_GetMatchesTo (DBusConnection * bus, DBusMessage * message,
 
   dbus_message_iter_init (message, &iter);
   dbus_message_iter_get_basic (&iter, &current_object_path);
-  current_object = atk_dbus_path_to_object (current_object_path);
+  current_object = ATK_OBJECT (spi_register_path_to_object (spi_global_register, current_object_path));
   if (!current_object)
     {
       // TODO: object-not-found error
@@ -1086,7 +1085,7 @@ impl_GetMatchesTo (DBusConnection * bus, DBusMessage * message,
 static DBusMessage *
 impl_GetMatches (DBusConnection * bus, DBusMessage * message, void *user_data)
 {
-  AtkObject *obj = atk_dbus_path_to_object (dbus_message_get_path (message));
+  AtkObject *obj = ATK_OBJECT (spi_register_path_to_object (spi_global_register, dbus_message_get_path (message)));
   DBusMessageIter iter;
   MatchRulePrivate rule;
   dbus_uint32_t sortby;
diff --git a/atk-adaptor/adaptors/component-adaptor.c b/atk-adaptor/adaptors/component-adaptor.c
index 40f8360..a3810de 100644
--- a/atk-adaptor/adaptors/component-adaptor.c
+++ b/atk-adaptor/adaptors/component-adaptor.c
@@ -25,8 +25,8 @@
 #include <atk/atk.h>
 #include <droute/droute.h>
 
-#include "accessible-marshaller.h"
 #include "common/spi-dbus.h"
+#include "object.h"
 
 static DBusMessage *
 impl_contains (DBusConnection * bus, DBusMessage * message, void *user_data)
@@ -82,7 +82,7 @@ impl_GetAccessibleAtPoint (DBusConnection * bus, DBusMessage * message,
   child =
     atk_component_ref_accessible_at_point (component, x, y,
                                            (AtkCoordType) coord_type);
-  return spi_dbus_return_object (message, child, TRUE, TRUE);
+  return spi_object_return_reference (message, child);
 }
 
 static DBusMessage *
diff --git a/atk-adaptor/adaptors/document-adaptor.c b/atk-adaptor/adaptors/document-adaptor.c
index de83a0d..dc3f628 100644
--- a/atk-adaptor/adaptors/document-adaptor.c
+++ b/atk-adaptor/adaptors/document-adaptor.c
@@ -26,8 +26,7 @@
 #include <droute/droute.h>
 
 #include "common/spi-dbus.h"
-
-#include "accessible-marshaller.h"
+#include "object.h"
 
 static DBusMessage *
 impl_GetLocale (DBusConnection * bus, DBusMessage * message, void *user_data)
diff --git a/atk-adaptor/adaptors/hyperlink-adaptor.c b/atk-adaptor/adaptors/hyperlink-adaptor.c
index 75521ed..732ab2b 100644
--- a/atk-adaptor/adaptors/hyperlink-adaptor.c
+++ b/atk-adaptor/adaptors/hyperlink-adaptor.c
@@ -25,8 +25,8 @@
 #include <atk/atk.h>
 #include <droute/droute.h>
 
-#include "accessible-marshaller.h"
 #include "common/spi-dbus.h"
+#include "object.h"
 
 static AtkHyperlink *
 get_hyperlink (void *user_data)
@@ -80,8 +80,7 @@ impl_GetObject (DBusConnection * bus, DBusMessage * message, void *user_data)
       return droute_invalid_arguments_error (message);
     }
   atk_object = atk_hyperlink_get_object (link, i);
-  return spi_dbus_return_sub_object (message, G_OBJECT (atk_object),
-                                     G_OBJECT (link), FALSE);
+  return spi_object_return_reference (message, atk_object);
 }
 
 static DBusMessage *
diff --git a/atk-adaptor/adaptors/hypertext-adaptor.c b/atk-adaptor/adaptors/hypertext-adaptor.c
index 082dde3..0bb4060 100644
--- a/atk-adaptor/adaptors/hypertext-adaptor.c
+++ b/atk-adaptor/adaptors/hypertext-adaptor.c
@@ -26,7 +26,7 @@
 #include <droute/droute.h>
 
 #include "common/spi-dbus.h"
-#include "accessible-marshaller.h"
+#include "object.h"
 
 static DBusMessage *
 impl_GetNLinks (DBusConnection * bus, DBusMessage * message, void *user_data)
@@ -64,8 +64,7 @@ impl_GetLink (DBusConnection * bus, DBusMessage * message, void *user_data)
       return droute_invalid_arguments_error (message);
     }
   link = atk_hypertext_get_link (hypertext, linkIndex);
-  return spi_dbus_return_hyperlink (message, link, ATK_OBJECT (hypertext),
-                                    TRUE);
+  return spi_object_return_reference (message, ATK_OBJECT (hypertext));
 }
 
 static DBusMessage *
diff --git a/atk-adaptor/adaptors/image-adaptor.c b/atk-adaptor/adaptors/image-adaptor.c
index 1ed7b24..c2e00b0 100644
--- a/atk-adaptor/adaptors/image-adaptor.c
+++ b/atk-adaptor/adaptors/image-adaptor.c
@@ -26,6 +26,7 @@
 #include <droute/droute.h>
 
 #include "common/spi-dbus.h"
+#include "object.h"
 
 static dbus_bool_t
 impl_get_ImageDescription (DBusMessageIter * iter, void *user_data)
diff --git a/atk-adaptor/adaptors/selection-adaptor.c b/atk-adaptor/adaptors/selection-adaptor.c
index 4516b52..02e28f2 100644
--- a/atk-adaptor/adaptors/selection-adaptor.c
+++ b/atk-adaptor/adaptors/selection-adaptor.c
@@ -26,7 +26,7 @@
 #include <droute/droute.h>
 
 #include "common/spi-dbus.h"
-#include "accessible-marshaller.h"
+#include "object.h"
 
 static dbus_bool_t
 impl_get_NSelectedChildren (DBusMessageIter * iter, void *user_data)
@@ -66,7 +66,7 @@ impl_GetSelectedChild (DBusConnection * bus, DBusMessage * message,
       return droute_invalid_arguments_error (message);
     }
   atk_object = atk_selection_ref_selection (selection, selectedChildIndex);
-  return spi_dbus_return_object (message, atk_object, TRUE, TRUE);
+  return spi_object_return_reference (message, atk_object);
 }
 
 static DBusMessage *
diff --git a/atk-adaptor/adaptors/table-adaptor.c b/atk-adaptor/adaptors/table-adaptor.c
index 212004a..b61caa2 100644
--- a/atk-adaptor/adaptors/table-adaptor.c
+++ b/atk-adaptor/adaptors/table-adaptor.c
@@ -25,8 +25,8 @@
 #include <atk/atk.h>
 #include <droute/droute.h>
 
-#include "accessible-marshaller.h"
 #include "common/spi-dbus.h"
+#include "object.h"
 
 static dbus_bool_t
 impl_get_NRows (DBusMessageIter * iter, void *user_data)
@@ -49,8 +49,8 @@ impl_get_Caption (DBusMessageIter * iter, void *user_data)
 {
   AtkTable *table = (AtkTable *) user_data;
   g_return_val_if_fail (ATK_IS_TABLE (user_data), FALSE);
-  return spi_dbus_return_v_object (iter, atk_table_get_caption (table),
-                                   FALSE);
+  spi_object_append_v_reference (iter, atk_table_get_caption (table));
+  return TRUE;
 }
 
 static dbus_bool_t
@@ -58,8 +58,8 @@ impl_get_Summary (DBusMessageIter * iter, void *user_data)
 {
   AtkTable *table = (AtkTable *) user_data;
   g_return_val_if_fail (ATK_IS_TABLE (user_data), FALSE);
-  return spi_dbus_return_v_object (iter, atk_table_get_summary (table),
-                                   FALSE);
+  spi_object_append_v_reference (iter, atk_table_get_summary (table));
+  return TRUE;
 }
 
 static dbus_bool_t
@@ -107,7 +107,7 @@ impl_GetAccessibleAt (DBusConnection * bus, DBusMessage * message,
       return droute_invalid_arguments_error (message);
     }
   obj = atk_table_ref_at (table, row, column);
-  return spi_dbus_return_object (message, obj, TRUE, TRUE);
+  return spi_object_return_reference (message, obj);
 }
 
 static DBusMessage *
@@ -331,7 +331,7 @@ impl_GetRowHeader (DBusConnection * bus, DBusMessage * message,
     }
   obj = atk_table_get_row_header (table, row);
   obj = atk_table_get_row_header (table, row);
-  return spi_dbus_return_object (message, obj, TRUE, FALSE);
+  return spi_object_return_reference (message, obj);
 }
 
 static DBusMessage *
@@ -353,7 +353,7 @@ impl_GetColumnHeader (DBusConnection * bus, DBusMessage * message,
     }
   obj = atk_table_get_column_header (table, column);
   obj = atk_table_get_column_header (table, column);
-  return spi_dbus_return_object (message, obj, TRUE, FALSE);
+  return spi_object_return_reference (message, obj);
 }
 
 static DBusMessage *
diff --git a/atk-adaptor/adaptors/text-adaptor.c b/atk-adaptor/adaptors/text-adaptor.c
index a15f9c7..dc20a80 100644
--- a/atk-adaptor/adaptors/text-adaptor.c
+++ b/atk-adaptor/adaptors/text-adaptor.c
@@ -28,8 +28,7 @@
 #include <droute/droute.h>
 
 #include "common/spi-dbus.h"
-
-#include "accessible-marshaller.h"
+#include "object.h"
 
 static dbus_bool_t
 impl_get_CharacterCount (DBusMessageIter * iter, void *user_data)
@@ -735,7 +734,7 @@ impl_GetAttributeRun (DBusConnection * bus, DBusMessage * message,
   dbus_int32_t startOffset, endOffset;
   gint intstart_offset = 0, intend_offset = 0;
   DBusMessage *reply;
-  AtkAttributeSet *attributes, *default_attributes = NULL;
+  AtkAttributeSet *attributes = NULL;
   AtkAttribute *attr = NULL;
   DBusMessageIter iter, iterArray;
 
@@ -753,20 +752,18 @@ impl_GetAttributeRun (DBusConnection * bus, DBusMessage * message,
     atk_text_get_run_attributes (text, offset, &intstart_offset,
                                  &intend_offset);
 
+  if (includeDefaults)
+    {
+      attributes = g_slist_concat (attributes,
+                                   atk_text_get_default_attributes (text));
+    }
+
   reply = dbus_message_new_method_return (message);
   if (!reply)
     return NULL;
 
   dbus_message_iter_init_append (reply, &iter);
-  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{ss}",
-                                    &iterArray);
-  spi_atk_append_attribute_set_inner (&iterArray, attributes);
-  if (includeDefaults)
-    {
-      default_attributes = atk_text_get_default_attributes (text);
-      spi_atk_append_attribute_set_inner (&iterArray, default_attributes);
-    }
-  dbus_message_iter_close_container (&iter, &iterArray);
+  spi_object_append_attribute_set (&iter, attributes);
 
   startOffset = intstart_offset;
   endOffset = intend_offset;
@@ -774,8 +771,6 @@ impl_GetAttributeRun (DBusConnection * bus, DBusMessage * message,
   dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &endOffset);
 
   atk_attribute_set_free (attributes);
-  if (default_attributes)
-    atk_attribute_set_free (default_attributes);
 
   return reply;
 }
diff --git a/atk-adaptor/bridge.c b/atk-adaptor/bridge.c
index 00ead5c..b283506 100644
--- a/atk-adaptor/bridge.c
+++ b/atk-adaptor/bridge.c
@@ -31,15 +31,19 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
+#include <string.h>
 #include <atk/atk.h>
 
 #include <droute/droute.h>
 
 #include "bridge.h"
 #include "event.h"
-#include "accessible-register.h"
 #include "adaptors.h"
 
+#include "accessible-register.h"
+#include "accessible-leasing.h"
+#include "accessible-cache.h"
+
 #include "common/spi-dbus.h"
 
 /*
@@ -51,7 +55,7 @@
 
 /*---------------------------------------------------------------------------*/
 
-SpiAppData *atk_adaptor_app_data = NULL;
+SpiBridge *spi_global_app_data = NULL;
 
 static const AtkMisc *atk_misc = NULL;
 
@@ -151,7 +155,7 @@ spi_atk_bridge_get_bus (void)
       else
         {
           if (!dbus_bus_register (bus, &error))
-            g_error ("AT-SPI: Couldn't register with bus: %s\n");
+            g_error ("AT-SPI: Couldn't register with bus: %s\n", error.message);
         }
     }
 
@@ -161,7 +165,7 @@ spi_atk_bridge_get_bus (void)
 /*---------------------------------------------------------------------------*/
 
 static void
-register_application (SpiAppData * app)
+register_application (SpiBridge * app)
 {
   DBusMessage *message;
   DBusMessageIter iter;
@@ -192,7 +196,7 @@ register_application (SpiAppData * app)
 /*---------------------------------------------------------------------------*/
 
 static void
-deregister_application (SpiAppData * app)
+deregister_application (SpiBridge * app)
 {
   DBusMessage *message;
   DBusMessageIter iter;
@@ -221,17 +225,17 @@ deregister_application (SpiAppData * app)
 static void
 exit_func (void)
 {
-  if (!atk_adaptor_app_data)
+  if (!spi_global_app_data)
     {
       return;
     }
 
   spi_atk_tidy_windows ();
   spi_atk_deregister_event_listeners ();
-  deregister_application (atk_adaptor_app_data);
+  deregister_application (spi_global_app_data);
 
-  g_free (atk_adaptor_app_data);
-  atk_adaptor_app_data = NULL;
+  g_free (spi_global_app_data);
+  spi_global_app_data = NULL;
 
   /* Not currently creating an XDisplay */
 #if 0
@@ -249,7 +253,7 @@ static AtkSocketClass *socket_class;
 static gchar *
 get_plug_id (AtkPlug * plug)
 {
-  const char *uname = dbus_bus_get_unique_name (atk_adaptor_app_data->bus);
+  const char *uname = dbus_bus_get_unique_name (spi_global_app_data->bus);
   gchar *path;
   GString *str = g_string_new (NULL);
 
@@ -352,24 +356,24 @@ adaptor_init (gint * argc, gchar ** argv[])
     g_warning ("AT-SPI Option parsing failed: %s\n", err->message);
 
   /* Allocate global data and do ATK initializations */
-  atk_adaptor_app_data = g_new0 (SpiAppData, 1);
+  spi_global_app_data = g_new0 (SpiBridge, 1);
   atk_misc = atk_misc_get_instance ();
-  atk_adaptor_app_data->root = root;
+  spi_global_app_data->root = root;
 
   /* Set up D-Bus connection and register bus name */
   dbus_error_init (&error);
-  atk_adaptor_app_data->bus = spi_atk_bridge_get_bus ();
-  if (!atk_adaptor_app_data->bus)
+  spi_global_app_data->bus = spi_atk_bridge_get_bus ();
+  if (!spi_global_app_data->bus)
     {
-      g_free (atk_adaptor_app_data);
-      atk_adaptor_app_data = NULL;
+      g_free (spi_global_app_data);
+      spi_global_app_data = NULL;
       return 0;
     }
 
   if (atspi_dbus_name != NULL)
     {
       if (dbus_bus_request_name
-          (atk_adaptor_app_data->bus, atspi_dbus_name, 0, &error))
+          (spi_global_app_data->bus, atspi_dbus_name, 0, &error))
         {
           g_print ("AT-SPI Recieved D-Bus name - %s\n", atspi_dbus_name);
         }
@@ -381,7 +385,7 @@ adaptor_init (gint * argc, gchar ** argv[])
         }
     }
 
-  dbus_connection_setup_with_g_main (atk_adaptor_app_data->bus,
+  dbus_connection_setup_with_g_main (spi_global_app_data->bus,
                                      g_main_context_default ());
 
   /* Get D-Bus introspection directory */
@@ -390,21 +394,29 @@ adaptor_init (gint * argc, gchar ** argv[])
     introspection_directory = ATSPI_INTROSPECTION_PATH;
 
   /* Register droute for routing AT-SPI messages */
-  atk_adaptor_app_data->droute =
-    droute_new (atk_adaptor_app_data->bus, introspection_directory);
+  spi_global_app_data->droute =
+    droute_new (spi_global_app_data->bus, introspection_directory);
 
-  treepath = droute_add_one (atk_adaptor_app_data->droute,
-                             "/org/freedesktop/atspi/tree", NULL);
+  treepath = droute_add_one (spi_global_app_data->droute,
+                             "/org/at_spi/cache", NULL);
 
-  accpath = droute_add_many (atk_adaptor_app_data->droute,
-                             "/org/freedesktop/atspi/accessible",
+  accpath = droute_add_many (spi_global_app_data->droute,
+                             "/org/at_spi/accessible",
                              NULL,
                              (DRouteGetDatumFunction)
-                             atk_dbus_path_to_gobject);
+                             spi_global_register_path_to_object);
 
-  /* Register all interfaces with droute and set up application accessible db */
-  spi_initialize_tree (treepath);
+  /* 
+   * Create the leasing, register and cache objects.
+   * The order is important here, the cache depends on the
+   * register object.
+   */
+  spi_global_register = g_object_new (SPI_REGISTER_TYPE, NULL);
+  spi_global_leasing  = g_object_new (SPI_LEASING_TYPE, NULL);
+  spi_global_cache    = g_object_new (SPI_CACHE_TYPE, NULL);
 
+  /* Register all interfaces with droute and set up application accessible db */
+  spi_initialize_cache (treepath);
   spi_initialize_accessible (accpath);
   spi_initialize_application (accpath);
   spi_initialize_action (accpath);
@@ -420,9 +432,6 @@ adaptor_init (gint * argc, gchar ** argv[])
   spi_initialize_text (accpath);
   spi_initialize_value (accpath);
 
-  /* Initialize the AtkObject registration */
-  atk_dbus_initialize (atk_adaptor_app_data->root);
-
   /* Register methods to send D-Bus signals on certain ATK events */
   spi_atk_register_event_listeners ();
 
@@ -433,7 +442,7 @@ adaptor_init (gint * argc, gchar ** argv[])
 
   /* Register this app by sending a signal out to AT-SPI registry daemon */
   if (!atspi_no_register)
-    register_application (atk_adaptor_app_data);
+    register_application (spi_global_app_data);
 
   g_atexit (exit_func);
 
diff --git a/atk-adaptor/bridge.h b/atk-adaptor/bridge.h
index 44315f1..2a95fcd 100644
--- a/atk-adaptor/bridge.h
+++ b/atk-adaptor/bridge.h
@@ -4,7 +4,7 @@
  *
  * Copyright 2001, 2002, 2003 Sun Microsystems Inc.,
  * Copyright 2001, 2002, 2003 Ximian, Inc.
- * Copyright 2008, 2009 Codethink Ltd.
+ * Copyright 2008, 2009, 2010 Codethink Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -28,15 +28,29 @@
 #include <atk/atk.h>
 #include <droute/droute.h>
 
-typedef struct _SpiAppData SpiAppData;
-struct _SpiAppData
+typedef struct _SpiBridge SpiBridge;
+typedef struct _SpiBridgeClass SpiBridgeClass;
+
+G_BEGIN_DECLS
+
+struct _SpiBridge
 {
+  GObject parent;
+
   AtkObject *root;
 
   DBusConnection *bus;
-  DRouteContext *droute;
+  DRouteContext  *droute;
+
+/*
+  SpiRegister *reg;
+  SpiCache    *cache;
+  SpiLeasing  *leasing;
+*/
 };
 
-extern SpiAppData *atk_adaptor_app_data;
+extern SpiBridge *spi_global_app_data;
+
+G_END_DECLS
 
 #endif /* BRIDGE_H */
diff --git a/atk-adaptor/event.c b/atk-adaptor/event.c
index 687fc79..e97046b 100644
--- a/atk-adaptor/event.c
+++ b/atk-adaptor/event.c
@@ -73,6 +73,14 @@ send_and_allow_reentry (DBusConnection * bus, DBusMessage * message)
   return reply;
 }
 
+/*---------------------------------------------------------------------------*/
+
+/*
+ * Functionality related to sending device events from the application.
+ *
+ * This is used for forwarding key events on to the registry daemon.
+ */
+
 static gboolean
 Accessibility_DeviceEventController_NotifyListenersSync (const
                                                          Accessibility_DeviceEvent
@@ -92,7 +100,7 @@ Accessibility_DeviceEventController_NotifyListenersSync (const
   if (spi_dbus_marshal_deviceEvent (message, key_event))
     {
       DBusMessage *reply =
-        send_and_allow_reentry (atk_adaptor_app_data->bus, message);
+        send_and_allow_reentry (spi_global_app_data->bus, message);
       if (reply)
         {
           DBusError error;
@@ -169,22 +177,10 @@ spi_atk_bridge_key_listener (AtkKeyEventStruct * event, gpointer data)
   return result;
 }
 
-
 /*---------------------------------------------------------------------------*/
 
-/*
- * Emits an AT-SPI event.
- * AT-SPI events names are split into three parts:
- * class:major:minor
- * This is mapped onto D-Bus events as:
- * D-Bus Interface:Signal Name:Detail argument
- *
- * Marshals a basic type into the 'any_data' attribute of
- * the AT-SPI event.
- */
-
 static gchar *
-DBusSignalName (const gchar * s)
+convert_signal_name (const gchar * s)
 {
   gchar *ret = g_strdup (s);
   gchar *t;
@@ -200,103 +196,122 @@ DBusSignalName (const gchar * s)
   return ret;
 }
 
+static const void *
+replace_null (const gint type,
+              const void *val)
+{
+  switch (type)
+    {
+      case DBUS_TYPE_STRING:
+      case DBUS_TYPE_OBJECT_PATH:
+	   if (!val)
+	      return "";
+	   else
+	      return val;
+      default:
+	   return val;
+    }
+}
+
 static void
-emit (AtkObject * accessible,
-      const char *klass,
-      const char *major,
-      const char *minor,
-      dbus_int32_t detail1,
-      dbus_int32_t detail2, const char *type, const void *val)
+append_basic (DBusMessageIter *iter,
+              const char *type,
+              const void *val)
 {
-  gchar *path;
-  gchar *cname;
+  DBusMessageIter sub;
 
-  /* TODO this is a hack, used becuase child-added events are not guaranteed.
-   * On recieving an event from a non-registered object we check if it can be safely 
-   * registered before sending the event.
-   */
-  path = atk_dbus_object_attempt_registration (accessible);
+  dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, type, &sub);
 
-  /* Tough decision here
-   * We won't send events from accessible
-   * objects that have not yet been added to the accessible tree.
-   */
-  if (path == NULL)
-    {
-#ifdef SPI_ATK_DEBUG
-      g_debug ("AT-SPI: Event recieved from non-registered object");
-#endif
-      return;
-    }
+    val = replace_null ((int) *type, val);
+    dbus_message_iter_append_basic(&sub, (int) *type, &val);
 
-  cname = DBusSignalName (major);
-  spi_dbus_emit_signal (atk_adaptor_app_data->bus, path, klass, cname, minor,
-                        detail1, detail2, type, val);
-  g_free (cname);
-  g_free (path);
+  dbus_message_iter_close_container(iter, &sub);
 }
 
-/*---------------------------------------------------------------------------*/
-
-/*
- * Emits an AT-SPI event, marshalling a BoundingBox structure into the 
- * 'any_data' variant of the event.
- */
 static void
-emit_rect (AtkObject * accessible,
-           const char *klass,
-           const char *major, const char *minor, AtkRectangle * rect)
+append_rect (DBusMessageIter *iter,
+             const char *type,
+             const void *val)
 {
-  DBusMessage *sig;
-  DBusMessageIter iter, variant, sub;
-  gchar *path, *cname;
-  dbus_int32_t dummy = 0;
+  DBusMessageIter variant, sub;
+  const AtkRectangle *rect = (const AtkRectangle *) val;
 
-  path = atk_dbus_object_to_path (accessible, FALSE);
+  dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, type, &variant);
 
-  /* Tough decision here
-   * We won't send events from accessible
-   * objects that have not yet been added to the accessible tree.
-   */
-  if (path == NULL)
-    return;
+    dbus_message_iter_open_container (&variant, DBUS_TYPE_STRUCT, NULL, &sub);
+
+      dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->x));
+      dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->y));
+      dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->width));
+      dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->height));
 
-  if (!klass)
-    klass = "";
-  if (!major)
-    major = "";
-  if (!minor)
-    minor = "";
+    dbus_message_iter_close_container (&variant, &sub);
+
+  dbus_message_iter_close_container(iter, &variant);
+}
+
+static void
+append_object (DBusMessageIter *iter,
+               const char *type,
+               const void *val)
+{
+  spi_object_append_v_reference (iter, ATK_OBJECT (val));
+}
+
+/*
+ * Emits an AT-SPI event.
+ * AT-SPI events names are split into three parts:
+ * class:major:minor
+ * This is mapped onto D-Bus events as:
+ * D-Bus Interface:Signal Name:Detail argument
+ *
+ * Marshals a basic type into the 'any_data' attribute of
+ * the AT-SPI event.
+ */
+static void 
+emit_event (AtkObject  *obj,
+            const char *klass,
+            const char *major,
+            const char *minor,
+            dbus_int32_t detail1,
+            dbus_int32_t detail2,
+            const char *type,
+            const void *val,
+            void (*append_variant) (DBusMessageIter *, const char *, const void *))
+{
+  DBusConnection *bus = spi_global_app_data->bus;
+  const char *path =  spi_register_object_to_path (spi_global_register,
+                                                   G_OBJECT (obj));
+
+  gchar *cname, *t;
+  DBusMessage *sig;
+  DBusMessageIter iter;
+  
+  if (!klass) klass = "";
+  if (!major) major = "";
+  if (!minor) minor = "";
+  if (!type) type = "u";
 
   /*
    * This is very annoying, but as '-' isn't a legal signal
    * name in D-Bus (Why not??!?) The names need converting
    * on this side, and again on the client side.
    */
-  cname = DBusSignalName (major);
-
-  sig = dbus_message_new_signal (path, klass, cname);
-  g_free (path);
-  g_free (cname);
-
-  dbus_message_iter_init_append (sig, &iter);
-  dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &minor);
-  dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &dummy);
-  dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &dummy);
-
-  dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "(iiii)",
-                                    &variant);
-  dbus_message_iter_open_container (&variant, DBUS_TYPE_STRUCT, NULL, &sub);
-  dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->x));
-  dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->y));
-  dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->width));
-  dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->height));
-  dbus_message_iter_close_container (&variant, &sub);
-  dbus_message_iter_close_container (&iter, &variant);
-
-  dbus_connection_send (atk_adaptor_app_data->bus, sig, NULL);
-
-  dbus_message_unref (sig);
+  cname = g_strdup(major);
+  while ((t = strchr(cname, '-')) != NULL) *t = '_';
+  sig = dbus_message_new_signal(path, klass, cname);
+  g_free(cname);
+
+  dbus_message_iter_init_append(sig, &iter);
+
+  dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &minor);
+  dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &detail1);
+  dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &detail2);
+
+  append_variant (&iter, type, val);
+
+  dbus_connection_send(bus, sig, NULL);
+  dbus_message_unref(sig);
 }
 
 /*---------------------------------------------------------------------------*/
@@ -308,8 +323,8 @@ emit_rect (AtkObject * accessible,
 static void
 focus_tracker (AtkObject * accessible)
 {
-  emit (accessible, ITF_EVENT_FOCUS, "focus", "", 0, 0,
-        DBUS_TYPE_INT32_AS_STRING, 0);
+  emit_event (accessible, ITF_EVENT_FOCUS, "focus", "", 0, 0,
+              DBUS_TYPE_INT32_AS_STRING, 0, append_basic);
 }
 
 /*---------------------------------------------------------------------------*/
@@ -335,75 +350,85 @@ property_event_listener (GSignalInvocationHint * signal_hint,
   const gchar *pname = NULL;
 
   AtkObject *otemp;
-  const gchar *stemp;
+  const gchar *s1, s2;
   gint i;
 
   accessible = g_value_get_object (&param_values[0]);
   values = (AtkPropertyValues *) g_value_get_pointer (&param_values[1]);
 
   pname = values[0].property_name;
-  if (strcmp (pname, "accessible-name") == 0 ||
-      strcmp (pname, "accessible-description") == 0 ||
-      strcmp (pname, "accessible-role") == 0 ||
-      strcmp (pname, "accessible-parent") == 0)
-    {
-      return TRUE;
-    }
 
   /* TODO Could improve this control statement by matching
    * on only the end of the signal names,
    */
+  if (strcmp (pname, "accessible-name") == 0)
+    {
+      s1 = atk_object_get_name (accessible);
+      if (s1 != NULL)
+        emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+                    DBUS_TYPE_STRING_AS_STRING, s1, append_basic);
+    }
+  if (strcmp (pname, "accessible-description") == 0)
+    {
+      s1 = atk_object_get_description (accessible);
+      if (s1 != NULL)
+        emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+                    DBUS_TYPE_STRING_AS_STRING, s1, append_basic);
+    }
+  if (strcmp (pname, "accessible-parent") == 0)
+    {
+      otemp = atk_object_get_parent (accessible);
+      if (otemp != NULL)
+        emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+                    "(so)", otemp, append_object);
+    }
   if (strcmp (pname, "accessible-table-summary") == 0)
     {
       otemp = atk_table_get_summary (ATK_TABLE (accessible));
-      stemp = atk_dbus_object_to_path (otemp, FALSE);
-      if (stemp != NULL)
-        emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
-              DBUS_TYPE_OBJECT_PATH_AS_STRING, stemp);
+      if (otemp != NULL)
+        emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+                    "(so)", otemp, append_object);
     }
   else if (strcmp (pname, "accessible-table-column-header") == 0)
     {
       i = g_value_get_int (&(values->new_value));
       otemp = atk_table_get_column_header (ATK_TABLE (accessible), i);
-      stemp = atk_dbus_object_to_path (otemp, FALSE);
-      if (stemp != NULL)
-        emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
-              DBUS_TYPE_OBJECT_PATH_AS_STRING, stemp);
+      if (otemp != NULL)
+        emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+                    "(so)", otemp, append_object);
     }
   else if (strcmp (pname, "accessible-table-row-header") == 0)
     {
       i = g_value_get_int (&(values->new_value));
       otemp = atk_table_get_row_header (ATK_TABLE (accessible), i);
-      stemp = atk_dbus_object_to_path (otemp, FALSE);
-      if (stemp != NULL)
-        emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
-              DBUS_TYPE_OBJECT_PATH_AS_STRING, stemp);
+      if (otemp != NULL)
+        emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+                    "(so)", otemp, append_object);
     }
   else if (strcmp (pname, "accessible-table-row-description") == 0)
     {
       i = g_value_get_int (&(values->new_value));
-      stemp = atk_table_get_row_description (ATK_TABLE (accessible), i);
-      emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
-            DBUS_TYPE_STRING_AS_STRING, stemp);
+      s1 = atk_table_get_row_description (ATK_TABLE (accessible), i);
+      emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+                  DBUS_TYPE_STRING_AS_STRING, s1, append_basic);
     }
   else if (strcmp (pname, "accessible-table-column-description") == 0)
     {
       i = g_value_get_int (&(values->new_value));
-      stemp = atk_table_get_column_description (ATK_TABLE (accessible), i);
-      emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
-            DBUS_TYPE_STRING_AS_STRING, stemp);
+      s1 = atk_table_get_column_description (ATK_TABLE (accessible), i);
+      emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+                  DBUS_TYPE_STRING_AS_STRING, s1, append_basic);
     }
   else if (strcmp (pname, "accessible-table-caption-object") == 0)
     {
       otemp = atk_table_get_caption (ATK_TABLE (accessible));
-      stemp = atk_object_get_name (otemp);
-      emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
-            DBUS_TYPE_STRING_AS_STRING, stemp);
+      emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+                  "(so)", otemp, append_object);
     }
   else
     {
-      emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
-            DBUS_TYPE_INT32_AS_STRING, 0);
+      emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+            DBUS_TYPE_INT32_AS_STRING, 0, append_basic);
     }
   return TRUE;
 }
@@ -433,8 +458,8 @@ state_event_listener (GSignalInvocationHint * signal_hint,
    * This is because without reference counting defunct objects should be removed.
    */
   detail1 = (g_value_get_boolean (&param_values[2])) ? 1 : 0;
-  emit (accessible, ITF_EVENT_OBJECT, STATE_CHANGED, pname, detail1, 0,
-        DBUS_TYPE_INT32_AS_STRING, 0);
+  emit_event (accessible, ITF_EVENT_OBJECT, STATE_CHANGED, pname, detail1, 0,
+              DBUS_TYPE_INT32_AS_STRING, 0, append_basic);
   g_free (pname);
   return TRUE;
 }
@@ -466,8 +491,8 @@ window_event_listener (GSignalInvocationHint * signal_hint,
 
   accessible = ATK_OBJECT (g_value_get_object (&param_values[0]));
   s = atk_object_get_name (accessible);
-  emit (accessible, ITF_EVENT_WINDOW, name, "", 0, 0,
-        DBUS_TYPE_STRING_AS_STRING, s);
+  emit_event (accessible, ITF_EVENT_WINDOW, name, "", 0, 0,
+              DBUS_TYPE_STRING_AS_STRING, s, append_basic);
 
   return TRUE;
 }
@@ -496,8 +521,8 @@ document_event_listener (GSignalInvocationHint * signal_hint,
 
   accessible = ATK_OBJECT (g_value_get_object (&param_values[0]));
   s = atk_object_get_name (accessible);
-  emit (accessible, ITF_EVENT_DOCUMENT, name, "", 0, 0,
-        DBUS_TYPE_STRING_AS_STRING, s);
+  emit_event (accessible, ITF_EVENT_DOCUMENT, name, "", 0, 0,
+              DBUS_TYPE_STRING_AS_STRING, s, append_basic);
 
   return TRUE;
 }
@@ -524,9 +549,12 @@ bounds_event_listener (GSignalInvocationHint * signal_hint,
   accessible = ATK_OBJECT (g_value_get_object (&param_values[0]));
 
   if (G_VALUE_HOLDS_BOXED (param_values + 1))
+  {
     atk_rect = g_value_get_boxed (param_values + 1);
 
-  emit_rect (accessible, ITF_EVENT_OBJECT, name, "", atk_rect);
+    emit_event (accessible, ITF_EVENT_OBJECT, name, "", 0, 0,
+                "(iiii)", atk_rect, append_rect);
+  }
   return TRUE;
 }
 
@@ -558,15 +586,9 @@ active_descendant_event_listener (GSignalInvocationHint * signal_hint,
   minor = g_quark_to_string (signal_hint->detail);
 
   detail1 = atk_object_get_index_in_parent (child);
-  s = atk_dbus_object_to_path (child, FALSE);
-  if (s == NULL)
-    {
-      g_free (s);
-      return TRUE;
-    }
 
-  emit (accessible, ITF_EVENT_OBJECT, name, "", detail1, 0,
-        DBUS_TYPE_OBJECT_PATH_AS_STRING, s);
+  emit_event (accessible, ITF_EVENT_OBJECT, name, "", detail1, 0,
+              "(so)", child, append_object);
   g_free (s);
   return TRUE;
 }
@@ -597,8 +619,8 @@ link_selected_event_listener (GSignalInvocationHint * signal_hint,
   if (G_VALUE_TYPE (&param_values[1]) == G_TYPE_INT)
     detail1 = g_value_get_int (&param_values[1]);
 
-  emit (accessible, ITF_EVENT_OBJECT, name, minor, detail1, 0,
-        DBUS_TYPE_INT32_AS_STRING, 0);
+  emit_event (accessible, ITF_EVENT_OBJECT, name, minor, detail1, 0,
+              DBUS_TYPE_INT32_AS_STRING, 0, append_basic);
   return TRUE;
 }
 
@@ -635,8 +657,8 @@ text_changed_event_listener (GSignalInvocationHint * signal_hint,
   selected =
     atk_text_get_text (ATK_TEXT (accessible), detail1, detail1 + detail2);
 
-  emit (accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2,
-        DBUS_TYPE_STRING_AS_STRING, selected);
+  emit_event (accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2,
+              DBUS_TYPE_STRING_AS_STRING, selected, append_basic);
   return TRUE;
 }
 
@@ -670,8 +692,8 @@ text_selection_changed_event_listener (GSignalInvocationHint * signal_hint,
   if (G_VALUE_TYPE (&param_values[2]) == G_TYPE_INT)
     detail2 = g_value_get_int (&param_values[2]);
 
-  emit (accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2,
-        DBUS_TYPE_STRING_AS_STRING, "");
+  emit_event (accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2,
+              DBUS_TYPE_STRING_AS_STRING, "", append_basic);
   return TRUE;
 }
 
@@ -708,8 +730,8 @@ generic_event_listener (GSignalInvocationHint * signal_hint,
   if (n_param_values > 2 && G_VALUE_TYPE (&param_values[2]) == G_TYPE_INT)
     detail2 = g_value_get_int (&param_values[2]);
 
-  emit (accessible, ITF_EVENT_OBJECT, name, "", detail1, detail2,
-        DBUS_TYPE_INT32_AS_STRING, 0);
+  emit_event (accessible, ITF_EVENT_OBJECT, name, "", detail1, detail2,
+              DBUS_TYPE_INT32_AS_STRING, 0, append_basic);
   return TRUE;
 }
 
@@ -861,13 +883,13 @@ spi_atk_tidy_windows (void)
       name = atk_object_get_name (child);
       if (atk_state_set_contains_state (stateset, ATK_STATE_ACTIVE))
         {
-          emit (child, ITF_EVENT_WINDOW, "deactivate", NULL, 0, 0,
-                DBUS_TYPE_STRING_AS_STRING, name);
+          emit_event (child, ITF_EVENT_WINDOW, "deactivate", NULL, 0, 0,
+                      DBUS_TYPE_STRING_AS_STRING, name, append_basic);
         }
       g_object_unref (stateset);
 
-      emit (child, ITF_EVENT_WINDOW, "destroy", NULL, 0, 0,
-            DBUS_TYPE_STRING_AS_STRING, name);
+      emit_event (child, ITF_EVENT_WINDOW, "destroy", NULL, 0, 0,
+                  DBUS_TYPE_STRING_AS_STRING, name, append_basic);
       g_object_unref (child);
     }
 }
diff --git a/atk-adaptor/object.c b/atk-adaptor/object.c
new file mode 100644
index 0000000..856e991
--- /dev/null
+++ b/atk-adaptor/object.c
@@ -0,0 +1,404 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2008 Novell, Inc.
+ * Copyright 2008, 2009, 2010 Codethink Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This module contains utility functions for exporting AT-SPI
+ * objects based upon an ATK object.
+ *
+ * It incudes functions for marshalling object references
+ * and supported interfaces to a D-Bus message.
+ */
+
+#include <atk/atk.h>
+#include <common/spi-types.h>
+#include <common/spi-dbus.h>
+
+#include "accessible-register.h"
+#include "accessible-cache.h"
+#include "accessible-leasing.h"
+
+#include "bridge.h"
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ * This is the all important function that decides whether an object should
+ * be leased or not.
+ *
+ * The choice of algorithm for this is somewhat vuage. We want ideally to lease
+ * all atk objects that are not owned by their parent.
+ *
+ * The 'cache' object attempts to cache all objects that are owned by their
+ * parent by traversing the tree of accessibles, ignoring the children of
+ * manages-descendants and transient objects.
+ *
+ * This function will simply look for all the accessibles that the cache object
+ * has not found and assume that they need to be leased.
+ */
+static void
+maybe_lease (AtkObject *obj)
+{
+  if (!spi_cache_in (spi_global_cache, G_OBJECT (obj)))
+    {
+      spi_leasing_take (spi_global_leasing, G_OBJECT (obj));
+    }
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ * It is assumed that all of these functions are returning an accessible
+ * object to the client side.
+ *
+ * All of them will lease the AtkObject if it is deemed neccessary.
+ */
+
+void
+spi_object_append_reference (DBusMessageIter * iter, AtkObject * obj)
+{
+  DBusMessageIter iter_struct;
+  const gchar *name;
+  gchar *path;
+
+  maybe_lease (obj);
+
+  name = dbus_bus_get_unique_name (spi_global_app_data->bus);
+  path = spi_register_object_to_path (spi_global_register, G_OBJECT (obj));
+
+  if (!path)
+    path = g_strdup (SPI_DBUS_PATH_NULL);
+
+  dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
+                                    &iter_struct);
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
+  dbus_message_iter_close_container (iter, &iter_struct);
+  
+  g_free (path);
+}
+
+void
+spi_object_append_v_reference (DBusMessageIter * iter, AtkObject * obj)
+{
+  DBusMessageIter iter_variant;
+
+  dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "(so)",
+                                    &iter_variant);
+     spi_object_append_reference (&iter_variant, obj);
+  dbus_message_iter_close_container (iter, &iter_variant);
+}
+
+void
+spi_object_append_desktop_reference (DBusMessageIter * iter)
+{
+  DBusMessageIter iter_struct;
+  const char *name = SPI_DBUS_NAME_REGISTRY;
+  const char *path = SPI_DBUS_PATH_DESKTOP;
+
+  dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
+                                    &iter_struct);
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
+  dbus_message_iter_close_container (iter, &iter_struct);
+}
+
+void
+spi_object_append_null_reference (DBusMessageIter * iter)
+{
+  DBusMessageIter iter_struct;
+  const char *name;
+  const char *path = "/org/at_spi/null";
+
+  name = dbus_bus_get_unique_name (spi_global_app_data->bus);
+
+  dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
+                                    &iter_struct);
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
+  dbus_message_iter_close_container (iter, &iter_struct);
+}
+
+DBusMessage *
+spi_object_return_reference (DBusMessage * msg, AtkObject * obj)
+{
+  DBusMessage *reply;
+
+  reply = dbus_message_new_method_return (msg);
+  if (reply)
+    {
+      DBusMessageIter iter;
+      dbus_message_iter_init_append (reply, &iter);
+      spi_object_append_reference (&iter, obj);
+    }
+  g_object_unref (G_OBJECT (obj));
+
+  return reply;
+}
+
+/*---------------------------------------------------------------------------*/
+
+void
+spi_object_append_interfaces (DBusMessageIter * iter, AtkObject * obj)
+{
+  const gchar *itf;
+
+  itf = SPI_DBUS_INTERFACE_ACCESSIBLE;
+  dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
+
+  if (ATK_IS_ACTION (obj))
+    {
+      itf = SPI_DBUS_INTERFACE_ACTION;
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
+    }
+
+  if (ATK_IS_COMPONENT (obj))
+    {
+      itf = SPI_DBUS_INTERFACE_COMPONENT;
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
+    }
+
+  if (ATK_IS_EDITABLE_TEXT (obj))
+    {
+      itf = SPI_DBUS_INTERFACE_EDITABLE_TEXT;
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
+    }
+
+  if (ATK_IS_TEXT (obj))
+    {
+      itf = SPI_DBUS_INTERFACE_TEXT;
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
+    }
+
+  if (ATK_IS_HYPERTEXT (obj))
+    {
+      itf = SPI_DBUS_INTERFACE_HYPERTEXT;
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
+    }
+
+  if (ATK_IS_IMAGE (obj))
+    {
+      itf = SPI_DBUS_INTERFACE_IMAGE;
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
+    }
+
+  if (ATK_IS_SELECTION (obj))
+    {
+      itf = SPI_DBUS_INTERFACE_SELECTION;
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
+    }
+
+  if (ATK_IS_TABLE (obj))
+    {
+      itf = SPI_DBUS_INTERFACE_TABLE;
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
+    }
+
+  if (ATK_IS_VALUE (obj))
+    {
+      itf = SPI_DBUS_INTERFACE_VALUE;
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
+    }
+
+  if (ATK_IS_STREAMABLE_CONTENT (obj))
+    {
+      itf = "org.freedesktop.atspi.StreamableContent";
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
+    }
+
+  if (ATK_IS_DOCUMENT (obj))
+    {
+      itf = "org.freedesktop.atspi.Collection";
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
+      itf = SPI_DBUS_INTERFACE_DOCUMENT;
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
+    }
+
+  if (ATK_IS_HYPERLINK_IMPL (obj))
+    {
+      itf = SPI_DBUS_INTERFACE_HYPERLINK;
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
+    }
+}
+
+/*---------------------------------------------------------------------------*/
+
+void
+spi_object_append_attribute_set (DBusMessageIter * iter, AtkAttributeSet * attr)
+{
+  DBusMessageIter dictIter;
+
+  dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{ss}", &dictIter);
+  while (attr)
+    {
+      DBusMessageIter dictEntryIter;
+      AtkAttribute *attribute = (AtkAttribute *) attr->data;
+      const char *key = attribute->name;
+      const char *value = attribute->value;
+
+      if (key == NULL)
+	key = "";
+      if (value == NULL)
+        value = "";
+
+      dbus_message_iter_open_container (&dictIter, DBUS_TYPE_DICT_ENTRY, NULL,
+                                        &dictEntryIter);
+      dbus_message_iter_append_basic (&dictEntryIter, DBUS_TYPE_STRING,
+                                      &key);
+      dbus_message_iter_append_basic (&dictEntryIter, DBUS_TYPE_STRING,
+                                      &value);
+      dbus_message_iter_close_container (&dictIter, &dictEntryIter);
+      attr = g_slist_next (attr);
+    }
+  dbus_message_iter_close_container (iter, &dictIter);
+}
+
+/*---------------------------------------------------------------------------*/
+
+static gboolean
+init_role_lookup_table (Accessibility_Role * role_table)
+{
+  int i;
+  /* if it's not in the list below, dunno what it is */
+  for (i = 0; i < ATK_ROLE_LAST_DEFINED; ++i)
+    {
+      role_table[i] = Accessibility_ROLE_UNKNOWN;
+    }
+
+  role_table[ATK_ROLE_INVALID] = Accessibility_ROLE_INVALID;
+  role_table[ATK_ROLE_ACCEL_LABEL] = Accessibility_ROLE_ACCELERATOR_LABEL;
+  role_table[ATK_ROLE_ALERT] = Accessibility_ROLE_ALERT;
+  role_table[ATK_ROLE_ANIMATION] = Accessibility_ROLE_ANIMATION;
+  role_table[ATK_ROLE_ARROW] = Accessibility_ROLE_ARROW;
+  role_table[ATK_ROLE_CALENDAR] = Accessibility_ROLE_CALENDAR;
+  role_table[ATK_ROLE_CANVAS] = Accessibility_ROLE_CANVAS;
+  role_table[ATK_ROLE_CHECK_BOX] = Accessibility_ROLE_CHECK_BOX;
+  role_table[ATK_ROLE_CHECK_MENU_ITEM] = Accessibility_ROLE_CHECK_MENU_ITEM;
+  role_table[ATK_ROLE_COLOR_CHOOSER] = Accessibility_ROLE_COLOR_CHOOSER;
+  role_table[ATK_ROLE_COLUMN_HEADER] = Accessibility_ROLE_COLUMN_HEADER;
+  role_table[ATK_ROLE_COMBO_BOX] = Accessibility_ROLE_COMBO_BOX;
+  role_table[ATK_ROLE_DATE_EDITOR] = Accessibility_ROLE_DATE_EDITOR;
+  role_table[ATK_ROLE_DESKTOP_ICON] = Accessibility_ROLE_DESKTOP_ICON;
+  role_table[ATK_ROLE_DESKTOP_FRAME] = Accessibility_ROLE_DESKTOP_FRAME;
+  role_table[ATK_ROLE_DIAL] = Accessibility_ROLE_DIAL;
+  role_table[ATK_ROLE_DIALOG] = Accessibility_ROLE_DIALOG;
+  role_table[ATK_ROLE_DIRECTORY_PANE] = Accessibility_ROLE_DIRECTORY_PANE;
+  role_table[ATK_ROLE_DRAWING_AREA] = Accessibility_ROLE_DRAWING_AREA;
+  role_table[ATK_ROLE_FILE_CHOOSER] = Accessibility_ROLE_FILE_CHOOSER;
+  role_table[ATK_ROLE_FILLER] = Accessibility_ROLE_FILLER;
+  role_table[ATK_ROLE_FONT_CHOOSER] = Accessibility_ROLE_FONT_CHOOSER;
+  role_table[ATK_ROLE_FRAME] = Accessibility_ROLE_FRAME;
+  role_table[ATK_ROLE_GLASS_PANE] = Accessibility_ROLE_GLASS_PANE;
+  role_table[ATK_ROLE_HTML_CONTAINER] = Accessibility_ROLE_HTML_CONTAINER;
+  role_table[ATK_ROLE_ICON] = Accessibility_ROLE_ICON;
+  role_table[ATK_ROLE_IMAGE] = Accessibility_ROLE_IMAGE;
+  role_table[ATK_ROLE_INTERNAL_FRAME] = Accessibility_ROLE_INTERNAL_FRAME;
+  role_table[ATK_ROLE_LABEL] = Accessibility_ROLE_LABEL;
+  role_table[ATK_ROLE_LAYERED_PANE] = Accessibility_ROLE_LAYERED_PANE;
+  role_table[ATK_ROLE_LIST] = Accessibility_ROLE_LIST;
+  role_table[ATK_ROLE_LIST_ITEM] = Accessibility_ROLE_LIST_ITEM;
+  role_table[ATK_ROLE_MENU] = Accessibility_ROLE_MENU;
+  role_table[ATK_ROLE_MENU_BAR] = Accessibility_ROLE_MENU_BAR;
+  role_table[ATK_ROLE_MENU_ITEM] = Accessibility_ROLE_MENU_ITEM;
+  role_table[ATK_ROLE_OPTION_PANE] = Accessibility_ROLE_OPTION_PANE;
+  role_table[ATK_ROLE_PAGE_TAB] = Accessibility_ROLE_PAGE_TAB;
+  role_table[ATK_ROLE_PAGE_TAB_LIST] = Accessibility_ROLE_PAGE_TAB_LIST;
+  role_table[ATK_ROLE_PANEL] = Accessibility_ROLE_PANEL;
+  role_table[ATK_ROLE_PASSWORD_TEXT] = Accessibility_ROLE_PASSWORD_TEXT;
+  role_table[ATK_ROLE_POPUP_MENU] = Accessibility_ROLE_POPUP_MENU;
+  role_table[ATK_ROLE_PROGRESS_BAR] = Accessibility_ROLE_PROGRESS_BAR;
+  role_table[ATK_ROLE_PUSH_BUTTON] = Accessibility_ROLE_PUSH_BUTTON;
+  role_table[ATK_ROLE_RADIO_BUTTON] = Accessibility_ROLE_RADIO_BUTTON;
+  role_table[ATK_ROLE_RADIO_MENU_ITEM] = Accessibility_ROLE_RADIO_MENU_ITEM;
+  role_table[ATK_ROLE_ROOT_PANE] = Accessibility_ROLE_ROOT_PANE;
+  role_table[ATK_ROLE_ROW_HEADER] = Accessibility_ROLE_ROW_HEADER;
+  role_table[ATK_ROLE_SCROLL_BAR] = Accessibility_ROLE_SCROLL_BAR;
+  role_table[ATK_ROLE_SCROLL_PANE] = Accessibility_ROLE_SCROLL_PANE;
+  role_table[ATK_ROLE_SEPARATOR] = Accessibility_ROLE_SEPARATOR;
+  role_table[ATK_ROLE_SLIDER] = Accessibility_ROLE_SLIDER;
+  role_table[ATK_ROLE_SPIN_BUTTON] = Accessibility_ROLE_SPIN_BUTTON;
+  role_table[ATK_ROLE_SPLIT_PANE] = Accessibility_ROLE_SPLIT_PANE;
+  role_table[ATK_ROLE_STATUSBAR] = Accessibility_ROLE_STATUS_BAR;
+  role_table[ATK_ROLE_TABLE] = Accessibility_ROLE_TABLE;
+  role_table[ATK_ROLE_TABLE_CELL] = Accessibility_ROLE_TABLE_CELL;
+  role_table[ATK_ROLE_TABLE_COLUMN_HEADER] =
+    Accessibility_ROLE_TABLE_COLUMN_HEADER;
+  role_table[ATK_ROLE_TABLE_ROW_HEADER] = Accessibility_ROLE_TABLE_ROW_HEADER;
+  role_table[ATK_ROLE_TEAR_OFF_MENU_ITEM] =
+    Accessibility_ROLE_TEAROFF_MENU_ITEM;
+  role_table[ATK_ROLE_TERMINAL] = Accessibility_ROLE_TERMINAL;
+  role_table[ATK_ROLE_TEXT] = Accessibility_ROLE_TEXT;
+  role_table[ATK_ROLE_TOGGLE_BUTTON] = Accessibility_ROLE_TOGGLE_BUTTON;
+  role_table[ATK_ROLE_TOOL_BAR] = Accessibility_ROLE_TOOL_BAR;
+  role_table[ATK_ROLE_TOOL_TIP] = Accessibility_ROLE_TOOL_TIP;
+  role_table[ATK_ROLE_TREE] = Accessibility_ROLE_TREE;
+  role_table[ATK_ROLE_TREE_TABLE] = Accessibility_ROLE_TREE_TABLE;
+  role_table[ATK_ROLE_UNKNOWN] = Accessibility_ROLE_UNKNOWN;
+  role_table[ATK_ROLE_VIEWPORT] = Accessibility_ROLE_VIEWPORT;
+  role_table[ATK_ROLE_WINDOW] = Accessibility_ROLE_WINDOW;
+  role_table[ATK_ROLE_HEADER] = Accessibility_ROLE_HEADER;
+  role_table[ATK_ROLE_FOOTER] = Accessibility_ROLE_FOOTER;
+  role_table[ATK_ROLE_PARAGRAPH] = Accessibility_ROLE_PARAGRAPH;
+  role_table[ATK_ROLE_RULER] = Accessibility_ROLE_RULER;
+  role_table[ATK_ROLE_APPLICATION] = Accessibility_ROLE_APPLICATION;
+  role_table[ATK_ROLE_AUTOCOMPLETE] = Accessibility_ROLE_AUTOCOMPLETE;
+  role_table[ATK_ROLE_EDITBAR] = Accessibility_ROLE_EDITBAR;
+  role_table[ATK_ROLE_EMBEDDED] = Accessibility_ROLE_EMBEDDED;
+  role_table[ATK_ROLE_ENTRY] = Accessibility_ROLE_ENTRY;
+  role_table[ATK_ROLE_CHART] = Accessibility_ROLE_CHART;
+  role_table[ATK_ROLE_CAPTION] = Accessibility_ROLE_CAPTION;
+  role_table[ATK_ROLE_DOCUMENT_FRAME] = Accessibility_ROLE_DOCUMENT_FRAME;
+  role_table[ATK_ROLE_HEADING] = Accessibility_ROLE_HEADING;
+  role_table[ATK_ROLE_PAGE] = Accessibility_ROLE_PAGE;
+  role_table[ATK_ROLE_SECTION] = Accessibility_ROLE_SECTION;
+  role_table[ATK_ROLE_FORM] = Accessibility_ROLE_FORM;
+  role_table[ATK_ROLE_REDUNDANT_OBJECT] = Accessibility_ROLE_REDUNDANT_OBJECT;
+  role_table[ATK_ROLE_LINK] = Accessibility_ROLE_LINK;
+  role_table[ATK_ROLE_INPUT_METHOD_WINDOW] =
+    Accessibility_ROLE_INPUT_METHOD_WINDOW;
+  return TRUE;
+}
+
+Accessibility_Role
+spi_accessible_role_from_atk_role (AtkRole role)
+{
+  static gboolean is_initialized = FALSE;
+  static Accessibility_Role spi_role_table[ATK_ROLE_LAST_DEFINED];
+  Accessibility_Role spi_role;
+
+  if (!is_initialized)
+    {
+      is_initialized = init_role_lookup_table (spi_role_table);
+    }
+
+  if (role >= 0 && role < ATK_ROLE_LAST_DEFINED)
+    {
+      spi_role = spi_role_table[role];
+    }
+  else
+    {
+      spi_role = Accessibility_ROLE_EXTENDED;
+    }
+  return spi_role;
+}
+
+/*END------------------------------------------------------------------------*/
diff --git a/atk-adaptor/adaptors/tree-adaptor.h b/atk-adaptor/object.h
similarity index 54%
rename from atk-adaptor/adaptors/tree-adaptor.h
rename to atk-adaptor/object.h
index 2406448..fb30b04 100644
--- a/atk-adaptor/adaptors/tree-adaptor.h
+++ b/atk-adaptor/object.h
@@ -2,9 +2,8 @@
  * AT-SPI - Assistive Technology Service Provider Interface
  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
  *
- * Copyright 2001, 2002 Sun Microsystems Inc.,
- * Copyright 2001, 2002 Ximian, Inc.
- * Copyright 2008, 2009 Codethink Ltd.
+ * Copyright 2008 Novell, Inc.
+ * Copyright 2008, 2009, 2010 Codethink Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -22,14 +21,34 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#ifndef TREE_ADAPTOR_H
-#define TREE_ADAPTOR_H
+#ifndef ACCESSIBLE_OBJECT_H
+#define ACCESSIBLE_OBJECT_H
 
 #include <atk/atk.h>
 #include <dbus/dbus.h>
 
-void spi_emit_cache_update (AtkObject * accessible, DBusConnection * bus);
+void
+spi_object_append_reference (DBusMessageIter * iter, AtkObject * obj);
 
-void spi_emit_cache_removal (guint ref, DBusConnection * bus);
+void
+spi_object_append_v_reference (DBusMessageIter * iter, AtkObject * obj);
 
-#endif /* TREE_ADAPTOR_H */
+void
+spi_object_append_desktop_reference (DBusMessageIter * iter);
+
+void
+spi_object_append_null_reference (DBusMessageIter * iter);
+
+DBusMessage *
+spi_object_return_reference (DBusMessage * msg, AtkObject * obj);
+
+void
+spi_object_append_interfaces (DBusMessageIter * iter, AtkObject * obj);
+
+void
+spi_object_append_attribute_set (DBusMessageIter * iter, AtkAttributeSet * attr);
+
+Accessibility_Role
+spi_accessible_role_from_atk_role (AtkRole role);
+
+#endif /* ACCESSIBLE_OBJECT_H */
diff --git a/common/spi-dbus.c b/common/spi-dbus.c
index f859156..b24a8ee 100644
--- a/common/spi-dbus.c
+++ b/common/spi-dbus.c
@@ -172,6 +172,43 @@ provide_defaults(const gint type,
     }
 }
 
+/*
+ * Appends all the standard parameters to an AT-SPI event.
+ */
+void
+spi_dbus_signal_new (const char *path,
+                     const char *klass,
+                     const char *major,
+                     const char *minor,
+                     dbus_int32_t detail1,
+                     dbus_int32_t detail2)
+{
+  DBusMessage *sig;
+  DBusMessageIter iter, sub;
+  gchar *cname, *t;
+
+  if (!klass) klass = "";
+  if (!major) major = "";
+  if (!minor) minor = "";
+
+  /*
+   * This is very annoying, but as '-' isn't a legal signal
+   * name in D-Bus (Why not??!?) The names need converting
+   * on this side, and again on the client side.
+   */
+  cname = g_strdup(major);
+  while ((t = strchr(cname, '-')) != NULL) *t = '_';
+
+  sig = dbus_message_new_signal(path, klass, cname);
+  g_free(cname);
+
+  dbus_message_iter_init_append(sig, &iter);
+
+  dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &minor);
+  dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &detail1);
+  dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &detail2);
+}
+
 void 
 spi_dbus_emit_signal(DBusConnection *bus, const char *path,
      const char *klass,
@@ -222,6 +259,7 @@ spi_dbus_emit_signal(DBusConnection *bus, const char *path,
   dbus_message_unref(sig);
 }
 
+
 /*
 dbus_bool_t spi_dbus_get_simple_property (DBusConnection *bus, const char *dest, const char *path, const char *interface, const char *prop, int *type, void *ptr, DBusError *error)
 {
diff --git a/common/spi-dbus.h b/common/spi-dbus.h
index b6e1283..f82e24c 100644
--- a/common/spi-dbus.h
+++ b/common/spi-dbus.h
@@ -44,7 +44,7 @@ extern int _dbg;
 #define SPI_DBUS_INTERFACE_DEC "org.freedesktop.atspi.DeviceEventController"
 #define SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER "org.freedesktop.atspi.DeviceEventListener"
 
-#define SPI_DBUS_INTERFACE_TREE "org.freedesktop.atspi.Tree"
+#define SPI_DBUS_INTERFACE_CACHE "org.freedesktop.atspi.Cache"
 #define SPI_DBUS_INTERFACE_ACCESSIBLE "org.freedesktop.atspi.Accessible"
 #define SPI_DBUS_INTERFACE_ACTION "org.freedesktop.atspi.Action"
 #define SPI_DBUS_INTERFACE_APPLICATION "org.freedesktop.atspi.Application"
diff --git a/common/spi-stateset.c b/common/spi-stateset.c
index ff0a53d..2c148f0 100644
--- a/common/spi-stateset.c
+++ b/common/spi-stateset.c
@@ -154,7 +154,7 @@ spi_atk_state_from_spi_state (Accessibility_StateType state)
 }
 
 AtkStateSet *
-spi_state_set_cache_from_sequence (const GArray *seq)
+spi_state_set_cache_from_sequence (GArray *seq)
 {
   int i;
   AtkStateSet *set;
diff --git a/common/spi-stateset.h b/common/spi-stateset.h
index b82466d..f097c92 100644
--- a/common/spi-stateset.h
+++ b/common/spi-stateset.h
@@ -30,7 +30,7 @@
 G_BEGIN_DECLS
 
 /* private - internal API to abstract away atk API */
-AtkStateSet *spi_state_set_cache_from_sequence(const GArray *seq);
+AtkStateSet *spi_state_set_cache_from_sequence(GArray *seq);
 AtkState     spi_atk_state_from_spi_state     (Accessibility_StateType state);
 void spi_atk_state_to_dbus_array (AtkObject * object, dbus_uint32_t * array);
 void spi_atk_state_set_to_dbus_array (AtkStateSet *set, dbus_uint32_t * array);
diff --git a/configure.ac b/configure.ac
index aadf7f5..f16ff7f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -98,26 +98,23 @@ fi
 AC_SUBST(EXTRA_SOCKET_LIBS)
 
 dnl find sizes & alignments
-orig_CPPFLAGS=$CPPFLAGS
-CPPFLAGS="$CPPFLAGS $DBUS_CFLAGS"
-DBIND_CHECK_ALIGNOF(char)
-DBIND_CHECK_ALIGNOF(dbus_bool_t)
-DBIND_CHECK_ALIGNOF(dbus_int16_t)
-DBIND_CHECK_ALIGNOF(dbus_int32_t)
-DBIND_CHECK_ALIGNOF(dbus_int64_t)
-DBIND_CHECK_ALIGNOF(double)
-DBIND_CHECK_ALIGNOF(dbind_pointer)
-DBIND_CHECK_ALIGNOF(dbind_struct)
-CPPFLAGS=$orig_CPPFLAGS 
+#orig_CPPFLAGS=$CPPFLAGS
+#CPPFLAGS="$CPPFLAGS $DBUS_CFLAGS"
+#DBIND_CHECK_ALIGNOF(char)
+#DBIND_CHECK_ALIGNOF(dbus_bool_t)
+#DBIND_CHECK_ALIGNOF(dbus_int16_t)
+#DBIND_CHECK_ALIGNOF(dbus_int32_t)
+#DBIND_CHECK_ALIGNOF(dbus_int64_t)
+#DBIND_CHECK_ALIGNOF(double)
+#DBIND_CHECK_ALIGNOF(dbind_pointer)
+#DBIND_CHECK_ALIGNOF(dbind_struct)
+#CPPFLAGS=$orig_CPPFLAGS 
 
 AC_CONFIG_FILES([Makefile
 		 droute/Makefile
-		 dbind/Makefile
-		 dbind/dbind-config.h
 		 common/Makefile
 		 atk-adaptor/Makefile
 		 atk-adaptor/adaptors/Makefile
-		 tests/Makefile
 		])
 
 AC_OUTPUT
diff --git a/droute/droute.c b/droute/droute.c
index 55020a7..5ab1478 100644
--- a/droute/droute.c
+++ b/droute/droute.c
@@ -525,6 +525,8 @@ handle_message (DBusConnection *bus, DBusMessage *message, void *user_data)
     const gint   type    = dbus_message_get_type (message);
     const gchar *pathstr = dbus_message_get_path (message);
 
+    _DROUTE_DEBUG ("DRoute (handle message): %s|%s of type %d on %s\n", member, iface, type, pathstr);
+
     /* Check for basic reasons not to handle */
     if (type   != DBUS_MESSAGE_TYPE_METHOD_CALL ||
         member == NULL ||



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