[at-spi2-core/gi: 3/4] Initial commit, not even close to being usable yet



commit 11d647c36278e2430df5df0c56546e267971e74a
Author: Mike Gorse <mgorse novell com>
Date:   Tue Oct 26 10:15:53 2010 -0400

    Initial commit, not even close to being usable yet

 Makefile.am                    |    9 +-
 atspi/atspi-accessible.c       | 1213 ++++++++++++++++++++++++++++++++++++++++
 atspi/atspi-accessible.h       |  101 ++++
 atspi/atspi-constants.h        |  766 +++++++++++++++++++++++++
 atspi/atspi-event-types.h      |  128 +++++
 atspi/atspi-listener-private.h |   37 ++
 atspi/atspi-listener.c         |  383 +++++++++++++
 atspi/atspi-listener.h         |  135 +++++
 atspi/atspi-misc-private.h     |  114 ++++
 atspi/atspi-misc.c             |  828 +++++++++++++++++++++++++++
 atspi/atspi-misc.h             |   36 ++
 atspi/atspi-private.h          |   33 ++
 atspi/atspi-registry.c         |  364 ++++++++++++
 atspi/atspi-registry.h         |   66 +++
 atspi/atspi-stateset.c         |   28 +
 atspi/atspi-stateset.h         |   29 +
 atspi/atspi.h                  |   36 ++
 configure.ac                   |    6 +-
 dbind/Makefile.am              |   22 +
 dbind/dbind-any.c              |  670 ++++++++++++++++++++++
 dbind/dbind-any.h              |   31 +
 dbind/dbind.c                  |  230 ++++++++
 dbind/dbind.h                  |   49 ++
 dbind/dbtest.c                 |  404 +++++++++++++
 xml/Makefile.am                |    6 +-
 25 files changed, 5720 insertions(+), 4 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 68f7dc6..4aba3ef 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,3 +1,10 @@
-SUBDIRS=registryd tools xml bus libspi
+DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
+
+-include $(INTROSPECTION_MAKEFILE)
+INTROSPECTION_GIRS =
+INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir)
+INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
+
+SUBDIRS=registryd xml bus dbind atspi
 
 ACLOCAL_AMFLAGS=-I m4
diff --git a/atspi/atspi-accessible.c b/atspi/atspi-accessible.c
new file mode 100644
index 0000000..2a9d071
--- /dev/null
+++ b/atspi/atspi-accessible.c
@@ -0,0 +1,1213 @@
+/*
+ * 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.
+ *
+ * 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 "atspi-private.h"
+
+G_DEFINE_TYPE (AtspiAccessible, atspi_accessible, G_TYPE_OBJECT)
+
+static void
+atspi_accessible_init (AtspiAccessible *accessible)
+{
+}
+
+static void
+atspi_accessible_class_init (AtspiAccessibleClass *klass)
+{
+}
+/* TODO: Generate following from spec? */
+static const char *role_names [] =
+{
+  "invalid",
+  "accel-label",
+  "alert",
+  "animation",
+  "arrow",
+  "calendar",
+  "canvas",
+  "check-box",
+  "check-menu-item",
+  "color-chooser",
+  "column-header",
+  "combo-box",
+  "date-editor",
+  "desktop-icon",
+  "desktop-frame",
+  "dial",
+  "dialog",
+  "directory-pane",
+  "drawing-area",
+  "file-chooser",
+  "filler",
+  "font-chooser",
+  "frame",
+  "glass-pane",
+  "html-container",
+  "icon",
+  "image",
+  "internalframe",
+  "label",
+  "layered-pane",
+  "list",
+  "list-item",
+  "menu",
+  "menu-bar",
+  "menu-item",
+  "option-pane",
+  "page-tab",
+  "page-tab-list",
+  "panel",
+  "password-text",
+  "popup-menu",
+  "progress-bar",
+  "push-button",
+  "radio-button",
+  "radio-menu-item",
+  "root-pane",
+  "row-header",
+  "scroll-bar",
+  "scroll-pane",
+  "separator",
+  "slider",
+  "spin-button",
+  "split-pane",
+  "statusbar",
+  "table",
+  "table-cell",
+  "table-column-header",
+  "table-row-header",
+  "tear-off-menu-item",
+  "terminal",
+  "text",
+  "toggle-button",
+  "tool-bar",
+  "tool-tip",
+  "tree",
+  "tree-table",
+  "unknown",
+  "viewport",
+  "window",
+  NULL,
+  "header",
+  "fooler",
+  "paragraph",
+  "ruler",
+  "application",
+  "autocomplete",
+  "editbar",
+  "embedded",
+  "entry",
+  "chart",
+  "caption",
+  "document_frame",
+  "heading",
+  "page",
+  "section",
+  "form",
+  "redundant object",
+  "link",
+  "input method window"
+};
+
+#define MAX_ROLES (sizeof (role_names) / sizeof (char *))
+
+/**
+ * atspi_role_get_name
+ * @role: an #AtspiAccessibleRole object to query.
+ *
+ * Get a localizeable string that indicates the name of an #AtspiAccessibleRole.
+ * <em>DEPRECATED.</em>
+ *
+ * Returns: a localizable string name for an #AtspiAccessibleRole enumerated type.
+ **/
+gchar *
+atspi_role_get_name (AtspiRole role)
+{
+  if (role < MAX_ROLES && role_names [(int) role])
+    {
+      return g_strdup (role_names [(int) role]);
+    }
+  else
+    {
+      return g_strdup ("");
+    }
+}
+
+/**
+ * atspi_accessible_get_name:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Get the name of an #AtspiAccessible object.
+ *
+ * Returns: a UTF-8 string indicating the name of the #AtspiAccessible object.
+ * or NULL on exception
+ **/
+gchar *
+atspi_accessible_get_name (AtspiAccessible *obj, GError **error)
+{
+  g_return_val_if_fail (obj != NULL, NULL);
+  return g_strdup (obj->name);
+}
+
+/**
+ * atspi_accessible_get_description:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Get the description of an #AtspiAccessible object.
+ *
+ * Returns: a UTF-8 string describing the #AtspiAccessible object.
+ * or NULL on exception
+ **/
+gchar *
+atspi_accessible_get_description (AtspiAccessible *obj, GError **error)
+{
+  g_return_val_if_fail (obj != NULL, NULL);
+
+  return g_strdup (obj->description);
+}
+
+/**
+ * atspi_accessible_get_parent:
+ * @obj: a pointer to the #AtspiAccessible object to query.
+ *
+ * Get an #AtspiAccessible object's parent container.
+ *
+ * Returns: a pointer tothe #AtspiAccessible object which contains the given
+ *          #AtspiAccessible instance, or NULL if the @obj has no parent container.
+ *
+ **/
+AtspiAccessible *
+atspi_accessible_get_parent (AtspiAccessible *obj, GError **error)
+{
+  g_return_val_if_fail (obj != NULL, NULL);
+
+  return g_object_ref (obj->accessible_parent);
+}
+
+/**
+ * atspi_accessible_get_child_count:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Get the number of children contained by an #AtspiAccessible object.
+ *
+ * Returns: a #long indicating the number of #AtspiAccessible children
+ *          contained by an #AtspiAccessible object. or -1 on exception
+ *
+ **/
+gint
+atspi_accessible_get_child_count (AtspiAccessible *obj, GError *error)
+{
+  g_return_val_if_fail (obj != NULL, -1);
+
+  /* TODO: MANAGES_DESCENDANTS */
+  return g_list_length (obj->children);
+}
+
+/**
+ * atspi_accessible_get_child_at_index:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ * @child_index: a #long indicating which child is specified.
+ *
+ * Get the #AtspiAccessible child of an #AtspiAccessible object at a given index.
+ *
+ * Returns: a pointer to the #AtspiAccessible child object at index
+ *          @child_index. or NULL on exception
+ **/
+AtspiAccessible *
+atspi_accessible_get_child_at_index (AtspiAccessible *obj,
+                            gint    child_index,
+                            GError **error)
+{
+  AtspiAccessible *child;
+
+  g_return_val_if_fail (obj != NULL, NULL);
+
+  /* TODO: ManagesDescendants */
+  child = g_list_nth_data (obj->children, child_index);
+  return g_object_ref (child);
+}
+
+/**
+ * atspi_accessible_get_index_in_parent
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Get the index of an #AtspiAccessible object in its containing #AtspiAccessible.
+ *
+ * Returns: a #glong indicating the index of the #AtspiAccessible object
+ *          in its parent (i.e. containing) #AtspiAccessible instance,
+ *          or -1 if @obj has no containing parent or on exception.
+ **/
+gint
+atspi_accessible_get_index_in_parent (AtspiAccessible *obj, GError **error)
+{
+  GList *l;
+  gint i;
+
+  g_return_val_if_fail (obj != NULL, -1);
+  if (!obj->accessible_parent) return -1;
+  l = obj->accessible_parent->children;
+  while (l)
+  {
+    if (l->data == obj) return i;
+    l = g_list_next (l);
+    i++;
+  }
+  return -1;
+}
+
+typedef struct
+{
+  dbus_uint32_t type;
+  GArray *targets;
+} Accessibility_Relation;
+
+/**
+ * atspi_accessible_get_relation_set:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Get the set of #AtspiRelation objects which describe this #AtspiAccessible object's
+ *       relationships with other #AtspiAccessible objects.
+ *
+ * Returns: an array of #AtspiAccessibleRelation pointers. or NULL on exception
+ * TODO:: Annotate array type
+ **/
+GArray *
+atspi_accessible_get_relation_set (AtspiAccessible *obj, GError **error)
+{
+  int i;
+  int n_relations;
+  GArray *relation_set;
+
+  g_return_val_if_fail (obj != NULL, NULL);
+
+  if (!_atspi_dbus_call (obj, atspi_interface_accessible, "GetRelationSet", error, "=>a(uao)", &relation_set))
+    return NULL;
+
+  return relation_set;
+}
+
+/**
+ * atspi_accessible_get_role:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Get the UI role of an #AtspiAccessible object.
+ * A UTF-8 string describing this role can be obtained via atspi_accessible_getRoleName ().
+ *
+ * Returns: the #AtspiRole of the object.
+ *
+ **/
+AtspiRole
+atspi_accessible_get_role (AtspiAccessible *obj, GError **error)
+{
+  g_return_val_if_fail (obj != NULL, ATSPI_ROLE_INVALID);
+
+  return obj->role;
+}
+
+/**
+ * atspi_accessible_get_role_name:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Get a UTF-8 string describing the role this object plays in the UI.
+ * This method will return useful values for roles that fall outside the
+ * enumeration used in atspi_accessible_getRole ().
+ *
+ * Returns: a UTF-8 string specifying the role of this #AtspiAccessible object.
+ *
+ **/
+gchar *
+atspi_accessible_get_role_name (AtspiAccessible *obj, GError **error)
+{
+  char *retval = NULL;
+
+  g_return_val_if_fail (obj != NULL, g_strdup ("invalid"));
+
+  _atspi_dbus_call (obj, atspi_interface_accessible, "GetRoleName", error, "=>s", &retval);
+
+  return retval;
+}
+
+/**
+ * atspi_accessible_get_localized_role_name:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Get a UTF-8 string describing the (localized) role this object plays in the UI.
+ * This method will return useful values for roles that fall outside the
+ * enumeration used in atspi_accessible_getRole ().
+ *
+ * Returns: a UTF-8 string specifying the role of this #AtspiAccessible object.
+ *
+ **/
+gchar *
+atspi_accessible_get_localized_role_name (AtspiAccessible *obj, GError **error)
+{
+  char *retval = NULL;
+
+  g_return_val_if_fail (obj != NULL, g_strdup ("invalid"));
+
+  _atspi_dbus_call (obj, atspi_interface_accessible, "GetLocalizedRoleName", error, "=>s", &retval);
+
+  return retval;
+}
+
+/**
+ * atspi_accessible_get_state_set:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Gets the current state of an object.
+ *
+ * Returns: a pointer to an #AtspiStateSet representing the object's current state.
+ **/
+AtspiStateSet *
+atspi_accessible_get_state_set (AtspiAccessible *obj)
+{
+  return obj->states;
+}
+
+/**
+ * atspi_accessible_get_attributes:
+ * @obj: The #AtspiAccessible being queried.
+ *
+ * Get the #AttributeSet representing any assigned 
+ * name-value pair attributes or annotations for this object.
+ * For typographic, textual, or textually-semantic attributes, see
+ * atspi_text_get_attributes instead.
+ *
+ * Returns: The name-value-pair attributes assigned to this object.
+ */
+GHashTable *
+atspi_accessible_get_attributes (AtspiAccessible *obj, GError **error)
+{
+  DBusMessage *message;
+  GHashTable *ret;
+
+    g_return_val_if_fail (obj != NULL, NULL);
+
+  message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetAttributes", error, "");
+  ret = _atspi_dbus_hash_from_message (message);
+  dbus_message_unref (message);
+  return ret;
+}
+
+/**
+ * atspi_accessible_get_host_application:
+ * @obj: The #AtspiAccessible being queried.
+ *
+ * Get the containing #AtspiApplication for an object.
+ *
+ * Returns: the containing AtspiApplication instance for this object.
+ */
+AtspiApplication *
+atspi_accessible_get_host_application (AtspiAccessible *obj, GError **error)
+{
+  while (obj->accessible_parent) obj = obj->accessible_parent;
+  g_warning ("atspi: TODO: Application interface");
+  //return atspi_accessible_get_application (obj);
+}
+
+#if 0	// TODO: interfaces */
+/* Interface query methods */
+
+/**
+ * atspi_accessible_is_action:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements #AtspiAction.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiAction interface,
+ *          #FALSE otherwise.
+ **/
+gboolean
+atspi_accessible_is_action (AtspiAccessible *obj)
+{
+  return _atspi_accessible_is_a (obj,
+			      atspi_interface_action);
+}
+
+/**
+ * atspi_accessible_is_application:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements #AtspiApplication.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiApplication interface,
+ *          #FALSE otherwise.
+ **/
+gboolean
+atspi_accessible_is_application (AtspiAccessible *obj)
+{
+  return _atspi_accessible_is_a (obj,
+			      atspi_interface_application);
+}
+
+/**                      
+ * atspi_accessible_is_collection:                                                                                                                                                                          * @obj: a pointer to the #AtspiAccessible instance to query.                                                                                                                                          
+ *                          
+ * Query whether the specified #AtspiAccessible implements #AtspiCollection.    
+ * Returns: #TRUE if @obj implements the #AtspiCollection interface,                                                                                                               
+ *          #FALSE otherwise.
+ **/
+gboolean
+atspi_accessible_is_collection (AtspiAccessible *obj)
+{
+#if 0
+     g_warning ("Collections not implemented");
+     return _atspi_accessible_is_a (obj,
+			      atspi_interface_collection);
+#else
+     return FALSE;
+#endif
+}
+
+/**
+ * atspi_accessible_is_component:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements #AtspiComponent.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiComponent interface,
+ *          #FALSE otherwise.
+ **/
+gboolean
+atspi_accessible_is_component (AtspiAccessible *obj)
+{
+  return _atspi_accessible_is_a (obj,
+			      atspi_interface_component);
+}
+
+/**
+ * atspi_accessible_is_document:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements #AtspiDocument.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiDocument interface,
+ *          #FALSE otherwise.
+ **/
+gboolean
+atspi_accessible_is_document (AtspiAccessible *obj)
+{
+  return _atspi_accessible_is_a (obj,
+			      atspi_interface_document);
+}
+
+/**
+ * atspi_accessible_is_editable_text:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements #AtspiEditableText.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiEditableText interface,
+ *          #FALSE otherwise.
+ **/
+gboolean
+atspi_accessible_is_editable_text (AtspiAccessible *obj)
+{
+  return _atspi_accessible_is_a (obj,
+			      atspi_interface_editable_text);
+}
+                                                                                                                                                                        
+/**
+ * atspi_accessible_is_hypertext:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements #AtspiHypertext.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiHypertext interface,
+ *          #FALSE otherwise.
+ **/
+gboolean
+atspi_accessible_is_hypertext (AtspiAccessible *obj)
+{
+  return _atspi_accessible_is_a (obj,
+			      atspi_interface_hypertext);
+}
+
+/**
+ * atspi_accessible_is_image:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements #AtspiImage.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiImage interface,
+ *          #FALSE otherwise.
+**/
+gboolean
+atspi_accessible_is_image (AtspiAccessible *obj)
+{
+  return _atspi_accessible_is_a (obj,
+			      atspi_interface_image);
+}
+
+/**
+ * atspi_accessible_is_selection:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements #AtspiSelection.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiSelection interface,
+ *          #FALSE otherwise.
+**/
+gboolean
+atspi_accessible_is_selection (AtspiAccessible *obj)
+{
+  return _atspi_accessible_is_a (obj,
+			      atspi_interface_selection);
+}
+
+/**
+ * atspi_accessible_is_table:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements #AtspiTable.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiTable interface,
+ *          #FALSE otherwise.
+**/
+gboolean
+atspi_accessible_is_table (AtspiAccessible *obj)
+{
+  return _atspi_accessible_is_a (obj,
+			      atspi_interface_table);
+}
+
+/**
+ * atspi_accessible_is_streamable_content:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements
+ *          #AtspiStreamableContent.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiStreamableContent interface,
+ *          #FALSE otherwise.
+**/
+gboolean
+atspi_accessible_is_streamable_content (AtspiAccessible *obj)
+{
+#if 0
+  return _atspi_accessible_is_a (obj,
+			      atspi_interface_streamable_content);
+#else
+  g_warning ("Streamable content not implemented");
+  return FALSE;
+#endif
+}
+
+/**
+ * atspi_accessible_is_text:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements #AtspiText.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiText interface,
+ *          #FALSE otherwise.
+**/
+gboolean
+atspi_accessible_is_text (AtspiAccessible *obj)
+{
+  return _atspi_accessible_is_a (obj,
+			      atspi_interface_text);
+}
+
+/**
+ * atspi_accessible_is_value:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements #AtspiValue.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiValue interface,
+ *          #FALSE otherwise.
+**/
+gboolean
+atspi_accessible_is_value (AtspiAccessible *obj)
+{
+  return _atspi_accessible_is_a (obj,
+			      atspi_interface_value);
+}
+
+/**
+ * atspi_accessible_get_application:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Get the #AtspiApplication interface for an #AtspiAccessible.
+ *
+ * Returns: a pointer to an #AtspiApplication interface instance, or
+ *          NULL if @obj does not implement #AtspiApplication.
+ **/
+AtspiApplication *
+atspi_accessible_get_application (AtspiAccessible *obj)
+{
+  return (_atspi_accessible_is_a (accessible, atspi_interface_application) ?
+          ATSPI_APPLICATION (accessible) : NULL);  
+}
+
+/**
+ * atspi_accessible_get_action:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Get the #AtspiAction interface for an #AtspiAccessible.
+ *
+ * Returns: a pointer to an #AtspiAction interface instance, or
+ *          NULL if @obj does not implement #AtspiAction.
+ **/
+AtspiAction *
+atspi_accessible_get_action (AtspiAccessible *obj)
+{
+  return (_atspi_accessible_is_a (accessible, atspi_interface_action) ?
+          ATSPI_APPLICATION (accessible) : NULL);  
+}
+
+/**
+ * atspi_accessible_get_collection:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Get the #AtspiCollection interface for an #AtspiAccessible.
+ *
+ * Returns: a pointer to an #AtspiCollection interface instance, or
+ *          NULL if @obj does not implement #AtspiCollection.
+ **/
+AtspiCollection *
+atspi_accessible_get_collection (AtspiAccessible *obj)
+{
+  return (_atspi_accessible_is_a (accessible, atspi_interface_collection) ?
+          ATSPI_APPLICATION (accessible) : NULL);  
+}
+
+/**
+ * atspi_accessible_get_component:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Get the #AtspiComponent interface for an #AtspiAccessible.
+ *
+ * Returns: a pointer to an #AtspiComponent interface instance, or
+ *          NULL if @obj does not implement #AtspiComponent.
+ **/
+AtspiComponent *
+atspi_accessible_get_component (AtspiAccessible *obj)
+{
+  return (_atspi_accessible_is_a (accessible, atspi_interface_component) ?
+          ATSPI_APPLICATION (accessible) : NULL);  
+}
+
+/**
+ * atspi_accessible_get_document:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Get the #AtspiDocument interface for an #AtspiAccessible.
+ *
+ * Returns: a pointer to an #AtspiDocument interface instance, or
+ *          NULL if @obj does not implement #AtspiDocument.
+ **/
+AtspiDocument *
+atspi_accessible_get_document (AtspiAccessible *obj)
+{
+  return (_atspi_accessible_is_a (accessible, atspi_interface_document) ?
+          ATSPI_APPLICATION (accessible) : NULL);  
+}
+
+/**
+ * atspi_accessible_get_editable_text:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Get the #AtspiEditableText interface for an #AtspiAccessible.
+ *
+ * Returns: a pointer to an #AtspiEditableText interface instance, or
+ *          NULL if @obj does not implement #AtspiEditableText.
+ **/
+AtspiEditableText *
+atspi_accessible_get_editable_text (AtspiAccessible *obj)
+{
+  return (_atspi_accessible_is_a (accessible, atspi_interface_editable_text) ?
+          ATSPI_APPLICATION (accessible) : NULL);  
+}
+
+/**
+ * atspi_accessible_get_hypertext:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Get the #AtspiHypertext interface for an #AtspiAccessible.
+ *
+ * Returns: a pointer to an #AtspiHypertext interface instance, or
+ *          NULL if @obj does not implement #AtspiHypertext.
+ **/
+AtspiHypertext *
+atspi_accessible_get_hypertext (AtspiAccessible *obj)
+{
+  return (_atspi_accessible_is_a (accessible, atspi_interface_hypertext) ?
+          ATSPI_APPLICATION (accessible) : NULL);  
+}
+
+/**
+ * atspi_accessible_get_image:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Get the #AtspiImage interface for an #AtspiAccessible.
+ *
+ * Returns: a pointer to an #AtspiImage interface instance, or
+ *          NULL if @obj does not implement #AtspiImage.
+ **/
+AtspiImage *
+atspi_accessible_get_image (AtspiAccessible *obj)
+{
+  return (_atspi_accessible_is_a (accessible, atspi_interface_image) ?
+          ATSPI_APPLICATION (accessible) : NULL);  
+}
+
+/**
+ * atspi_accessible_get_selection:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Get the #AtspiSelection interface for an #AtspiAccessible.
+ *
+ * Returns: a pointer to an #AtspiSelection interface instance, or
+ *          NULL if @obj does not implement #AtspiSelection.
+ **/
+AtspiSelection *
+atspi_accessible_get_selection (AtspiAccessible *obj)
+{
+  return (_atspi_accessible_is_a (accessible, atspi_interface_selection) ?
+          ATSPI_APPLICATION (accessible) : NULL);  
+}
+
+/**
+ * atspi_accessible_get_streamable_content:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Get the #AtspiStreamableContent interface for an #AtspiAccessible.
+ *
+ * Returns: a pointer to an #AtspiStreamableContent interface instance, or
+ *          NULL if @obj does not implement #AtspiStreamableContent.
+ **/
+AtspiStreamableContent *
+atspi_accessible_get_streamable_content (AtspiAccessible *obj)
+{
+  return (_atspi_accessible_is_a (accessible, atspi_interface_streamable_content) ?
+          ATSPI_APPLICATION (accessible) : NULL);  
+}
+
+/**
+ * atspi_accessible_get_table:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Get the #AtspiTable interface for an #AtspiAccessible.
+ *
+ * Returns: a pointer to an #AtspiTable interface instance, or
+ *          NULL if @obj does not implement #AtspiTable.
+ **/
+AtspiTable *
+atspi_accessible_get_table (AtspiAccessible *obj)
+{
+  return (_atspi_accessible_is_a (accessible, atspi_interface_table) ?
+          ATSPI_APPLICATION (accessible) : NULL);  
+}
+
+/**
+ * atspi_accessible_get_text:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Get the #AtspiTable interface for an #AtspiAccessible.
+ *
+ * Returns: a pointer to an #AtspiTable interface instance, or
+ *          NULL if @obj does not implement #AtspiTable.
+ **/
+AtspiTable *
+atspi_accessible_get_text (AtspiAccessible *obj)
+{
+  return (_atspi_accessible_is_a (accessible, atspi_interface_text) ?
+          ATSPI_APPLICATION (accessible) : NULL);  
+}
+
+/**
+ * atspi_accessible_get_value:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Get the #AtspiTable interface for an #AtspiAccessible.
+ *
+ * Returns: a pointer to an #AtspiTable interface instance, or
+ *          NULL if @obj does not implement #AtspiTable.
+ **/
+AtspiTable *
+atspi_accessible_get_value (AtspiAccessible *obj)
+{
+  return (_atspi_accessible_is_a (accessible, atspi_interface_value) ?
+          ATSPI_APPLICATION (accessible) : NULL);  
+}
+
+static gboolean
+cspi_init_relation_type_table (AccessibleRelationType *relation_type_table)
+{
+  int i;
+  for (i = 0; i < Accessibility_RELATION_LAST_DEFINED; ++i)
+    {
+      relation_type_table [i] = SPI_RELATION_NULL;
+    }
+  relation_type_table [Accessibility_RELATION_NULL] = SPI_RELATION_NULL;
+  relation_type_table [Accessibility_RELATION_LABEL_FOR] = SPI_RELATION_LABEL_FOR;
+  relation_type_table [Accessibility_RELATION_LABELLED_BY] = SPI_RELATION_LABELED_BY;
+  relation_type_table [Accessibility_RELATION_CONTROLLER_FOR] = SPI_RELATION_CONTROLLER_FOR;
+  relation_type_table [Accessibility_RELATION_CONTROLLED_BY] = SPI_RELATION_CONTROLLED_BY;
+  relation_type_table [Accessibility_RELATION_MEMBER_OF] = SPI_RELATION_MEMBER_OF;
+  relation_type_table [Accessibility_RELATION_TOOLTIP_FOR] = SPI_RELATION_NULL;
+  relation_type_table [Accessibility_RELATION_NODE_CHILD_OF] = SPI_RELATION_NODE_CHILD_OF;
+  relation_type_table [Accessibility_RELATION_EXTENDED] = SPI_RELATION_EXTENDED;
+  relation_type_table [Accessibility_RELATION_FLOWS_TO] = SPI_RELATION_FLOWS_TO;
+  relation_type_table [Accessibility_RELATION_FLOWS_FROM] = SPI_RELATION_FLOWS_FROM;
+  relation_type_table [Accessibility_RELATION_SUBWINDOW_OF] = SPI_RELATION_SUBWINDOW_OF;
+  relation_type_table [Accessibility_RELATION_EMBEDS] = SPI_RELATION_EMBEDS;
+  relation_type_table [Accessibility_RELATION_EMBEDDED_BY] = SPI_RELATION_EMBEDDED_BY;
+  relation_type_table [Accessibility_RELATION_POPUP_FOR] = SPI_RELATION_POPUP_FOR;
+  relation_type_table [Accessibility_RELATION_PARENT_WINDOW_OF] = SPI_RELATION_PARENT_WINDOW_OF;
+  relation_type_table [Accessibility_RELATION_DESCRIBED_BY] = SPI_RELATION_DESCRIBED_BY;
+  relation_type_table [Accessibility_RELATION_DESCRIPTION_FOR] = SPI_RELATION_DESCRIPTION_FOR;
+  return TRUE;
+}
+
+static AccessibleRelationType
+cspi_relation_type_from_spi_relation_type (Accessibility_RelationType type)
+{
+  /* array is sized according to IDL RelationType because IDL RelationTypes are the index */	
+  static AccessibleRelationType cspi_relation_type_table [Accessibility_RELATION_LAST_DEFINED];
+  static gboolean is_initialized = FALSE;
+  AccessibleRelationType cspi_type;
+  if (!is_initialized)
+    {
+      is_initialized = cspi_init_relation_type_table (cspi_relation_type_table);	    
+    }
+  if (type >= 0 && type < Accessibility_RELATION_LAST_DEFINED)
+    {
+      cspi_type = cspi_relation_type_table [type];	    
+    }
+  else
+    {
+      cspi_type = SPI_RELATION_NULL;
+    }
+  return cspi_type; 
+}
+/**
+ * AccessibleRelation_getRelationType:
+ * @obj: a pointer to the #AtspiAccessibleRelation object to query.
+ *
+ * Get the type of relationship represented by an #AtspiAccessibleRelation.
+ *
+ * Returns: an #AtspiAccessibleRelationType indicating the type of relation
+ *         encapsulated in this #AtspiAccessibleRelation object.
+ *
+ **/
+AccessibleRelationType
+AccessibleRelation_getRelationType (AccessibleRelation *obj)
+{
+  cspi_return_val_if_fail (obj, SPI_RELATION_NULL);
+  return cspi_relation_type_from_spi_relation_type (obj->type);
+}
+
+/**
+ * AccessibleRelation_getNTargets:
+ * @obj: a pointer to the #AtspiAccessibleRelation object to query.
+ *
+ * Get the number of objects which this relationship has as its
+ *       target objects (the subject is the #AtspiAccessible from which this
+ *       #AtspiAccessibleRelation originated).
+ *
+ * Returns: a short integer indicating how many target objects which the
+ *       originating #AtspiAccessible object has the #AtspiAccessibleRelation
+ *       relationship with.
+ **/
+int
+AccessibleRelation_getNTargets (AccessibleRelation *obj)
+{
+  cspi_return_val_if_fail (obj, -1);
+  return obj->targets->len;
+}
+
+/**
+ * AccessibleRelation_getTarget:
+ * @obj: a pointer to the #AtspiAccessibleRelation object to query.
+ * @i: a (zero-index) integer indicating which (of possibly several) target is requested.
+ *
+ * Get the @i-th target of a specified #AtspiAccessibleRelation relationship.
+ *
+ * Returns: an #AtspiAccessible which is the @i-th object with which the
+ *      originating #AtspiAccessible has relationship specified in the
+ *      #AtspiAccessibleRelation object.
+ *
+ **/
+Accessible *
+AccessibleRelation_getTarget (AccessibleRelation *obj, int i)
+{
+  cspi_return_val_if_fail (obj, NULL);
+
+  if (i < 0 || i >= obj->targets->len) return NULL;
+  return cspi_object_add (
+			 g_array_index (obj->targets, Accessible *, i));
+}
+
+/**
+ * AccessibleStateSet_ref:
+ * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
+ *
+ * Increment the reference count for an #AtspiAccessibleStateSet object.
+ *
+ **/
+void
+AccessibleStateSet_ref (AccessibleStateSet *obj)
+{
+  spi_state_set_cache_ref (obj);
+}
+
+/**
+ * AccessibleStateSet_unref:
+ * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
+ *
+ * Decrement the reference count for an #AtspiAccessibleStateSet object.
+ *
+ **/
+void
+AccessibleStateSet_unref (AccessibleStateSet *obj)
+{
+  spi_state_set_cache_unref (obj);
+}
+
+static Accessibility_StateType
+spi_state_to_dbus (AccessibleState state)
+{
+#define MAP_STATE(a) \
+  case SPI_STATE_##a: \
+    return Accessibility_STATE_##a
+
+  switch (state)
+    {
+      MAP_STATE (INVALID);
+      MAP_STATE (ACTIVE);
+      MAP_STATE (ARMED);
+      MAP_STATE (BUSY);
+      MAP_STATE (CHECKED);
+      MAP_STATE (DEFUNCT);
+      MAP_STATE (EDITABLE);
+      MAP_STATE (ENABLED);
+      MAP_STATE (EXPANDABLE);
+      MAP_STATE (EXPANDED);
+      MAP_STATE (FOCUSABLE);
+      MAP_STATE (FOCUSED);
+      MAP_STATE (HORIZONTAL);
+      MAP_STATE (ICONIFIED);
+      MAP_STATE (MODAL);
+      MAP_STATE (MULTI_LINE);
+      MAP_STATE (MULTISELECTABLE);
+      MAP_STATE (OPAQUE);
+      MAP_STATE (PRESSED);
+      MAP_STATE (RESIZABLE);
+      MAP_STATE (SELECTABLE);
+      MAP_STATE (SELECTED);
+      MAP_STATE (SENSITIVE);
+      MAP_STATE (SHOWING);
+      MAP_STATE (SINGLE_LINE);
+      MAP_STATE (STALE);
+      MAP_STATE (TRANSIENT);
+      MAP_STATE (VERTICAL);
+      MAP_STATE (VISIBLE);
+      MAP_STATE (MANAGES_DESCENDANTS);
+      MAP_STATE (INDETERMINATE);
+      MAP_STATE (TRUNCATED);
+      MAP_STATE (REQUIRED);
+      MAP_STATE (INVALID_ENTRY);
+      MAP_STATE (SUPPORTS_AUTOCOMPLETION);
+      MAP_STATE (SELECTABLE_TEXT);
+      MAP_STATE (IS_DEFAULT);
+      MAP_STATE (VISITED);
+    default:
+      return Accessibility_STATE_INVALID;
+  }
+#undef MAP_STATE
+}	      
+
+/**
+ * AccessibleStateSet_contains:
+ * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
+ * @state: an #AtspiAccessibleState for which the specified #AtspiAccessibleStateSet
+ *       will be queried.
+ *
+ * Determine whether a given #AtspiAccessibleStateSet includes a given state; that is,
+ *       whether @state is true for the stateset in question.
+ *
+ * Returns: #TRUE if @state is true/included in the given #AtspiAccessibleStateSet,
+ *          otherwise #FALSE.
+ *
+ **/
+gboolean
+AccessibleStateSet_contains (AccessibleStateSet *obj,
+			     AccessibleState state)
+{
+  return spi_state_set_cache_contains (obj, spi_state_to_dbus (state));
+}
+
+/**
+ * AccessibleStateSet_add:
+ * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
+ * @state: an #AtspiAccessibleState to be added to the specified #AtspiAccessibleStateSet
+ *
+ * Add a particular #AtspiAccessibleState to an #AtspiAccessibleStateSet (i.e. set the
+ *       given state to #TRUE in the stateset.
+ *
+ **/
+void
+AccessibleStateSet_add (AccessibleStateSet *obj,
+			AccessibleState state)
+{
+  spi_state_set_cache_add (obj, spi_state_to_dbus (state));
+}
+
+/**
+ * AccessibleStateSet_remove:
+ * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
+ * @state: an #AtspiAccessibleState to be removed from the specified #AtspiAccessibleStateSet
+ *
+ * Remove a particular #AtspiAccessibleState to an #AtspiAccessibleStateSet (i.e. set the
+ *       given state to #FALSE in the stateset.)
+ *
+ **/
+void
+AccessibleStateSet_remove (AccessibleStateSet *obj,
+			   AccessibleState state)
+{
+  spi_state_set_cache_remove (obj, spi_state_to_dbus (state));
+}
+
+/**
+ * AccessibleStateSet_equals:
+ * @obj: a pointer to the first #AtspiAccessibleStateSet object on which to operate.
+ * @obj2: a pointer to the second #AtspiAccessibleStateSet object on which to operate.
+ *
+ * Determine whether two instances of #AtspiAccessibleStateSet are equivalent (i.e.
+ *         consist of the same #AtspiAccessibleStates).  Useful for checking multiple
+ *         state variables at once; construct the target state then compare against it.
+ *
+ * @see AccessibleStateSet_compare().
+ *
+ * Returns: #TRUE if the two #AtspiAccessibleStateSets are equivalent,
+ *          otherwise #FALSE.
+ *
+ **/
+gboolean
+AccessibleStateSet_equals (AccessibleStateSet *obj,
+                           AccessibleStateSet *obj2)
+{
+  gboolean   eq;
+  AtkStateSet *cmp;
+
+  if (obj == obj2)
+    {
+      return TRUE;
+    }
+
+  cmp = spi_state_set_cache_xor (obj, obj2);
+  eq = spi_state_set_cache_is_empty (cmp);
+  spi_state_set_cache_unref (cmp);
+
+  return eq;
+}
+
+/**
+ * AccessibleStateSet_compare:
+ * @obj: a pointer to the first #AtspiAccessibleStateSet object on which to operate.
+ * @obj2: a pointer to the second #AtspiAccessibleStateSet object on which to operate.
+ *
+ * Determine the differences between two instances of #AtspiAccessibleStateSet.
+ * Not Yet Implemented.
+ *.
+ * @see AccessibleStateSet_equals().
+ *
+ * Returns: an #AtspiAccessibleStateSet object containing all states contained on one of
+ *          the two sets but not the other.
+ *
+ **/
+AccessibleStateSet *
+AccessibleStateSet_compare (AccessibleStateSet *obj,
+                            AccessibleStateSet *obj2)
+{
+  return spi_state_set_cache_xor (obj, obj2);
+}
+
+/**
+ * AccessibleStateSet_isEmpty:
+ * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
+ *
+ * Determine whether a given #AtspiAccessibleStateSet is the empty set.
+ *
+ * Returns: #TRUE if the given #AtspiAccessibleStateSet contains no (true) states,
+ *          otherwise #FALSE.
+ *
+ **/
+gboolean
+AccessibleStateSet_isEmpty (AccessibleStateSet *obj)
+{
+  return spi_state_set_cache_is_empty (obj);
+}
+
+gboolean
+_atspi_accessible_is_a (AtspiAccessible *accessible,
+		      const char *interface_name)
+{
+  int n;
+
+  if (accessible == NULL)
+    {
+      return FALSE;
+    }
+
+  n = get_iface_num (interface_name);
+  if (n == -1) return FALSE;
+  return (gbooleanean)((accessible->interfaces & (1 << n))? TRUE: FALSE);
+}
+#endif
+
+/* TODO: Move to a finalizer */
+static void
+cspi_object_destroyed (AtspiAccessible *accessible)
+{
+  gboolean cached;
+  AtspiEvent e;
+
+  /* TODO: Only fire if object not already marked defunct */
+  memset (&e, 0, sizeof(e));
+  e.type = "object:state-change:defunct";
+  e.source = accessible;
+  e.detail1 = 1;
+  atspi_dispatch_event (&e);
+
+    g_free (accessible->path);
+
+    if (accessible->states)
+      g_object_unref (accessible->states);
+    g_free (accessible->description);
+    g_free (accessible->name);
+}
+
+AtspiAccessible *
+atspi_accessible_new ()
+{
+  AtspiAccessible *accessible;
+  
+  accessible = g_object_new (ATSPI_TYPE_ACCESSIBLE, NULL);
+  g_return_val_if_fail (accessible != NULL, NULL);
+
+  return accessible;
+}
diff --git a/atspi/atspi-accessible.h b/atspi/atspi-accessible.h
new file mode 100644
index 0000000..56e2888
--- /dev/null
+++ b/atspi/atspi-accessible.h
@@ -0,0 +1,101 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ *           2002 Sun Microsystems Inc.
+ *           
+ *
+ * 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 _ATSPI_ACCESSIBLE_H_
+#define _ATSPI_ACCESSIBLE_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+#include "atspi-stateset.h"
+
+#define ATSPI_TYPE_ACCESSIBLE                        (atspi_accessible_get_type ())
+#define ATSPI_ACCESSIBLE(obj)                        (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_ACCESSIBLE, AtspiAccessible))
+#define ATSPI_ACCESSIBLE_CLASS(klass)                (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_ACCESSIBLE, AtspiAccessibleClass))
+#define ATSPI_IS_ACCESSIBLE(obj)                     (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_ACCESSIBLE))
+#define ATSPI_IS_ACCESSIBLE_CLASS(klass)             (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_ACCESSIBLE))
+#define ATSPI_ACCESSIBLE_GET_CLASS(obj)              (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_ACCESSIBLE, AtspiAccessibleClass))
+
+typedef struct _AtspiApplication AtspiApplication;
+struct _AtspiApplication
+{
+  GHashTable *hash;
+  char *bus_name;
+  struct _AtspiAccessible *root;
+};
+
+typedef struct _AtspiAccessible AtspiAccessible;
+struct _AtspiAccessible
+{
+  GObject parent;
+  gint ref_count;
+  AtspiAccessible *accessible_parent;
+  GList *children;
+  AtspiApplication *app;
+  char *path;
+  gint role : 8;
+  gint interfaces : 24;
+  char *name;
+  char *description;
+  AtspiStateSet *states;
+};
+
+typedef struct _AtspiAccessibleClass AtspiAccessibleClass;
+struct _AtspiAccessibleClass
+{
+  GObjectClass parent_class;
+};
+
+AtspiAccessible *
+atspi_accessible_new ();
+
+gchar * atspi_role_get_name (AtspiRole role);
+
+gchar * atspi_accessible_get_name (AtspiAccessible *obj, GError **error);
+
+gchar * atspi_accessible_get_description (AtspiAccessible *obj, GError **error);
+
+AtspiAccessible * atspi_accessible_get_parent (AtspiAccessible *obj, GError **error);
+
+gint atspi_accessible_get_child_count (AtspiAccessible *obj, GError *error);
+
+AtspiAccessible * atspi_accessible_get_child_at_index (AtspiAccessible *obj, gint    child_index, GError **error);
+
+gint atspi_accessible_get_index_in_parent (AtspiAccessible *obj, GError **error);
+
+GArray * atspi_accessible_get_relation_set (AtspiAccessible *obj, GError **error);
+
+AtspiRole atspi_accessible_get_role (AtspiAccessible *obj, GError **error);
+
+gchar * atspi_accessible_get_role_name (AtspiAccessible *obj, GError **error);
+
+gchar * atspi_accessible_get_localized_role_name (AtspiAccessible *obj, GError **error);
+
+AtspiStateSet * atspi_accessible_get_state_set (AtspiAccessible *obj);
+
+GHashTable * atspi_accessible_get_attributes (AtspiAccessible *obj, GError **error);
+
+AtspiApplication * atspi_accessible_get_host_application (AtspiAccessible *obj, GError **error);
+
+#endif	/* _ATSPI_ACCESSIBLE_H_ */
diff --git a/atspi/atspi-constants.h b/atspi/atspi-constants.h
new file mode 100644
index 0000000..a011645
--- /dev/null
+++ b/atspi/atspi-constants.h
@@ -0,0 +1,766 @@
+/* TODO: Auto-generate this file again
+
+
+
+ !\mainpage AT-SPI Interfaces and Subinterfaces
+
+  This is the main documentation page for the 
+  Assistive Technology Service Provider Interface (AT-SPI). 
+  
+  \section apps Applications and Interface Components
+  Namespace Accessibility includes service APIs implemented by
+  participating applications and their user interface components:\n\n
+  Accessibility::Accessible\n 
+  Accessibility::Application\n
+  Accessibility::Desktop\n
+  Accessibility::Collecgtion\n
+  Accessibility::Component\n
+  Accessibility::Hypertext\n
+  Accessibility::Image\n
+  Accessibility::Selection\n
+  Accessibility::Table\n
+  Accessibility::Text\n
+  Accessibility::EditableText\n
+  Accessibility::Value
+ 
+  \section types Enumerated Types
+  Accessibility defines a number of key enumerated types, including:\n\n
+  Accessibility::RelationType\n
+  Accessibility::Role\n
+  Accessibility::StateType\n
+  Accessibility::Event\n
+  Accessibility::EventDetails \n
+ 
+  \section Registry
+  Accessibility also includes Accessibility::Registry,
+  which is the service used by assistive technologies and related
+  AT-SPI clients to register interest in certain classes of events,
+  enumerate the currently available desktop and application list,
+  and to synthesize certain kinds of device events.
+ 
+  \section listeners Event Listener Interfaces
+  Accessibility::EventListener\n
+  Accessibility::DeviceEventListener
+ 
+  \section helpers Helper Interfaces
+ 
+  The following interfaces may be implemented by assistive technologies 
+  themselves, in order to export their services in a consistent manner or
+  in order to interoperate with other applications or desktop services.\n
+ 
+  Accessibility::LoginHelper : Implemented by adaptive technologies which 
+  need to participate in user-authentication or login activities, and which
+  therefore may need negotiation with authentication agents or processes.\n
+ 
+  Accessibility::Selector [NEW]: Implemented by user agents or assistive 
+  technologies which export lists of choices from which the end-user is 
+  expected to make selections.  Useful for various types of remote
+  activation or intercommunication between multiple ATs.
+
+ */
+
+#ifndef _ATSPI_CONSTANTS_H_
+#define _ATSPI_CONSTANTS_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *
+ATSPI_LOCALE_TYPE:
+ * @ATSPI_LOCALE_TYPE_MESSAGES: <![CDATA[]]>
+ * @ATSPI_LOCALE_TYPE_COLLATE: <![CDATA[]]>
+ * @ATSPI_LOCALE_TYPE_CTYPE: <![CDATA[]]>
+ * @ATSPI_LOCALE_TYPE_MONETARY: <![CDATA[]]>
+ * @ATSPI_LOCALE_TYPE_NUMERIC: <![CDATA[]]>
+ * @ATSPI_LOCALE_TYPE_TIME: <![CDATA[]]>
+ *
+ * <![CDATA[   Used by Text and Document interfaces these correspond to the POSIX 'setlocale' enum values.    ]]>
+ *
+ * Bitfield/set of flags generated from the AT-SPI specification.
+ */
+typedef enum {
+    ATSPI_LOCALE_TYPE_MESSAGES,
+    ATSPI_LOCALE_TYPE_COLLATE,
+    ATSPI_LOCALE_TYPE_CTYPE,
+    ATSPI_LOCALE_TYPE_MONETARY,
+    ATSPI_LOCALE_TYPE_NUMERIC,
+    ATSPI_LOCALE_TYPE_TIME,
+} AtspiLocaleType;
+
+/**
+ * NUM_ATSPI_LOCALE_TYPES:
+ *
+ * 1 higher than the highest valid value of #AtspiLocaleType.
+ */
+#define NUM_ATSPI_LOCALE_TYPES (5+1)
+
+/**
+ *
+ATSPI_COORD_TYPE:
+ * @ATSPI_COORD_TYPE_SCREEN: <![CDATA[]]>
+ * @ATSPI_COORD_TYPE_WINDOW: <![CDATA[]]>
+ *
+ * <![CDATA[   Used by Component, Image, and Text interfaces to specify whether coordinates are relative to the window or the screen.   ]]>
+ *
+ * Bitfield/set of flags generated from the AT-SPI specification.
+ */
+typedef enum {
+    ATSPI_COORD_TYPE_SCREEN,
+    ATSPI_COORD_TYPE_WINDOW,
+} AtspiCoordType;
+
+/**
+ * NUM_ATSPI_COORD_TYPES:
+ *
+ * 1 higher than the highest valid value of #AtspiCoordType.
+ */
+#define NUM_ATSPI_COORD_TYPES (1+1)
+
+/**
+ *
+ATSPI_Collection_SortOrder:
+ * @ATSPI_Collection_SORT_ORDER_INVALID: <![CDATA[]]>
+ * @ATSPI_Collection_SORT_ORDER_CANONICAL: <![CDATA[]]>
+ * @ATSPI_Collection_SORT_ORDER_FLOW: <![CDATA[]]>
+ * @ATSPI_Collection_SORT_ORDER_TAB: <![CDATA[]]>
+ * @ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL: <![CDATA[]]>
+ * @ATSPI_Collection_SORT_ORDER_REVERSE_FLOW: <![CDATA[]]>
+ * @ATSPI_Collection_SORT_ORDER_REVERSE_TAB: <![CDATA[]]>
+ * @ATSPI_Collection_SORT_ORDER_LAST_DEFINED: <![CDATA[]]>
+ *
+ * Bitfield/set of flags generated from the AT-SPI specification.
+ */
+typedef enum {
+    ATSPI_Collection_SORT_ORDER_INVALID,
+    ATSPI_Collection_SORT_ORDER_CANONICAL,
+    ATSPI_Collection_SORT_ORDER_FLOW,
+    ATSPI_Collection_SORT_ORDER_TAB,
+    ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL,
+    ATSPI_Collection_SORT_ORDER_REVERSE_FLOW,
+    ATSPI_Collection_SORT_ORDER_REVERSE_TAB,
+    ATSPI_Collection_SORT_ORDER_LAST_DEFINED,
+} AtspiCollectionSortOrder;
+
+/**
+ * NUM_ATSPI_SORTORDERS:
+ *
+ * 1 higher than the highest valid value of #AtspiCollectionSortOrder.
+ */
+#define NUM_ATSPI_SORTORDERS (7+1)
+
+/**
+ *
+ATSPI_Collection_MatchType:
+ * @ATSPI_Collection_MATCH_INVALID: <![CDATA[]]>
+ * @ATSPI_Collection_MATCH_ALL: <![CDATA[]]>
+ * @ATSPI_Collection_MATCH_ANY: <![CDATA[]]>
+ * @ATSPI_Collection_MATCH_NONE: <![CDATA[]]>
+ * @ATSPI_Collection_MATCH_EMPTY: <![CDATA[]]>
+ * @ATSPI_Collection_MATCH_LAST_DEFINED: <![CDATA[]]>
+ *
+ * Bitfield/set of flags generated from the AT-SPI specification.
+ */
+typedef enum {
+    ATSPI_Collection_MATCH_INVALID,
+    ATSPI_Collection_MATCH_ALL,
+    ATSPI_Collection_MATCH_ANY,
+    ATSPI_Collection_MATCH_NONE,
+    ATSPI_Collection_MATCH_EMPTY,
+    ATSPI_Collection_MATCH_LAST_DEFINED,
+} AtspiCollectionMatchType;
+
+/**
+ * NUM_ATSPI_MATCHTYPES:
+ *
+ * 1 higher than the highest valid value of #AtspiCollection_MatchType.
+ */
+#define NUM_ATSPI_MATCHTYPES (5+1)
+
+/**
+ *
+ATSPI_Collection_TreeTraversalType:
+ * @ATSPI_Collection_TREE_RESTRICT_CHILDREN: <![CDATA[]]>
+ * @ATSPI_Collection_TREE_RESTRICT_SIBLING: <![CDATA[]]>
+ * @ATSPI_Collection_TREE_INORDER: <![CDATA[]]>
+ * @ATSPI_Collection_TREE_LAST_DEFINED: <![CDATA[]]>
+ *
+ * Bitfield/set of flags generated from the AT-SPI specification.
+ */
+typedef enum {
+    ATSPI_Collection_TREE_RESTRICT_CHILDREN,
+    ATSPI_Collection_TREE_RESTRICT_SIBLING,
+    ATSPI_Collection_TREE_INORDER,
+    ATSPI_Collection_TREE_LAST_DEFINED,
+} AtspiCollectionTreeTraversalType;
+
+/**
+ * NUM_ATSPI_TREETRAVERSALTYPES:
+ *
+ * 1 higher than the highest valid value of #AtspiCollection_TreeTraversalType.
+ */
+#define NUM_ATSPI_TREETRAVERSALTYPES (3+1)
+
+/**
+ *
+ATSPI_ComponentLayer:
+ * @ATSPI_LAYER_INVALID: <![CDATA[     Indicates an error condition or uninitialized value.    ]]>
+ * @ATSPI_LAYER_BACKGROUND: <![CDATA[     The bottom-most layer, over which everything else is painted.        The 'desktop background' is generally in this layer.    ]]>
+ * @ATSPI_LAYER_CANVAS: <![CDATA[     The 'background' layer for most content renderers and UI Component        containers.    ]]>
+ * @ATSPI_LAYER_WIDGET: <![CDATA[     The layer in which the majority of ordinary 'foreground' widgets reside.   ]]>
+ * @ATSPI_LAYER_MDI: <![CDATA[     A special layer between LAYER_CANVAS and LAYER_WIDGET, in which the       'pseudo windows' (e.g. the MDI frames) reside.        (See Component.GetMDIZOrder)    ]]>
+ * @ATSPI_LAYER_POPUP: <![CDATA[     A layer for popup window content, above LAYER_WIDGET.    ]]>
+ * @ATSPI_LAYER_OVERLAY: <![CDATA[     The topmost layer.    ]]>
+ * @ATSPI_LAYER_WINDOW: <![CDATA[     The layer in which a toplevel window background usually resides.    ]]>
+ * @ATSPI_LAYER_LAST_DEFINED: <![CDATA[     Used only to determine the end of the enumeration.    ]]>
+ *
+ * <![CDATA[     The ComponentLayer of a Component instance indicates its relative stacking order       with respect to the onscreen visual representation of the UI.       ComponentLayer, in combination with Component bounds information, can be used       to compute the visibility of all or part of a component.  This is important in       programmatic determination of region-of-interest for magnification, and in       &#168;flat screen review&#168; models of the screen, as well as for other uses.       Objects residing in two of the ComponentLayer categories support       further z-ordering information, with respect to their peers in the same layer:       namely, LAYER_WINDOW and LAYER_MDI.  Relative stacking order for other objects within       the same layer is not available; the recommended heuristic is &#168;first child paints first&#168;,        in other words, assume that the first siblings in the child list are subject to being       overpainted by later siblings if t
 heir bounds intersect.        The order of layers, from bottom to top, is: 	     	    	LAYER_BACKGROUND 	    	LAYER_WINDOW 	    	LAYER_MDI 	    	LAYER_CANVAS 	    	LAYER_WIDGET 	    	LAYER_POPUP 	    	LAYER_OVERLAY 	            ]]>
+ *
+ * Bitfield/set of flags generated from the AT-SPI specification.
+ */
+typedef enum {
+    ATSPI_LAYER_INVALID,
+    ATSPI_LAYER_BACKGROUND,
+    ATSPI_LAYER_CANVAS,
+    ATSPI_LAYER_WIDGET,
+    ATSPI_LAYER_MDI,
+    ATSPI_LAYER_POPUP,
+    ATSPI_LAYER_OVERLAY,
+    ATSPI_LAYER_WINDOW,
+    ATSPI_LAYER_LAST_DEFINED,
+} AtspiComponentLayer;
+
+/**
+ * NUM_ATSPI_COMPONENTLAYERS:
+ *
+ * 1 higher than the highest valid value of #AtspiComponentLayer.
+ */
+#define NUM_ATSPI_COMPONENTLAYERS (8+1)
+
+/**
+ *
+ATSPI_TEXT_BOUNDARY_TYPE:
+ * @ATSPI_TEXT_BOUNDARY_CHAR: <![CDATA[     Text is bounded by this character only.        Start and end offsets differ by one, by definition, for this value.    ]]>
+ * @ATSPI_TEXT_BOUNDARY_WORD_START: <![CDATA[     Boundary condition is start of a word; i.e. range is from start of       one word to the start of another word.    ]]>
+ * @ATSPI_TEXT_BOUNDARY_WORD_END: <![CDATA[     Boundary condition is the end of a word; i.e. range is from  	    the end of one word to the end of another.     Some locales may not distinguish between words and       characters or glyphs, in particular those locales which use       wholly or partially ideographic character sets.  In these cases,       characters may be returned in lieu of multi-character substrings.   ]]>
+ * @ATSPI_TEXT_BOUNDARY_SENTENCE_START: <![CDATA[     Boundary condition is start of a sentence, as determined  	    by the application.       Some locales or character sets may not include explicit sentence       delimiters, so this boundary type can not always be honored.       Some locales will return lines of text instead of grammatical sentences.   ]]>
+ * @ATSPI_TEXT_BOUNDARY_SENTENCE_END: <![CDATA[     Boundary condition is end of a sentence, as determined by the application,  	    including the sentence-delimiting character, for instance '.'       Some locales or character sets may not include explicit sentence       delimiters, so this boundary type can not always be honored.       Some locales will return lines of text instead of grammatical sentences.   ]]>
+ * @ATSPI_TEXT_BOUNDARY_LINE_START: <![CDATA[      Boundary condition is the start of a line; i.e. range is        from start of one line to the start of another.  This generally        means that an end-of-line character will appear at the end of the range.    ]]>
+ * @ATSPI_TEXT_BOUNDARY_LINE_END: <![CDATA[      Boundary condition is the end of a line; i.e. range is       from start of one line to the start of another.  This generally        means that an end-of-line character will be the first character of the range.    ]]>
+ *
+ * <![CDATA[     Specifies the boundary conditions determining a run of text as returned from       GetTextAtOffset, GetTextAfterOffset, and GetTextBeforeOffset.   ]]>
+ *
+ * Bitfield/set of flags generated from the AT-SPI specification.
+ */
+typedef enum {
+    ATSPI_TEXT_BOUNDARY_CHAR,
+    ATSPI_TEXT_BOUNDARY_WORD_START,
+    ATSPI_TEXT_BOUNDARY_WORD_END,
+    ATSPI_TEXT_BOUNDARY_SENTENCE_START,
+    ATSPI_TEXT_BOUNDARY_SENTENCE_END,
+    ATSPI_TEXT_BOUNDARY_LINE_START,
+    ATSPI_TEXT_BOUNDARY_LINE_END,
+} AtspiTextBoundaryType;
+
+/**
+ * NUM_ATSPI_TEXT_BOUNDARY_TYPES:
+ *
+ * 1 higher than the highest valid value of #AtspiTextBOundaryType.
+ */
+#define NUM_ATSPI_TEXT_BOUNDARY_TYPES (6+1)
+
+/**
+ *
+ATSPI_TEXT_CLIP_TYPE:
+ * @ATSPI_TEXT_CLIP_NONE: <![CDATA[]]>
+ * @ATSPI_TEXT_CLIP_MIN: <![CDATA[     Characters/glyphs clipped by the minimum coordinate are omitted    ]]>
+ * @ATSPI_TEXT_CLIP_MAX: <![CDATA[     Characters/glyphs which intersect the maximum coordinate are omitted    ]]>
+ * @ATSPI_TEXT_CLIP_BOTH: <![CDATA[     Only glyphs falling entirely within the region bounded by min and max are retained.    ]]>
+ *
+ * <![CDATA[     TEXT_CLIP_TYPE:       CLIP_MIN means text clipped by min coordinate is omitted,       CLIP_MAX clips text interescted by the max coord, and CLIP_BOTH       will retain only text falling fully within the min/max bounds.     ]]>
+ *
+ * Bitfield/set of flags generated from the AT-SPI specification.
+ */
+typedef enum {
+    ATSPI_TEXT_CLIP_NONE,
+    ATSPI_TEXT_CLIP_MIN,
+    ATSPI_TEXT_CLIP_MAX,
+    ATSPI_TEXT_CLIP_BOTH,
+} AtspiTextClipType;
+
+/**
+ * NUM_ATSPI_TEXT_CLIP_TYPES:
+ *
+ * 1 higher than the highest valid value of #AtspiTextClipType.
+ */
+#define NUM_ATSPI_TEXT_CLIP_TYPES (3+1)
+
+/**
+ *
+ATSPI_StateType:
+ * @ATSPI_STATE_INVALID: <![CDATA[]]>
+ * @ATSPI_STATE_ACTIVE: <![CDATA[     Indicates a window is currently the active window, or is an active subelement within a container or table    ]]>
+ * @ATSPI_STATE_ARMED: <![CDATA[     Indicates that the object is armed    ]]>
+ * @ATSPI_STATE_BUSY: <![CDATA[     Indicates the current object is busy, i.e. onscreen representation is in the process of changing, or       the object is temporarily unavailable for interaction due to activity already in progress.   ]]>
+ * @ATSPI_STATE_CHECKED: <![CDATA[     Indicates this object is currently checked    ]]>
+ * @ATSPI_STATE_COLLAPSED: <![CDATA[     Indicates this object is collapsed    ]]>
+ * @ATSPI_STATE_DEFUNCT: <![CDATA[     Indicates that this object no longer has a valid backing widget        (for instance, if its peer object has been destroyed)    ]]>
+ * @ATSPI_STATE_EDITABLE: <![CDATA[     Indicates the user can change the contents of this object    ]]>
+ * @ATSPI_STATE_ENABLED: <![CDATA[     Indicates that this object is enabled, i.e. that it currently reflects some application state.        Objects that are "greyed out" may lack this state, and may lack the STATE_SENSITIVE if direct user       interaction cannot cause them to acquire STATE_ENABLED.  @see STATE_SENSITIVE.   ]]>
+ * @ATSPI_STATE_EXPANDABLE: <![CDATA[     Indicates this object allows progressive disclosure of its children    ]]>
+ * @ATSPI_STATE_EXPANDED: <![CDATA[     Indicates this object its expanded    ]]>
+ * @ATSPI_STATE_FOCUSABLE: <![CDATA[     Indicates this object can accept keyboard focus, which means all       events resulting from typing on the keyboard will normally be passed       to it when it has focus   ]]>
+ * @ATSPI_STATE_FOCUSED: <![CDATA[     Indicates this object currently has the keyboard focus    ]]>
+ * @ATSPI_STATE_HAS_TOOLTIP: <![CDATA[     Indicates that the object has an associated tooltip    ]]>
+ * @ATSPI_STATE_HORIZONTAL: <![CDATA[     Indicates the orientation of thsi object is horizontal    ]]>
+ * @ATSPI_STATE_ICONIFIED: <![CDATA[     Indicates this object is minimized and is represented only by an icon    ]]>
+ * @ATSPI_STATE_MODAL: <![CDATA[     Indicates something must be done with this object before the user can       interact with an object in a different window.   ]]>
+ * @ATSPI_STATE_MULTI_LINE: <![CDATA[     Indicates this (text) object can contain multiple lines of text    ]]>
+ * @ATSPI_STATE_MULTISELECTABLE: <![CDATA[     Indicates this object allows more than one of its children to be       selected at the same time, or in the case of text objects,        that the object supports non-contiguous text selections.   ]]>
+ * @ATSPI_STATE_OPAQUE: <![CDATA[     Indicates this object paints every pixel within its rectangular region.       It also indicates an alpha value of unity, if it supports alpha blending.    ]]>
+ * @ATSPI_STATE_PRESSED: <![CDATA[     Indicates this object is currently pressed    ]]>
+ * @ATSPI_STATE_RESIZABLE: <![CDATA[     Indicates the size of this object's size is not fixed    ]]>
+ * @ATSPI_STATE_SELECTABLE: <![CDATA[     Indicates this object is the child of an object that allows its       children to be selected and that this child is one of those children       that can be selected.   ]]>
+ * @ATSPI_STATE_SELECTED: <![CDATA[     Indicates this object is the child of an object that allows its       children to be selected and that this child is one of those children       that has been selected.   ]]>
+ * @ATSPI_STATE_SENSITIVE: <![CDATA[     Indicates this object is sensitive, e.g. to user interaction.        STATE_SENSITIVE usually accompanies STATE_ENABLED for user-actionable controls,       but may be found in the absence of STATE_ENABLED if the current visible state of the        control is "disconnected" from the application state.  In such cases, direct user interaction       can often result in the object gaining STATE_SENSITIVE, for instance if a user makes        an explicit selection using an object whose current state is ambiguous or undefined.       @see STATE_ENABLED, STATE_INDETERMINATE.    ]]>
+ * @ATSPI_STATE_SHOWING: <![CDATA[     Indicates this object, the object's parent, the object's parent's       parent, and so on, are all 'shown' to the end-user, i.e.       subject to "exposure" if blocking or obscuring objects do not interpose       between this object and the top of the window stack.   ]]>
+ * @ATSPI_STATE_SINGLE_LINE: <![CDATA[     Indicates this (text) object can contain only a single line of text    ]]>
+ * @ATSPI_STATE_STALE: <![CDATA[     Indicates that the information returned for this object may no longer be       synchronized with the application state.  This can occur if the object has STATE_TRANSIENT,       and can also occur towards the end of the object peer's lifecycle.    ]]>
+ * @ATSPI_STATE_TRANSIENT: <![CDATA[     Indicates this object is transient    ]]>
+ * @ATSPI_STATE_VERTICAL: <![CDATA[     Indicates the orientation of this object is vertical; for example this state may appear on        such objects as scrollbars, text objects (with vertical text flow), separators, etc.   ]]>
+ * @ATSPI_STATE_VISIBLE: <![CDATA[ 	  Indicates this object is visible, e.g. has been explicitly marked for exposure to the user. 	  STATE_VISIBLE is no guarantee that the object is actually unobscured on the screen, only       that it is 'potentially' visible, barring obstruction, being scrolled or clipped out of the        field of view, or having an ancestor container that has not yet made visible.       A widget is potentially onscreen if it has both STATE_VISIBLE and STATE_SHOWING.       The absence of STATE_VISIBLE and STATE_SHOWING is semantically equivalent to saying        that an object is 'hidden'.   ]]>
+ * @ATSPI_STATE_MANAGES_DESCENDANTS: <![CDATA[     Indicates that "active-descendant-changed" event is sent when children       become 'active' (i.e. are selected or navigated to onscreen).  Used to       prevent need to enumerate all children in very large containers, like       tables.  The presence of STATE_MANAGES_DESCENDANTS is an indication to the client.       that the children should not, and need not, be enumerated by the client.       Objects implementing this state are expected to provide relevant state       notifications to listening clients, for instance notifications of visibility       changes and activation of their contained child objects, without the client        having previously requested references to those children.   ]]>
+ * @ATSPI_STATE_INDETERMINATE: <![CDATA[     Indicates that a check box or other boolean indicator is in a state other than        checked or not checked.  This usually means that the boolean value reflected or        controlled by the object does not apply consistently to the entire current context.       For example, a checkbox for the "Bold" attribute of text may have STATE_INDETERMINATE       if the currently selected text contains a mixture of weight attributes.         In many cases interacting with a STATE_INDETERMINATE object will cause        the context's corresponding boolean attribute to be homogenized, whereupon the object       will lose STATE_INDETERMINATE and a corresponding state-changed event will be fired.   ]]>
+ * @ATSPI_STATE_REQUIRED: <![CDATA[     Indicates that user interaction with this object is 'required' from the user,        for instance before completing the processing of a form.   ]]>
+ * @ATSPI_STATE_TRUNCATED: <![CDATA[ 	  Indicates that an object's onscreen content is truncated, e.g. a text value in a spreadsheet cell.    ]]>
+ * @ATSPI_STATE_ANIMATED: <![CDATA[     Indicates this object's visual representation is dynamic, not static.       This state may be applied to an object during an animated 'effect' and        be removed from the object once its visual representation becomes static.     some applications, notably content viewers, may not be able to detect       all kinds of animated content.  Therefore the absence of this state should not       be taken as definitive evidence that the object's visual representation is       static; this state is advisory.   ]]>
+ * @ATSPI_STATE_INVALID_ENTRY: <![CDATA[     This object has indicated an error condition due to failure of input       validation.  For instance, a form control may acquire this state in response       to invalid or malformed user input.     ]]>
+ * @ATSPI_STATE_SUPPORTS_AUTOCOMPLETION: <![CDATA[     This state indicates that the object in question implements some form of &#168;typeahead&#168; or        pre-selection behavior whereby entering the first character of one or more sub-elements       causes those elements to scroll into view or become selected.  Subsequent character input       may narrow the selection further as long as one or more sub-elements match the string.       This state is normally only useful and encountered on objects that implement Selection.       In some cases the typeahead behavior may result in full or partial &#168;completion&#168; of        the data in the input field, in which case these input events may trigger text-changed       events from the source.     ]]>
+ * @ATSPI_STATE_SELECTABLE_TEXT: <![CDATA[     This state indicates that the object in question supports text selection.        It should only be exposed on objects which implement the Text interface,        in order to distinguish this state from STATE_SELECTABLE, which infers that       the object in question is a selectable child of an object which implements       Selection.  While similar, text selection and subelement selection are       distinct operations.     ]]>
+ * @ATSPI_STATE_IS_DEFAULT: <![CDATA[     This state indicates that the object in question is the 'default' interaction object        in a dialog, i.e. the one that gets activated if the user presses "Enter" when the       dialog is initially posted.     ]]>
+ * @ATSPI_STATE_VISITED: <![CDATA[     This state indicates that the object (typically a hyperlink)       has already been activated or invoked, with the result that some backing data       has been downloaded or rendered.     ]]>
+ * @ATSPI_STATE_LAST_DEFINED: <![CDATA[     This value of the enumeration should not be used as a parameter, it indicates the number of       items in the StateType enumeration.   ]]>
+ *
+ * Bitfield/set of flags generated from the AT-SPI specification.
+ */
+typedef enum {
+    ATSPI_STATE_INVALID,
+    ATSPI_STATE_ACTIVE,
+    ATSPI_STATE_ARMED,
+    ATSPI_STATE_BUSY,
+    ATSPI_STATE_CHECKED,
+    ATSPI_STATE_COLLAPSED,
+    ATSPI_STATE_DEFUNCT,
+    ATSPI_STATE_EDITABLE,
+    ATSPI_STATE_ENABLED,
+    ATSPI_STATE_EXPANDABLE,
+    ATSPI_STATE_EXPANDED,
+    ATSPI_STATE_FOCUSABLE,
+    ATSPI_STATE_FOCUSED,
+    ATSPI_STATE_HAS_TOOLTIP,
+    ATSPI_STATE_HORIZONTAL,
+    ATSPI_STATE_ICONIFIED,
+    ATSPI_STATE_MODAL,
+    ATSPI_STATE_MULTI_LINE,
+    ATSPI_STATE_MULTISELECTABLE,
+    ATSPI_STATE_OPAQUE,
+    ATSPI_STATE_PRESSED,
+    ATSPI_STATE_RESIZABLE,
+    ATSPI_STATE_SELECTABLE,
+    ATSPI_STATE_SELECTED,
+    ATSPI_STATE_SENSITIVE,
+    ATSPI_STATE_SHOWING,
+    ATSPI_STATE_SINGLE_LINE,
+    ATSPI_STATE_STALE,
+    ATSPI_STATE_TRANSIENT,
+    ATSPI_STATE_VERTICAL,
+    ATSPI_STATE_VISIBLE,
+    ATSPI_STATE_MANAGES_DESCENDANTS,
+    ATSPI_STATE_INDETERMINATE,
+    ATSPI_STATE_REQUIRED,
+    ATSPI_STATE_TRUNCATED,
+    ATSPI_STATE_ANIMATED,
+    ATSPI_STATE_INVALID_ENTRY,
+    ATSPI_STATE_SUPPORTS_AUTOCOMPLETION,
+    ATSPI_STATE_SELECTABLE_TEXT,
+    ATSPI_STATE_IS_DEFAULT,
+    ATSPI_STATE_VISITED,
+    ATSPI_STATE_LAST_DEFINED,
+} AtspiStateType;
+
+/**
+ * NUM_ATSPI_STATETYPES:
+ *
+ * 1 higher than the highest valid value of #AtspiStateType.
+ */
+#define NUM_ATSPI_STATETYPES (41+1)
+
+/**
+ *
+ATSPI_KeyEventType:
+ * @ATSPI_KEY_PRESSED: <![CDATA[]]>
+ * @ATSPI_KEY_RELEASED: <![CDATA[]]>
+ *
+ * <![CDATA[     Deprecated, DO NOT USE!    ]]>
+ *
+ * Bitfield/set of flags generated from the AT-SPI specification.
+ */
+typedef enum {
+    ATSPI_KEY_PRESSED,
+    ATSPI_KEY_RELEASED,
+} AtspiKeyEventType;
+
+/**
+ * NUM_ATSPI_KEYEVENTTYPES:
+ *
+ * 1 higher than the highest valid value of #AtspiKeyEventType.
+ */
+#define NUM_ATSPI_KEYEVENTTYPES (1+1)
+
+/**
+ *
+ATSPI_EventType:
+ * @ATSPI_KEY_PRESSED_EVENT: <![CDATA[     < key on a keyboard device was pressed.    ]]>
+ * @ATSPI_KEY_RELEASED_EVENT: <![CDATA[     < key on a keyboard device was released.    ]]>
+ * @ATSPI_BUTTON_PRESSED_EVENT: <![CDATA[     < button on a non-keyboard human interface device        (HID) was pressed    ]]>
+ * @ATSPI_BUTTON_RELEASED_EVENT: <![CDATA[     < button on a non-keyboard human interface device        (HID) was pressed    ]]>
+ *
+ * <![CDATA[     Used to specify the event types of interest to an EventListener, or       to identify the type of an event for which notification has been sent.        @see EventTypeSeq, DeviceEvent::type   ]]>
+ *
+ * Bitfield/set of flags generated from the AT-SPI specification.
+ */
+typedef enum {
+    ATSPI_KEY_PRESSED_EVENT,
+    ATSPI_KEY_RELEASED_EVENT,
+    ATSPI_BUTTON_PRESSED_EVENT,
+    ATSPI_BUTTON_RELEASED_EVENT,
+} AtspiEventType;
+
+/**
+ * NUM_ATSPI_EVENTTYPES:
+ *
+ * 1 higher than the highest valid value of #AtspiEventType.
+ */
+#define NUM_ATSPI_EVENTTYPES (3+1)
+
+/**
+ *
+AtspiKeySynthType:
+ * @ATSPI_KEY_PRESS: <![CDATA[     emulate the pressing of a hardware keyboard key.    ]]>
+ * @ATSPI_KEY_RELEASE: <![CDATA[     emulate the release of a hardware keyboard key.    ]]>
+ * @ATSPI_KEY_PRESSRELEASE: <![CDATA[     a hardware keyboard key is pressed and immediately released.    ]]>
+ * @ATSPI_KEY_SYM: <![CDATA[     a symbolic key event is generated, without specifying a hardware key.        @note if the keysym is not present in the current keyboard map,       the DeviceEventController instance has a limited ability to generate       such keysyms on-the-fly.  Reliability of GenerateKeyboardEvent calls       using out-of-keymap keysyms will vary from system to system, and on the       number of different out-of-keymap being generated in quick succession.       In practice this is rarely significant, since the keysyms of interest to       AT clients and keyboard emulators are usually part of the current keymap, i.e.       present on the system keyboard for the current locale (even if a physical       hardware keyboard is not connected.   ]]>
+ * @ATSPI_KEY_STRING: <![CDATA[     a string is converted to its equivalent keyboard events and emitted.        If the string consists of complex character or composed characters       which are not in the current keymap, string emission is subject to the       out-of-keymap limitations described for KeySynthType::KEY_SYM.       In practice this limitation primarily effects Chinese and Japanese locales.   ]]>
+ *
+ * <![CDATA[     Used when synthesizing keyboard input via DeviceEventController:GenerateKeyboardEvent.   ]]>
+ *
+ * Bitfield/set of flags generated from the AT-SPI specification.
+ */
+typedef enum {
+    ATSPI_KEY_PRESS,
+    ATSPI_KEY_RELEASE,
+    ATSPI_KEY_PRESSRELEASE,
+    ATSPI_KEY_SYM,
+    ATSPI_KEY_STRING,
+} AtspiKeySynthType;
+
+/**
+ * NUM_ATSPI_KEYSYNTHTYPES:
+ *
+ * 1 higher than the highest valid value of #AtspiKeySynthType.
+ */
+#define NUM_ATSPI_KEYSYNTHTYPES (4+1)
+
+/**
+ *
+ATSPI_ModifierType:
+ * @ATSPI_MODIFIER_SHIFT: <![CDATA[     The left or right 'Shift' key    ]]>
+ * @ATSPI_MODIFIER_SHIFTLOCK: <![CDATA[     The ShiftLock or CapsLock key    ]]>
+ * @ATSPI_MODIFIER_CONTROL: <![CDATA[     'Control'/'Ctrl'    ]]>
+ * @ATSPI_MODIFIER_ALT: <![CDATA[     The Alt key (as opposed to AltGr)    ]]>
+ * @ATSPI_MODIFIER_META: <![CDATA[     depending on the platform this may map to 'Window', 'Function', 'Meta',       'Menu', or 'NumLock'.         Such 'Meta keys' will map to one of META, META2, META3.       On X Windows platforms these META values map to        the modifier masks Mod1Mask, Mod2Mask, Mod3Mask, e.g. an event having       ModifierType::MODIFIER_META2 means that the 'Mod2Mask' bit is       set in the corresponding XEvent.   ]]>
+ * @ATSPI_MODIFIER_META2: <![CDATA[]]>
+ * @ATSPI_MODIFIER_META3: <![CDATA[]]>
+ * @ATSPI_MODIFIER_NUMLOCK: <![CDATA[     A symbolic meta key name that is mapped by AT-SPI to the        appropriate META value, for the convenience of the client.   ]]>
+ *
+ * Bitfield/set of flags generated from the AT-SPI specification.
+ */
+typedef enum {
+    ATSPI_MODIFIER_SHIFT,
+    ATSPI_MODIFIER_SHIFTLOCK,
+    ATSPI_MODIFIER_CONTROL,
+    ATSPI_MODIFIER_ALT,
+    ATSPI_MODIFIER_META,
+    ATSPI_MODIFIER_META2,
+    ATSPI_MODIFIER_META3,
+    ATSPI_MODIFIER_NUMLOCK,
+} AtspimodifierType;
+
+/**
+ * NUM_ATSPI_MODIFIERTYPES:
+ *
+ * 1 higher than the highest valid value of #AtspiModifierType.
+ */
+#define NUM_ATSPI_MODIFIERTYPES (7+1)
+
+/**
+ *
+ATSPI_RelationType:
+ * @ATSPI_RELATION_NULL: <![CDATA[     Not a meaningful relationship; clients should not normally encounter this RelationType value.    ]]>
+ * @ATSPI_RELATION_LABEL_FOR: <![CDATA[     Object is a label for one or more other objects.    ]]>
+ * @ATSPI_RELATION_LABELLED_BY: <![CDATA[     Object is labelled by one or more other objects.    ]]>
+ * @ATSPI_RELATION_CONTROLLER_FOR: <![CDATA[     Object is an interactive object which modifies the state, onscreen location, or other attributes       of one or more target objects.    ]]>
+ * @ATSPI_RELATION_CONTROLLED_BY: <![CDATA[     Object state, position, etc. is modified/controlled by user interaction with one or        more other objects.   For instance a viewport or scroll pane may be CONTROLLED_BY scrollbars.    ]]>
+ * @ATSPI_RELATION_MEMBER_OF: <![CDATA[     Object has a grouping relationship (e.g. 'same group as') to one or more other objects.     ]]>
+ * @ATSPI_RELATION_TOOLTIP_FOR: <![CDATA[     Object is a tooltip associated with another object.    ]]>
+ * @ATSPI_RELATION_NODE_CHILD_OF: <![CDATA[     Object is a child of the target.   ]]>
+ * @ATSPI_RELATION_NODE_PARENT_OF: <![CDATA[     Object is a parent of the target.   ]]>
+ * @ATSPI_RELATION_EXTENDED: <![CDATA[     Used to indicate that a relationship exists, but its type is not specified in the enumeration       and must be obtained via a call to getRelationTypeName.     ]]>
+ * @ATSPI_RELATION_FLOWS_TO: <![CDATA[     Object renders content which flows logically to another object.         For instance, text in a paragraph may flow to another object which is not the        'next sibling' in the accessibility hierarchy.    ]]>
+ * @ATSPI_RELATION_FLOWS_FROM: <![CDATA[     Reciprocal of RELATION_FLOWS_TO.    ]]>
+ * @ATSPI_RELATION_SUBWINDOW_OF: <![CDATA[     Object is visually and semantically considered a subwindow of another object, even though       it is not the object's child.  Useful when dealing with embedded applications and other cases       where the widget hierarchy does not map cleanly to the onscreen presentation.     ]]>
+ * @ATSPI_RELATION_EMBEDS: <![CDATA[     Similar to SUBWINDOW_OF, but specifically used for cross-process embedding.     ]]>
+ * @ATSPI_RELATION_EMBEDDED_BY: <![CDATA[     Reciprocal of RELATION_EMBEDS; Used to denote content rendered by embedded renderers that       live in a separate process space from the embedding context.     ]]>
+ * @ATSPI_RELATION_POPUP_FOR: <![CDATA[     Denotes that the object is a transient window or frame associated with another onscreen object.       Similar to TOOLTIP_FOR, but more general.  Useful for windows which are technically        toplevels but which, for one or more reasons, do not explicitly cause their associated       window to lose 'window focus'. Creation of a ROLE_WINDOW object with the POPUP_FOR relation       usually requires some presentation action on the part of assistive technology clients, even though       the previous toplevel ROLE_FRAME object may still be the active window.     ]]>
+ * @ATSPI_RELATION_PARENT_WINDOW_OF: <![CDATA[     This is the reciprocal relation to RELATION_POPUP_FOR.    ]]>
+ * @ATSPI_RELATION_DESCRIPTION_FOR: <![CDATA[     Indicates that an object provides descriptive information        about another object; more verbose than RELATION_LABEL_FOR.    ]]>
+ * @ATSPI_RELATION_DESCRIBED_BY: <![CDATA[     Indicates that another object provides descriptive information        about this object; more verbose than RELATION_LABELLED_BY.    ]]>
+ * @ATSPI_RELATION_LAST_DEFINED: <![CDATA[     Do not use as a parameter value, used to determine the size of the enumeration.    ]]>
+ *
+ * <![CDATA[     RelationType specifies a relationship between objects (possibly one-to-many or many-to-one)       outside of the normal parent/child hierarchical relationship.  It allows better semantic       identification of how objects are associated with one another.       For instance the RELATION_LABELLED_BY relationship may be used to identify labelling information       that should accompany the accessibleName property when presenting an object's content or identity       to the end user.  Similarly, RELATION_CONTROLLER_FOR can be used to further specify the context       in which a valuator is useful, and/or the other UI components which are directly effected by       user interactions with the valuator. Common examples include association of scrollbars with       the viewport or panel which they control.   ]]>
+ *
+ * Bitfield/set of flags generated from the AT-SPI specification.
+ */
+typedef enum {
+    ATSPI_RELATION_NULL,
+    ATSPI_RELATION_LABEL_FOR,
+    ATSPI_RELATION_LABELLED_BY,
+    ATSPI_RELATION_CONTROLLER_FOR,
+    ATSPI_RELATION_CONTROLLED_BY,
+    ATSPI_RELATION_MEMBER_OF,
+    ATSPI_RELATION_TOOLTIP_FOR,
+    ATSPI_RELATION_NODE_CHILD_OF,
+    ATSPI_RELATION_NODE_PARENT_OF,
+    ATSPI_RELATION_EXTENDED,
+    ATSPI_RELATION_FLOWS_TO,
+    ATSPI_RELATION_FLOWS_FROM,
+    ATSPI_RELATION_SUBWINDOW_OF,
+    ATSPI_RELATION_EMBEDS,
+    ATSPI_RELATION_EMBEDDED_BY,
+    ATSPI_RELATION_POPUP_FOR,
+    ATSPI_RELATION_PARENT_WINDOW_OF,
+    ATSPI_RELATION_DESCRIPTION_FOR,
+    ATSPI_RELATION_DESCRIBED_BY,
+    ATSPI_RELATION_LAST_DEFINED,
+} AtspiRelationType;
+
+/**
+ * NUM_ATSPI_RELATIONTYPES:
+ *
+ * 1 higher than the highest valid value of #AtspiRelationType.
+ */
+#define NUM_ATSPI_RELATIONTYPES (19+1)
+
+/**
+ *
+ATSPI_Role:
+ * @ATSPI_ROLE_INVALID: <![CDATA[     A Role indicating an error condition, such as uninitialized Role data.    ]]>
+ * @ATSPI_ROLE_ACCELERATOR_LABEL: <![CDATA[     Object is a label indicating the keyboard accelerators for the parent     ]]>
+ * @ATSPI_ROLE_ALERT: <![CDATA[     Object is used to alert the user about something    ]]>
+ * @ATSPI_ROLE_ANIMATION: <![CDATA[     Object contains a dynamic or moving image of some kind    ]]>
+ * @ATSPI_ROLE_ARROW: <![CDATA[     Object is a 2d directional indicator    ]]>
+ * @ATSPI_ROLE_CALENDAR: <![CDATA[     Object contains one or more dates, usually arranged into a 2d list    ]]>
+ * @ATSPI_ROLE_CANVAS: <![CDATA[     Object that can be drawn into and is used to trap events    ]]>
+ * @ATSPI_ROLE_CHECK_BOX: <![CDATA[     A choice that can be checked or unchecked and provides a separate       indicator for the current state.   ]]>
+ * @ATSPI_ROLE_CHECK_MENU_ITEM: <![CDATA[     A menu item that behaves like a check box (see ROLE_CHECK_BOX)    ]]>
+ * @ATSPI_ROLE_COLOR_CHOOSER: <![CDATA[     A specialized dialog that lets the user choose a color.    ]]>
+ * @ATSPI_ROLE_COLUMN_HEADER: <![CDATA[     The header for a column of data    ]]>
+ * @ATSPI_ROLE_COMBO_BOX: <![CDATA[     A list of choices the user can select from    ]]>
+ * @ATSPI_ROLE_DATE_EDITOR: <![CDATA[     An object which allows entry of a date    ]]>
+ * @ATSPI_ROLE_DESKTOP_ICON: <![CDATA[     An inconifed internal frame within a DESKTOP_PANE    ]]>
+ * @ATSPI_ROLE_DESKTOP_FRAME: <![CDATA[     A pane that supports internal frames and iconified versions of those       internal frames.   ]]>
+ * @ATSPI_ROLE_DIAL: <![CDATA[     An object that allows a value to be changed via rotating a visual element,       or which displays a value via such a rotating element.    ]]>
+ * @ATSPI_ROLE_DIALOG: <![CDATA[     A top level window with title bar and a border    ]]>
+ * @ATSPI_ROLE_DIRECTORY_PANE: <![CDATA[     A pane that allows the user to navigate through and select the contents       of a directory   ]]>
+ * @ATSPI_ROLE_DRAWING_AREA: <![CDATA[     A specialized dialog that displays the files in the directory and lets       the user select a file, browse a different directory, or specify a       filename.   ]]>
+ * @ATSPI_ROLE_FILE_CHOOSER: <![CDATA[     An object used for drawing custom user interface elements.   ]]>
+ * @ATSPI_ROLE_FILLER: <![CDATA[     A object that fills up space in a user interface   ]]>
+ * @ATSPI_ROLE_FOCUS_TRAVERSABLE: <![CDATA[     Don't use, reserved for future use.    ]]>
+ * @ATSPI_ROLE_FONT_CHOOSER: <![CDATA[     Allows selection of a display font    ]]>
+ * @ATSPI_ROLE_FRAME: <![CDATA[     A top level window with a title bar, border, menubar, etc.    ]]>
+ * @ATSPI_ROLE_GLASS_PANE: <![CDATA[     A pane that is guaranteed to be painted on top of all panes beneath it    ]]>
+ * @ATSPI_ROLE_HTML_CONTAINER: <![CDATA[     A document container for HTML, whose children       represent the document content.   ]]>
+ * @ATSPI_ROLE_ICON: <![CDATA[     A small fixed size picture, typically used to decorate components    ]]>
+ * @ATSPI_ROLE_IMAGE: <![CDATA[     An image, typically static.    ]]>
+ * @ATSPI_ROLE_INTERNAL_FRAME: <![CDATA[     A frame-like object that is clipped by a desktop pane.    ]]>
+ * @ATSPI_ROLE_LABEL: <![CDATA[     An object used to present an icon or short string in an interface    ]]>
+ * @ATSPI_ROLE_LAYERED_PANE: <![CDATA[     A specialized pane that allows its children to be drawn in layers,       providing a form of stacking order.   ]]>
+ * @ATSPI_ROLE_LIST: <![CDATA[     An object that presents a list of objects to the user and allows the       user to select one or more of them.   ]]>
+ * @ATSPI_ROLE_LIST_ITEM: <![CDATA[     An object that represents an element of a list.    ]]>
+ * @ATSPI_ROLE_MENU: <![CDATA[     An object usually found inside a menu bar that contains a list of       actions the user can choose from.   ]]>
+ * @ATSPI_ROLE_MENU_BAR: <![CDATA[     An object usually drawn at the top of the primary dialog box of an       application that contains a list of menus the user can choose from.   ]]>
+ * @ATSPI_ROLE_MENU_ITEM: <![CDATA[     An object usually contained in a menu that presents an action the       user can choose.   ]]>
+ * @ATSPI_ROLE_OPTION_PANE: <![CDATA[     A specialized pane whose primary use is inside a DIALOG    ]]>
+ * @ATSPI_ROLE_PAGE_TAB: <![CDATA[     An object that is a child of a page tab list    ]]>
+ * @ATSPI_ROLE_PAGE_TAB_LIST: <![CDATA[     An object that presents a series of panels (or page tabs), one at a time,       through some mechanism provided by the object.   ]]>
+ * @ATSPI_ROLE_PANEL: <![CDATA[     A generic container that is often used to group objects.    ]]>
+ * @ATSPI_ROLE_PASSWORD_TEXT: <![CDATA[     A text object uses for passwords, or other places where the text       content is not shown visibly to the user.   ]]>
+ * @ATSPI_ROLE_POPUP_MENU: <![CDATA[     A temporary window that is usually used to offer the user a list of       choices, and then hides when the user selects one of those choices.   ]]>
+ * @ATSPI_ROLE_PROGRESS_BAR: <![CDATA[     An object used to indicate how much of a task has been completed.    ]]>
+ * @ATSPI_ROLE_PUSH_BUTTON: <![CDATA[     An object the user can manipulate to tell the application to do       something.   ]]>
+ * @ATSPI_ROLE_RADIO_BUTTON: <![CDATA[     A specialized check box that will cause other radio buttons in the       same group to become uncghecked when this one is checked.   ]]>
+ * @ATSPI_ROLE_RADIO_MENU_ITEM: <![CDATA[     Object is both a menu item and a "radio button" (see ROLE_RADIO_BUTTON)    ]]>
+ * @ATSPI_ROLE_ROOT_PANE: <![CDATA[     A specialized pane that has a glass pane and a layered pane as its       children.   ]]>
+ * @ATSPI_ROLE_ROW_HEADER: <![CDATA[     The header for a row of data    ]]>
+ * @ATSPI_ROLE_SCROLL_BAR: <![CDATA[     An object usually used to allow a user to incrementally view a large       amount of data by moving the bounds of a viewport along a one-dimensional axis.   ]]>
+ * @ATSPI_ROLE_SCROLL_PANE: <![CDATA[     An object that allows a user to incrementally view a large amount       of information.  ROLE_SCROLL_PANE objects are usually accompanied by       ROLE_SCROLL_BAR controllers, on which the RELATION_CONTROLLER_FOR and       RELATION_CONTROLLED_BY reciprocal relations are set; \see        Accessibility::RelationSet.   ]]>
+ * @ATSPI_ROLE_SEPARATOR: <![CDATA[     An object usually contained in a menu to provide a visible and       logical separation of the contents in a menu.   ]]>
+ * @ATSPI_ROLE_SLIDER: <![CDATA[     An object that allows the user to select from a bounded range    ]]>
+ * @ATSPI_ROLE_SPIN_BUTTON: <![CDATA[     An object which allows one of a set of choices to be selected,        and which displays the current choice.  Unlike ROLE_SCROLL_BAR,       ROLE_SLIDER objects need not control 'viewport'-like objects.   ]]>
+ * @ATSPI_ROLE_SPLIT_PANE: <![CDATA[     A specialized panel that presents two other panels at the same time.    ]]>
+ * @ATSPI_ROLE_STATUS_BAR: <![CDATA[     Object displays non-quantitative status information (c.f. ROLE_PROGRESS_BAR)    ]]>
+ * @ATSPI_ROLE_TABLE: <![CDATA[     An object used to repesent information in terms of rows and columns.    ]]>
+ * @ATSPI_ROLE_TABLE_CELL: <![CDATA[     A 'cell' or discrete child within a Table. \note Table cells need not have ROLE_TABLE_CELL,        other RoleType values are valid as well.     ]]>
+ * @ATSPI_ROLE_TABLE_COLUMN_HEADER: <![CDATA[     An object which labels a particular column in a Table.    ]]>
+ * @ATSPI_ROLE_TABLE_ROW_HEADER: <![CDATA[     An object which labels a particular row in a Table. Table rows and columns may also be        labelled via the RELATION_LABEL_FOR/RELATION_LABELLED_BY relationships;        see Accessibility.RelationSet.    ]]>
+ * @ATSPI_ROLE_TEAROFF_MENU_ITEM: <![CDATA[     Object allows menu to be removed from menubar and shown in its own window.    ]]>
+ * @ATSPI_ROLE_TERMINAL: <![CDATA[     An object that emulates a terminal    ]]>
+ * @ATSPI_ROLE_TEXT: <![CDATA[     An object that presents text to the user, of nonspecific type.    ]]>
+ * @ATSPI_ROLE_TOGGLE_BUTTON: <![CDATA[     A specialized push button that can be checked or unchecked, but does       not procide a separate indicator for the current state.   ]]>
+ * @ATSPI_ROLE_TOOL_BAR: <![CDATA[     A bar or palette usually composed of push buttons or toggle buttons   ]]>
+ * @ATSPI_ROLE_TOOL_TIP: <![CDATA[     An object that provides information about another object   ]]>
+ * @ATSPI_ROLE_TREE: <![CDATA[     An object used to repsent hierarchical information to the user.    ]]>
+ * @ATSPI_ROLE_TREE_TABLE: <![CDATA[     An object that presents both tabular and hierarchical info to the user    ]]>
+ * @ATSPI_ROLE_UNKNOWN: <![CDATA[     The object contains some Accessible information, but its role is       not known.     ]]>
+ * @ATSPI_ROLE_VIEWPORT: <![CDATA[     An object usually used in a scroll pane, or to otherwise clip a larger object or        content renderer to a specific onscreen viewport.    ]]>
+ * @ATSPI_ROLE_WINDOW: <![CDATA[     A &#168;top level window&#168; with no title or border.    ]]>
+ * @ATSPI_ROLE_EXTENDED: <![CDATA[     means that the role for this item is known, but not included in the        core enumeration    ]]>
+ * @ATSPI_ROLE_HEADER: <![CDATA[     An object that serves as a document header.    ]]>
+ * @ATSPI_ROLE_FOOTER: <![CDATA[     An object that serves as a document footer.    ]]>
+ * @ATSPI_ROLE_PARAGRAPH: <![CDATA[     An object which is contains a single paragraph of text content. See also ROLE_TEXT.    ]]>
+ * @ATSPI_ROLE_RULER: <![CDATA[     An object which describes margins and tab stops, etc.        for text objects which it controls        (should have CONTROLLER_FOR relation to such).    ]]>
+ * @ATSPI_ROLE_APPLICATION: <![CDATA[     An object corresponding to the toplevel accessible of an        application, which may contain ROLE_FRAME objects or other       accessible objects.  Children of AccessibleDesktop objects        are generally ROLE_APPLICATION objects.   ]]>
+ * @ATSPI_ROLE_AUTOCOMPLETE: <![CDATA[     The object is a dialog or list containing items for insertion        into an entry widget, for instance a list of words for completion        of a text entry.   ]]>
+ * @ATSPI_ROLE_EDITBAR: <![CDATA[     The object is an editable text object in a toolbar.   ]]>
+ * @ATSPI_ROLE_EMBEDDED: <![CDATA[     The object is an embedded component container.  This role is a        "grouping" hint that the contained objects share a context which is        different from the container in which this accessible is embedded.       In particular, it is used for some kinds of document embedding, and       for embedding of out-of-process component, "panel applets", etc.   ]]>
+ * @ATSPI_ROLE_ENTRY: <![CDATA[     The object is a component whose textual content may be entered or modified by the user, 	    provided STATE_EDITABLE is present.       A readonly ROLE_ENTRY object (i.e. where STATE_EDITABLE is not present) implies a       read-only 'text field' in a form, as opposed to a title, label, or caption.     ]]>
+ * @ATSPI_ROLE_CHART: <![CDATA[     The object is a graphical depiction of quantitative data.  It may contain multiple       subelements whose attributes and/or description may be queried to obtain both the       quantitative data and information about how the data is being presented.       The LABELLED_BY relation is particularly important in interpreting objects of this type,       as is the accessible-description property.         See ROLE_CAPTION     ]]>
+ * @ATSPI_ROLE_CAPTION: <![CDATA[     The object contains descriptive information, usually textual, about another user interface       element such as a table, chart, or image.     ]]>
+ * @ATSPI_ROLE_DOCUMENT_FRAME: <![CDATA[     The object is a visual frame or container which contains a view of document content.         Document frames may occur within another Document instance, in which case the second        document may be said to be embedded in the containing instance.  HTML frames are       often ROLE_DOCUMENT_FRAME.  Either this object, or a singleton descendant, should implement       the Document interface.     ]]>
+ * @ATSPI_ROLE_HEADING: <![CDATA[     The object serves as a heading for content which follows it in a document.       The 'heading level' of the heading, if availabe,  may be obtained by       querying the object's attributes.      ]]>
+ * @ATSPI_ROLE_PAGE: <![CDATA[     The object is a containing instance which encapsulates a page of        information.  ROLE_PAGE is used in documents and content which support       a paginated navigation model.     ]]>
+ * @ATSPI_ROLE_SECTION: <![CDATA[     The object is a containing instance of document content which constitutes       a particular 'logical' section of the document.  The type of content within       a section, and the nature of the section division itself, may be obtained       by querying the object's attributes.  Sections may be nested.     ]]>
+ * @ATSPI_ROLE_REDUNDANT_OBJECT: <![CDATA[     The object is redundant with another object in the hierarchy,        and is exposed for purely technical reasons.  Objects of this role        should be ignored by clients, if they are encountered at all.      ]]>
+ * @ATSPI_ROLE_FORM: <![CDATA[     The object is a containing instance of document content which       has within it components with which the user can interact in order to       input information; i.e. the object is a container for pushbuttons,       comboboxes, text input fields, and other 'GUI' components.       ROLE_FORM should not, in general, be used for toplevel GUI containers       or dialogs, but should be reserved for 'GUI' containers which occur within       document content, for instance within Web documents, presentations, or        text documents.  Unlike other GUI containers and dialogs which occur inside       application instances, ROLE_FORM containers' components are associated with       the current document, rather than the current foreground application or       viewer instance.     ]]>
+ * @ATSPI_ROLE_LINK: <![CDATA[     The object is a hypertext anchor, i.e. a "link" in a       hypertext document.  Such objects are distinct from 'inline'       content which may also use the Hypertext/Hyperlink interfaces       to indicate the range/location within a text object where       an inline or embedded object lies.     ]]>
+ * @ATSPI_ROLE_INPUT_METHOD_WINDOW: <![CDATA[     The object is a window or similar viewport which is used       to allow composition or input of a 'complex character',       in other words it is an "input method window."     ]]>
+ * @ATSPI_ROLE_LAST_DEFINED: <![CDATA[     Not a valid role, used for finding end of enumeration.    ]]>
+ *
+ * Bitfield/set of flags generated from the AT-SPI specification.
+ */
+typedef enum {
+    ATSPI_ROLE_INVALID,
+    ATSPI_ROLE_ACCELERATOR_LABEL,
+    ATSPI_ROLE_ALERT,
+    ATSPI_ROLE_ANIMATION,
+    ATSPI_ROLE_ARROW,
+    ATSPI_ROLE_CALENDAR,
+    ATSPI_ROLE_CANVAS,
+    ATSPI_ROLE_CHECK_BOX,
+    ATSPI_ROLE_CHECK_MENU_ITEM,
+    ATSPI_ROLE_COLOR_CHOOSER,
+    ATSPI_ROLE_COLUMN_HEADER,
+    ATSPI_ROLE_COMBO_BOX,
+    ATSPI_ROLE_DATE_EDITOR,
+    ATSPI_ROLE_DESKTOP_ICON,
+    ATSPI_ROLE_DESKTOP_FRAME,
+    ATSPI_ROLE_DIAL,
+    ATSPI_ROLE_DIALOG,
+    ATSPI_ROLE_DIRECTORY_PANE,
+    ATSPI_ROLE_DRAWING_AREA,
+    ATSPI_ROLE_FILE_CHOOSER,
+    ATSPI_ROLE_FILLER,
+    ATSPI_ROLE_FOCUS_TRAVERSABLE,
+    ATSPI_ROLE_FONT_CHOOSER,
+    ATSPI_ROLE_FRAME,
+    ATSPI_ROLE_GLASS_PANE,
+    ATSPI_ROLE_HTML_CONTAINER,
+    ATSPI_ROLE_ICON,
+    ATSPI_ROLE_IMAGE,
+    ATSPI_ROLE_INTERNAL_FRAME,
+    ATSPI_ROLE_LABEL,
+    ATSPI_ROLE_LAYERED_PANE,
+    ATSPI_ROLE_LIST,
+    ATSPI_ROLE_LIST_ITEM,
+    ATSPI_ROLE_MENU,
+    ATSPI_ROLE_MENU_BAR,
+    ATSPI_ROLE_MENU_ITEM,
+    ATSPI_ROLE_OPTION_PANE,
+    ATSPI_ROLE_PAGE_TAB,
+    ATSPI_ROLE_PAGE_TAB_LIST,
+    ATSPI_ROLE_PANEL,
+    ATSPI_ROLE_PASSWORD_TEXT,
+    ATSPI_ROLE_POPUP_MENU,
+    ATSPI_ROLE_PROGRESS_BAR,
+    ATSPI_ROLE_PUSH_BUTTON,
+    ATSPI_ROLE_RADIO_BUTTON,
+    ATSPI_ROLE_RADIO_MENU_ITEM,
+    ATSPI_ROLE_ROOT_PANE,
+    ATSPI_ROLE_ROW_HEADER,
+    ATSPI_ROLE_SCROLL_BAR,
+    ATSPI_ROLE_SCROLL_PANE,
+    ATSPI_ROLE_SEPARATOR,
+    ATSPI_ROLE_SLIDER,
+    ATSPI_ROLE_SPIN_BUTTON,
+    ATSPI_ROLE_SPLIT_PANE,
+    ATSPI_ROLE_STATUS_BAR,
+    ATSPI_ROLE_TABLE,
+    ATSPI_ROLE_TABLE_CELL,
+    ATSPI_ROLE_TABLE_COLUMN_HEADER,
+    ATSPI_ROLE_TABLE_ROW_HEADER,
+    ATSPI_ROLE_TEAROFF_MENU_ITEM,
+    ATSPI_ROLE_TERMINAL,
+    ATSPI_ROLE_TEXT,
+    ATSPI_ROLE_TOGGLE_BUTTON,
+    ATSPI_ROLE_TOOL_BAR,
+    ATSPI_ROLE_TOOL_TIP,
+    ATSPI_ROLE_TREE,
+    ATSPI_ROLE_TREE_TABLE,
+    ATSPI_ROLE_UNKNOWN,
+    ATSPI_ROLE_VIEWPORT,
+    ATSPI_ROLE_WINDOW,
+    ATSPI_ROLE_EXTENDED,
+    ATSPI_ROLE_HEADER,
+    ATSPI_ROLE_FOOTER,
+    ATSPI_ROLE_PARAGRAPH,
+    ATSPI_ROLE_RULER,
+    ATSPI_ROLE_APPLICATION,
+    ATSPI_ROLE_AUTOCOMPLETE,
+    ATSPI_ROLE_EDITBAR,
+    ATSPI_ROLE_EMBEDDED,
+    ATSPI_ROLE_ENTRY,
+    ATSPI_ROLE_CHART,
+    ATSPI_ROLE_CAPTION,
+    ATSPI_ROLE_DOCUMENT_FRAME,
+    ATSPI_ROLE_HEADING,
+    ATSPI_ROLE_PAGE,
+    ATSPI_ROLE_SECTION,
+    ATSPI_ROLE_REDUNDANT_OBJECT,
+    ATSPI_ROLE_FORM,
+    ATSPI_ROLE_LINK,
+    ATSPI_ROLE_INPUT_METHOD_WINDOW,
+    ATSPI_ROLE_LAST_DEFINED,
+} AtspiRole;
+
+/**
+ * NUM_ATSPI_ROLES:
+ *
+ * 1 higher than the highest valid value of #AtspiRole.
+ */
+#define NUM_ATSPI_ROLES (90+1)
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif	/* _ATSPI_CONSTANTS_H_ */
diff --git a/atspi/atspi-event-types.h b/atspi/atspi-event-types.h
new file mode 100644
index 0000000..154ba1b
--- /dev/null
+++ b/atspi/atspi-event-types.h
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ *
+ * 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 _ATSPI_EVENT_TYPES_H_
+#define _ATSPI_EVENT_TYPES_H_
+
+#include <glib.h>
+
+#include "atspi-accessible.h"
+
+typedef guint AtspiControllerEventMask;
+
+typedef guint AtspiKeyMaskType;
+
+typedef guint AtspiKeyEventMask;
+typedef guint AtspiDeviceEventMask;
+
+// TODO: auto-generate the below structs
+typedef struct _AtspiDeviceEvent AtspiDeviceEvent;
+struct _AtspiDeviceEvent
+{
+  AtspiEventType type;
+  guint id;
+  gushort hw_code;
+  gushort modifiers;
+  guint timestamp;
+  gchar * event_string;
+  gboolean is_text;
+};
+
+typedef struct _AtspiEventListenerMode AtspiEventListenerMode;
+struct _AtspiEventListenerMode
+{
+  gboolean synchronous;
+  gboolean preemptive;
+  gboolean global;
+};
+
+typedef struct _AtspiKeyDefinition AtspiKeyDefinition;
+struct _AtspiKeyDefinition
+{
+  gint keycode;
+  gint keysym;
+  gchar *keystring;
+  gint unused;
+};
+
+typedef struct _AtspiEvent AtspiEvent;
+struct _AtspiEvent
+{
+  const gchar  *type;
+  AtspiAccessible  *source;
+  gint         detail1;
+  gint         detail2;
+  GVariant *any;
+};
+
+typedef void AtspiKeystrokeListener;
+
+/**
+ * AtspiKeySet:
+ * @keysyms:
+ * @keycodes:
+ * @len:
+ *
+ * Structure containing identifying information about a set of keycode or
+ *        keysyms.
+ **/
+typedef struct _AtspiKeySet
+{
+  guint *keysyms;
+  gushort *keycodes;
+  gchar          **keystrings;
+  gshort           len;
+} AtspiKeySet;
+
+/**
+ *AtspiKeyListenerSyncType:
+ * SPI_KEYLISTENER_NOSYNC: Events may be delivered asynchronously, 
+ * which means in some cases they may already have been delivered to the 
+ * application before the AT client receives the notification.  
+ * SPI_KEYLISTENER_SYNCHRONOUS: Events are delivered synchronously, before the 
+ * currently focussed application sees them.  
+ * ATSPI_KEYLISTENER_CANCONSUME: Events may be consumed by the AT client.  Presumes and
+ * requires #ATSPI_KEYLISTENER_SYNCHRONOUS, incompatible with #ATSPI_KEYLISTENER_NOSYNC.
+ * SPI_KEYLISTENER_ALL_WINDOWS: Events are received not from the application toolkit layer, but
+ * from the device driver or windowing system subsystem; such notifications are 'global' in the 
+ * sense that they are not broken or defeated by applications that participate poorly
+ * in the accessibility APIs, or not at all; however because of the intrusive nature of
+ * such snooping, it can have side-effects on certain older platforms.  If unconditional
+ * event notifications, even when inaccessible or "broken" applications have focus, are not
+ * required, it may be best to avoid this enum value/flag.
+ *
+ *Specified the tyupe of a key listener event.
+ * Certain of the values above can and should be bitwise-'OR'ed
+ * together, observing the compatibility limitations specified in the description of
+ * each value.  For instance, #ATSPI_KEYLISTENER_ALL_WINDOWS | #ATSPI_KEYLISTENER_CANCONSUME is
+ * a commonly used combination which gives the AT complete control over the delivery of matching
+ * events.  However, such filters should be used sparingly as they may have a negative impact on 
+ * system performance.
+ **/
+typedef enum {
+  ATSPI_KEYLISTENER_NOSYNC = 0,
+  ATSPI_KEYLISTENER_SYNCHRONOUS = 1,
+  ATSPI_KEYLISTENER_CANCONSUME = 2,
+  ATSPI_KEYLISTENER_ALL_WINDOWS = 4
+} AtspiKeyListenerSyncType;
+#endif /* _ATSPI_EVENT_TYPES_H_ */
diff --git a/atspi/atspi-listener-private.h b/atspi/atspi-listener-private.h
new file mode 100644
index 0000000..7907863
--- /dev/null
+++ b/atspi/atspi-listener-private.h
@@ -0,0 +1,37 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ *           2002 Sun Microsystems Inc.
+ *           
+ *
+ * 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 _ATSPI_LISTENER_PRIVATE_H_
+#define _ATSPI_LISTENER_PRIVATE_H_
+
+#include "dbus/dbus.h"
+#include "glib.h"
+#include "atspi-listener.h"
+
+DBusHandlerResult
+atspi_dbus_handle_deviceEvent (DBusConnection *bus, DBusMessage *message, void *data);
+
+gchar *
+_atspi_device_listener_get_path (AtspiDeviceListener *listener);
+#endif	/* _ATSPI_LISTENER_PRIVATE_H_ */
diff --git a/atspi/atspi-listener.c b/atspi/atspi-listener.c
new file mode 100644
index 0000000..15492e7
--- /dev/null
+++ b/atspi/atspi-listener.c
@@ -0,0 +1,383 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian Inc.
+ * Copyright 2002 Sun Microsystems, Inc.
+ *
+ * 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 "atspi-private.h"
+
+typedef struct
+{
+  union
+    {
+      AtspiEventListenerCB     event;
+      AtspiDeviceListenerCB    device_event;
+      gpointer                      method;
+    } cb;
+  gpointer user_data;
+} EventHandler;
+
+GObjectClass *event_parent_class;
+GObjectClass *device_parent_class;
+
+static guint32 _e_id = 0;
+
+/*
+ * Misc. helpers.
+ */
+
+static EventHandler *
+atspi_event_handler_new (gpointer method, gpointer user_data)
+{
+  EventHandler *eh = g_new0 (EventHandler, 1);
+
+  eh->cb.method = method;
+  eh->user_data = user_data;
+
+  return eh;
+}
+
+static GList *
+event_list_remove_by_cb (GList *list, gpointer callback)
+{
+  GList *l, *next;
+	
+  for (l = list; l; l = next)
+    {
+      EventHandler *eh = l->data;
+      next = l->next;
+
+      if (eh->cb.method == callback)
+      {
+        list = g_list_delete_link (list, l);
+	g_free (eh);
+      }
+    }
+
+  return list;
+}
+
+/*
+ * Standard event dispatcher
+ */
+
+G_DEFINE_TYPE (AtspiEventListener, atspi_event_listener,
+			  G_TYPE_OBJECT)
+
+static void
+atspi_event_dispatch (AtspiEventListener    *listener,
+	    const AtspiEvent *event)
+{
+  GList *l;
+  
+  /* FIXME: re-entrancy hazard on this list */
+  for (l = listener->callbacks; l; l = l->next)
+    {
+      EventHandler *eh = l->data;
+      /* cast hides our private stuff from client handlers */
+      eh->cb.event (event, eh->user_data);
+    }
+}
+
+static guint listener_id = 0;
+static GList *device_listeners = NULL;
+
+static gboolean
+id_is_free (guint id)
+{
+  GList *l;
+
+  for (l = device_listeners; l; l = g_list_next (l))
+  {
+    AtspiDeviceListener *listener = l->data;
+    if (listener->id == id) return FALSE;
+  }
+  return TRUE;
+}
+
+static void
+remove_listener (GObject *obj, gpointer data)
+{
+  device_listeners = g_list_remove (device_listeners, obj);
+}
+
+static void
+atspi_event_listener_init (AtspiEventListener *listener)
+{
+}
+
+static void
+atspi_event_listener_finalize (GObject *object)
+{
+  AtspiEventListener *listener = (AtspiEventListener *) object;
+  GList *l;
+  
+  for (l = listener->callbacks; l; l = l->next)
+    {
+      g_free (l->data);
+    }
+  
+  g_list_free (listener->callbacks);
+
+  event_parent_class->finalize (object);
+}
+
+static void
+atspi_event_listener_class_init (AtspiEventListenerClass *klass)
+{
+  GObjectClass *object_class = (GObjectClass *) klass;
+
+  event_parent_class = g_type_class_peek_parent (klass);
+  object_class->finalize = atspi_event_listener_finalize;
+
+  klass->event = atspi_event_dispatch;
+}
+
+AtspiEventListener *
+atspi_event_listener_new (void)
+{
+  AtspiEventListener *listener;
+
+  listener = g_object_new (atspi_event_listener_get_type (), NULL);
+
+  return listener;
+}
+
+void
+atspi_event_listener_add_cb (AtspiEventListener  *listener,
+			    AtspiEventListenerCB callback,
+			    void                     *user_data)
+{
+  g_return_if_fail (ATSPI_IS_EVENT_LISTENER (listener));
+
+  listener->callbacks = g_list_prepend (listener->callbacks,
+					atspi_event_handler_new ((void *) callback, user_data));
+}
+
+void
+atspi_event_listener_remove_cb (AtspiEventListener  *listener,
+			       AtspiEventListenerCB callback)
+{
+  g_return_if_fail (ATSPI_IS_EVENT_LISTENER (listener));
+
+  listener->callbacks = event_list_remove_by_cb (listener->callbacks, (void *) callback);
+}
+
+/* 
+ * Device event handler
+ */
+static gboolean
+atspi_device_event_dispatch (AtspiDeviceListener               *listener,
+		   const AtspiDeviceEvent *event)
+{
+  GList *l;
+  AtspiDeviceEvent anevent;
+  gboolean handled = FALSE;
+
+  /* FIXME: re-enterancy hazard on this list */
+  for (l = listener->callbacks; l; l = l->next)
+    {
+      EventHandler *eh = l->data;
+
+      if ((handled = eh->cb.device_event (&anevent, eh->user_data)))
+        {
+	  break;
+	}
+    }
+
+  return handled;
+}
+
+static void
+atspi_device_listener_init (AtspiDeviceListener *listener)
+{
+  GList *new_list;
+
+  do
+  {
+    listener->id = listener_id++;
+  } while (!id_is_free (listener->id));
+  new_list = g_list_append (device_listeners, listener);
+  if (new_list) device_listeners = new_list;
+}
+
+static void
+atspi_device_listener_finalize (GObject *object)
+{
+  AtspiDeviceListener *listener = (AtspiDeviceListener *) object;
+  GList *l;
+  
+  for (l = listener->callbacks; l; l = l->next)
+    {
+      g_free (l->data);
+    }
+  
+  g_list_free (listener->callbacks);
+
+  device_parent_class->finalize (object);
+}
+
+static void
+atspi_device_listener_class_init (AtspiDeviceListenerClass *klass)
+{
+  GObjectClass *object_class = (GObjectClass *) klass;
+
+  device_parent_class = g_type_class_peek_parent (klass);
+  object_class->finalize = atspi_device_listener_finalize;
+
+  klass->device_event = atspi_device_event_dispatch;
+}
+
+G_DEFINE_TYPE (AtspiDeviceListener, atspi_device_listener,
+			  G_TYPE_OBJECT)
+
+AtspiDeviceListener *
+atspi_device_listener_new (void)
+{
+  AtspiDeviceListener *listener = g_object_new (atspi_device_listener_get_type (), NULL);
+
+  return listener;
+}
+
+void
+atspi_device_listener_add_cb (AtspiDeviceListener  *listener,
+			     AtspiDeviceListenerCB callback,
+			     void                      *user_data)
+{
+  g_return_if_fail (ATSPI_IS_DEVICE_LISTENER (listener));
+
+  listener->callbacks = g_list_prepend (listener->callbacks,
+					atspi_event_handler_new ((void *)callback, user_data));
+}
+
+void
+atspi_device_listener_remove_cb (AtspiDeviceListener  *listener,
+				AtspiDeviceListenerCB callback)
+{
+  g_return_if_fail (ATSPI_IS_DEVICE_LISTENER (listener));
+
+  listener->callbacks = event_list_remove_by_cb (listener->callbacks, (void *) callback);
+}
+
+static const char *device_event_type = "(uinnisb)";
+
+static void
+read_device_event_from_iter (DBusMessageIter *iter, AtspiDeviceEvent *event)
+{
+  dbus_uint32_t type;
+  dbus_int32_t id;
+  dbus_int16_t hw_code;
+  dbus_int16_t modifiers;
+  dbus_int32_t timestamp;
+  char *event_string;
+  dbus_bool_t is_text;
+  DBusMessageIter iter_struct;
+
+  dbus_message_iter_recurse (iter, &iter_struct);
+
+  dbus_message_iter_get_basic (&iter_struct, &type);
+  event->type = type;
+  dbus_message_iter_next (&iter_struct);
+
+  dbus_message_iter_get_basic (&iter_struct, &id);
+  event->id = id;
+  dbus_message_iter_next (&iter_struct);
+
+  dbus_message_iter_get_basic (&iter_struct, &hw_code);
+  event->hw_code = hw_code;
+  dbus_message_iter_next (&iter_struct);
+
+  dbus_message_iter_get_basic (&iter_struct, &modifiers);
+  event->modifiers = modifiers;
+  dbus_message_iter_next (&iter_struct);
+
+  dbus_message_iter_get_basic (&iter_struct, &timestamp);
+  event->timestamp = timestamp;
+  dbus_message_iter_next (&iter_struct);
+
+  dbus_message_iter_get_basic (&iter_struct, &event->event_string);
+  dbus_message_iter_next (&iter_struct);
+
+  dbus_message_iter_get_basic (&iter_struct, &is_text);
+  event->is_text = is_text;
+}
+
+/*
+ * atspi_dbus_handle_DeviceEvent: (skip)
+ */
+DBusHandlerResult
+atspi_dbus_handle_DeviceEvent (DBusConnection *bus, DBusMessage *message, void *data)
+{
+  const char *path = dbus_message_get_path (message);
+  int id;
+  AtspiDeviceEvent event;
+    AtspiDeviceListener *listener;
+  DBusMessageIter iter;
+  AtspiDeviceListenerClass *klass;
+  dbus_bool_t retval = FALSE;
+  GList *l;
+  DBusMessage *reply;
+  void *p = &event;
+
+  if (strcmp (dbus_message_get_signature (message), "(uinnisb)") != 0)
+  {
+    g_warning ("Atspi: Unknown signature for an event");
+    goto done;
+  }
+
+  if (sscanf (path, "/org/a11y/atspi/listeners/%d", &id) != 1)
+  {
+    g_warning ("Atspi: Bad listener path: %s\n", path);
+    goto done;
+  }
+
+  for (l = device_listeners; l; l = g_list_next (l))
+  {
+    listener = l->data;
+    if (listener->id == id) break;
+  }
+
+  if (!l)
+  {
+    goto done;
+  }
+  dbus_message_iter_init (message, &iter);
+  read_device_event_from_iter (&iter, &event);
+  klass = ATSPI_DEVICE_LISTENER_GET_CLASS (listener);
+  if (klass->device_event)
+  {
+    retval = (*klass->device_event) (listener, &event);
+  }
+done:
+  reply = dbus_message_new_method_return (message);
+  if (reply)
+  {
+    dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &retval, DBUS_TYPE_INVALID);
+    dbus_connection_send (_atspi_bus(), reply, NULL);
+    dbus_message_unref (reply);
+  }
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+gchar *
+_atspi_device_listener_get_path (AtspiDeviceListener *listener)
+{
+  return g_strdup_printf ("/org/a11y/atspi/listeners/%d", listener->id);
+}
diff --git a/atspi/atspi-listener.h b/atspi/atspi-listener.h
new file mode 100644
index 0000000..14fc6bf
--- /dev/null
+++ b/atspi/atspi-listener.h
@@ -0,0 +1,135 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ *           2002 Sun Microsystems Inc.
+ *           
+ *
+ * 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 _ATSPI_LISTENER_H_
+#define _ATSPI_LISTENER_H_
+
+#include "atspi-event-types.h"
+
+/*
+ * Function prototype typedefs for Event Listener Callbacks.
+ *
+ * usage: signatures should be
+ * void (*AtspiEventListenerCB) (AtspiEvent *event);
+ *
+ * gboolean (*AtspiKeystrokeListenerCB) (AtspiKeystrokeEvent *Event);
+ * Note that AtspiKeystrokeListeners may consume the event received
+ * if one of their callbacks returns TRUE (see atspi_register_accessible_keystroke_listener)
+ */
+
+/**
+ * AtspiEventListenerCB:
+ * @event: The event for which notification is sent.
+ * @user_data: User data which is passed to the callback each time a notification takes place.
+ *
+ * A function prototype for callbacks via which clients are notified of AT-SPI events.
+ * 
+ **/
+typedef void       (*AtspiEventListenerCB)     (const AtspiEvent     *event,
+						     void                      *user_data);
+
+/**
+ * AtspiDeviceListenerCB:
+ * @stroke: The #AtspiDeviceEvent for which notification is being received.
+ * @user_data: Data which is passed to the client each time this callback is notified.
+ *
+ * A callback function prototype via which clients receive device event notifications.
+ *
+ * Returns: %TRUE if the client wishes to consume/preempt the event, preventing it from being
+ * relayed to the currently focussed application, %FALSE if the event delivery should proceed as normal.
+ **/
+typedef gboolean (*AtspiDeviceListenerCB)    (const AtspiDeviceEvent *stroke,
+						     void                      *user_data);
+
+#define ATSPI_TYPE_DEVICE_LISTENER                        (atspi_device_listener_get_type ())
+#define ATSPI_DEVICE_LISTENER(obj)                        (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_DEVICE_LISTENER, AtspiDeviceListener))
+#define ATSPI_DEVICE_LISTENER_CLASS(klass)                (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_DEVICE_LISTENER, AtspiDeviceListenerClass))
+#define ATSPI_IS_DEVICE_LISTENER(obj)                     (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_DEVICE_LISTENER))
+#define ATSPI_IS_DEVICE_LISTENER_CLASS(klass)             (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_DEVICE_LISTENER))
+#define ATSPI_DEVICE_LISTENER_GET_CLASS(obj)              (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_DEVICE_LISTENER, AtspiDeviceListenerClass))
+
+#define ATSPI_TYPE_EVENT_LISTENER                        (atspi_event_listener_get_type ())
+#define ATSPI_EVENT_LISTENER(obj)                        (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_EVENT_LISTENER, AtspiEventListener))
+#define ATSPI_EVENT_LISTENER_CLASS(klass)                (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_EVENT_LISTENER, AtspiEventListenerClass))
+#define ATSPI_IS_EVENT_LISTENER(obj)                     (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_EVENT_LISTENER))
+#define ATSPI_IS_EVENT_LISTENER_CLASS(klass)             (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_EVENT_LISTENER))
+#define ATSPI_EVENT_LISTENER_GET_CLASS(obj)              (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_EVENT_LISTENER, AtspiEventListenerClass))
+
+typedef struct _AtspiEventListener AtspiEventListener;
+struct _AtspiEventListener
+{
+  GObject parent;
+  GList *callbacks;
+};
+
+typedef struct _AtspiEventListenerClass AtspiEventListenerClass;
+struct _AtspiEventListenerClass
+{
+  GObject parent_class;
+  void (*event) (AtspiEventListener *, const AtspiEvent *);
+};
+
+typedef struct _AtspiDeviceListener AtspiDeviceListener;
+struct _AtspiDeviceListener
+{
+  GObject parent;
+  GList *callbacks;
+  guint id;
+};
+
+typedef struct _AtspiDeviceListenerClass AtspiDeviceListenerClass;
+struct _AtspiDeviceListenerClass
+{
+  GObject parent_class;
+  gboolean (*device_event) (AtspiDeviceListener *, const AtspiDeviceEvent *);
+};
+
+AtspiEventListener *atspi_event_listener_new (void);
+
+void atspi_event_listener_add_cb (AtspiEventListener  *listener,
+			    AtspiEventListenerCB callback,
+			    void                     *user_data);
+
+void atspi_event_listener_remove_cb (AtspiEventListener  *listener,
+			       AtspiEventListenerCB callback);
+
+AtspiDeviceListener *
+atspi_device_listener_new (void);
+
+void
+atspi_device_listener_add_cb (AtspiDeviceListener  *listener,
+			     AtspiDeviceListenerCB callback,
+			     void                      *user_data);
+
+void
+atspi_device_listener_remove_cb (AtspiDeviceListener  *listener,
+				AtspiDeviceListenerCB callback);
+
+/* private */
+DBusHandlerResult
+atspi_dbus_handle_deviceEvent (DBusConnection *bus, DBusMessage *message, void *data);
+
+gchar *
+_atspi_device_listener_get_path (AtspiDeviceListener *listener);
+#endif	/* _ATSPI_LISTENER_H_ */
diff --git a/atspi/atspi-misc-private.h b/atspi/atspi-misc-private.h
new file mode 100644
index 0000000..15b831e
--- /dev/null
+++ b/atspi/atspi-misc-private.h
@@ -0,0 +1,114 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ *           2002 Sun Microsystems Inc.
+ *           
+ *
+ * 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 _ATSPI_MISC_PRIVATE_H_
+#define _ATSPI_MISC_PRIVATE_H_
+
+/* Private internal implementation details of at-spi. */
+
+#include "atspi.h"
+
+#include "dbus/dbus.h"
+
+#include "dbind/dbind.h"
+
+typedef struct _AtspiReference AtspiReference;
+struct _AtspiReference
+{
+  char *name;
+  char *path;
+};
+
+/* constants */
+#define ATSPI_DBUS_NAME_REGISTRY "org.a11y.atspi.Registry"
+#define ATSPI_DBUS_PATH_REGISTRY "/org/a11y/atspi/registry"
+#define ATSPI_DBUS_INTERFACE_REGISTRY "org.a11y.atspi.Registry"
+
+#define ATSPI_DBUS_PATH_NULL "/org/a11y/atspi/null"
+#define ATSPI_DBUS_PATH_ROOT "/org/a11y/atspi/accessible/root"
+
+#define ATSPI_DBUS_PATH_DEC "/org/a11y/atspi/registry/deviceeventcontroller"
+#define ATSPI_DBUS_INTERFACE_DEC "org.a11y.atspi.DeviceEventController"
+#define ATSPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER "org.a11y.atspi.DeviceEventListener"
+
+#define ATSPI_DBUS_INTERFACE_CACHE "org.a11y.atspi.Cache"
+#define ATSPI_DBUS_INTERFACE_ACCESSIBLE "org.a11y.atspi.Accessible"
+#define ATSPI_DBUS_INTERFACE_ACTION "org.a11y.atspi.Action"
+#define ATSPI_DBUS_INTERFACE_APPLICATION "org.a11y.atspi.Application"
+#define ATSPI_DBUS_INTERFACE_COLLECTION "org.a11y.atspi.Collection"
+#define ATSPI_DBUS_INTERFACE_COMPONENT "org.a11y.atspi.Component"
+#define ATSPI_DBUS_INTERFACE_DOCUMENT "org.a11y.atspi.Document"
+#define ATSPI_DBUS_INTERFACE_EDITABLE_TEXT "org.a11y.atspi.EditableText"
+#define ATSPI_DBUS_INTERFACE_EVENT_KEYBOARD "org.a11y.atspi.Event.Keyboard"
+#define ATSPI_DBUS_INTERFACE_EVENT_MOUSE "org.a11y.atspi.Event.Mouse"
+#define ATSPI_DBUS_INTERFACE_HYPERLINK "org.a11y.atspi.Hyperlink"
+#define ATSPI_DBUS_INTERFACE_HYPERTEXT "org.a11y.atspi.Hypertext"
+#define ATSPI_DBUS_INTERFACE_IMAGE "org.a11y.atspi.Image"
+#define ATSPI_DBUS_INTERFACE_SELECTION "org.a11y.atspi.Selection"
+#define ATSPI_DBUS_INTERFACE_TABLE "org.a11y.atspi.Table"
+#define ATSPI_DBUS_INTERFACE_TEXT "org.a11y.atspi.Text"
+#define ATSPI_DBUS_INTERFACE_VALUE "org.a11y.atspi.Value"
+#define ATSPI_DBUS_INTERFACE_SOCKET "org.a11y.atspi.Socket"
+
+/* externs */
+extern const char *atspi_path_dec;
+extern const char *atspi_path_registry;
+extern const char *atspi_path_root;
+extern const char *atspi_bus_registry;
+extern const char *atspi_interface_accessible;
+extern const char *atspi_interface_action;
+extern const char *atspi_interface_application;
+extern const char *atspi_interface_component;
+extern const char *atspi_interface_dec;
+extern const char *atspi_interface_device_event_listener;
+extern const char *atspi_interface_document;
+extern const char *atspi_interface_editable_text;
+extern const char *atspi_interface_hyperlink;
+extern const char *atspi_interface_hypertext;
+extern const char *atspi_interface_image;
+extern const char *atspi_interface_registry;
+extern const char *atspi_interface_selection;
+extern const char *atspi_interface_table;
+extern const char *atspi_interface_text;
+extern const char *atspi_interface_cache;
+extern const char *atspi_interface_value;
+
+/* function prototypes */
+DBusConnection * _atspi_bus ();
+
+AtspiAccessible * _atspi_ref_accessible (const char *app, const char *path);
+
+AtspiAccessible * _atspi_ref_related_accessible (AtspiAccessible *obj, const AtspiReference *ref);
+
+dbus_bool_t _atspi_dbus_call (AtspiAccessible *obj, const char *interface, const char *method, GError **error, const char *type, ...);
+
+DBusMessage *_atspi_dbus_call_partial (AtspiAccessible *obj, const char *interface, const char *method, GError **error, const char *type, ...);
+
+dbus_bool_t _atspi_dbus_get_property (AtspiAccessible *obj, const char *interface, const char *name, GError **error, const char *type, void *data);
+
+DBusMessage * _atspi_dbus_send_with_reply_and_block (DBusMessage *message);
+
+GHashTable *
+_atspi_dbus_hash_from_message (DBusMessage *message);
+#endif	/* _ATSPI_MISC_PRIVATE_H_ */
diff --git a/atspi/atspi-misc.c b/atspi/atspi-misc.c
new file mode 100644
index 0000000..874d533
--- /dev/null
+++ b/atspi/atspi-misc.c
@@ -0,0 +1,828 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ *
+ * Basic SPI initialization and event loop function prototypes
+ *
+ */
+
+#include "atspi-private.h"
+
+static DBusConnection *bus = NULL;
+static GHashTable *apps = NULL;
+static GHashTable *live_refs = NULL;
+static GQueue *exception_handlers = NULL;
+static DBusError exception;
+
+const char *atspi_path_dec = ATSPI_DBUS_PATH_DEC;
+const char *atspi_path_registry = ATSPI_DBUS_PATH_REGISTRY;
+const char *atspi_path_root = ATSPI_DBUS_PATH_ROOT;
+const char *atspi_bus_registry = ATSPI_DBUS_NAME_REGISTRY;
+const char *atspi_interface_accessible = ATSPI_DBUS_INTERFACE_ACCESSIBLE;
+const char *atspi_interface_action = ATSPI_DBUS_INTERFACE_ACTION;
+const char *atspi_interface_application = ATSPI_DBUS_INTERFACE_APPLICATION;
+const char *atspi_interface_component = ATSPI_DBUS_INTERFACE_COMPONENT;
+const char *atspi_interface_dec = ATSPI_DBUS_INTERFACE_DEC;
+const char *atspi_interface_device_event_listener = ATSPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER;
+const char *atspi_interface_document = ATSPI_DBUS_INTERFACE_DOCUMENT;
+const char *atspi_interface_editable_text = ATSPI_DBUS_INTERFACE_EDITABLE_TEXT;
+const char *atspi_interface_hyperlink = ATSPI_DBUS_INTERFACE_HYPERLINK;
+const char *atspi_interface_hypertext = ATSPI_DBUS_INTERFACE_HYPERTEXT;
+const char *atspi_interface_image = ATSPI_DBUS_INTERFACE_IMAGE;
+const char *atspi_interface_registry = ATSPI_DBUS_INTERFACE_REGISTRY;
+const char *atspi_interface_selection = ATSPI_DBUS_INTERFACE_SELECTION;
+const char *atspi_interface_table = ATSPI_DBUS_INTERFACE_TABLE;
+const char *atspi_interface_text = ATSPI_DBUS_INTERFACE_TEXT;
+const char *atspi_interface_cache = ATSPI_DBUS_INTERFACE_CACHE;
+const char *atspi_interface_value = ATSPI_DBUS_INTERFACE_VALUE;
+
+static const char *interfaces[] =
+{
+  ATSPI_DBUS_INTERFACE_ACCESSIBLE,
+  ATSPI_DBUS_INTERFACE_ACTION,
+  ATSPI_DBUS_INTERFACE_APPLICATION,
+  ATSPI_DBUS_INTERFACE_COLLECTION,
+  ATSPI_DBUS_INTERFACE_COMPONENT,
+  ATSPI_DBUS_INTERFACE_DOCUMENT,
+  ATSPI_DBUS_INTERFACE_EDITABLE_TEXT,
+  ATSPI_DBUS_INTERFACE_HYPERLINK,
+  ATSPI_DBUS_INTERFACE_HYPERTEXT,
+  ATSPI_DBUS_INTERFACE_IMAGE,
+  "org.a11y.atspi.LoginHelper",
+  ATSPI_DBUS_INTERFACE_SELECTION,
+  ATSPI_DBUS_INTERFACE_TABLE,
+  ATSPI_DBUS_INTERFACE_TEXT,
+  ATSPI_DBUS_INTERFACE_VALUE,
+  NULL
+};
+
+static gint get_iface_num (const char *iface)
+{
+  /* TODO: Use a binary search or hash to improve performance */
+  int i;
+
+  for (i = 0; interfaces[i]; i++)
+  {
+    if (!strcmp(iface, interfaces[i])) return i;
+  }
+  return -1;
+}
+
+static GHashTable *
+get_live_refs (void)
+{
+  if (!live_refs) 
+    {
+      live_refs = g_hash_table_new (g_direct_hash, g_direct_equal);
+    }
+  return live_refs;
+}
+
+DBusConnection *
+_atspi_bus ()
+{
+  return bus;
+}
+
+#define APP_IS_REGISTRY(app) (!strcmp (app->bus_name, atspi_bus_registry))
+
+static void
+cleanup ()
+{
+  GHashTable *refs;
+
+  refs = live_refs;
+  live_refs = NULL;
+  if (refs)
+    {
+      g_hash_table_destroy (refs);
+    }
+}
+
+static gboolean atspi_inited = FALSE;
+
+static GHashTable *app_hash = NULL;
+
+static AtspiApplication *
+get_application (const char *bus_name)
+{
+  AtspiApplication *app = NULL;
+  char *bus_name_dup;
+
+  if (!app_hash)
+  {
+    app_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_hash_table_unref);
+    if (!app_hash) return NULL;
+  }
+  app = g_hash_table_lookup (app_hash, bus_name);
+  if (app) return app;
+  bus_name_dup = g_strdup (bus_name);
+  if (!bus_name_dup) return NULL;
+  // TODO: change below to something that will send state-change:defunct notification if necessary */
+  app = g_new (AtspiApplication, 1);
+  if (!app) return NULL;
+  app->bus_name = bus_name_dup;
+  if (APP_IS_REGISTRY (app))
+  {
+    app->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+  }
+  else
+  {
+    app->hash = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_object_unref);
+  }
+  g_hash_table_insert (app_hash, bus_name_dup, app);
+  return app;
+}
+
+static AtspiAccessible *
+ref_accessible (const char *app_name, const char *path)
+{
+  int id;
+  guint *id_val;
+  AtspiApplication *app = get_application (app_name);
+  AtspiAccessible *a;
+
+  if (!strcmp (path, "/org/a11y/atspi/accessible/root"))
+    return g_object_ref (app->root);
+
+  if (sscanf (path, "/org/a11y/atspi/accessible/%d", &id) != 1)
+  {
+    return NULL;
+  }
+
+  a = g_hash_table_lookup (app->hash, &id);
+  if (a)
+  {
+    g_object_ref (a);
+    return a;
+  }
+  id_val = g_new (guint, 1);
+  if (!id_val) return NULL;
+  *id_val = id;
+  a = atspi_accessible_new ();
+  if (!a)
+  {
+    g_free (id_val);
+    return NULL;
+  }
+  a->app = app;
+  a->path = g_strdup_printf ("/org/a11y/atspi/accessible/%d", id);
+  g_hash_table_insert (app->hash, id_val, a);
+  g_object_ref (a);	/* for the hash */
+  return a;
+}
+
+typedef struct
+{
+  char *path;
+  char *parent;
+  GArray *children;
+  GArray *interfaces;
+  char *name;
+  dbus_uint32_t role;
+  char *description;
+  GArray *state_bitflags;
+} CACHE_ADDITION;
+
+static DBusHandlerResult
+handle_remove_accessible (DBusConnection *bus, DBusMessage *message, void *user_data)
+{
+  const char *sender = dbus_message_get_sender (message);
+  AtspiApplication *app;
+  const char *path;
+  DBusMessageIter iter, iter_struct;
+  const char *signature = dbus_message_get_signature (message);
+  AtspiAccessible *a;
+  int id;
+
+  if (strcmp (signature, "(so)") != 0)
+  {
+    g_warning ("at-spi: Unknown signature %s for RemoveAccessible", signature);
+    return DBUS_HANDLER_RESULT_HANDLED;
+  }
+
+  dbus_message_iter_init (message, &iter);
+  dbus_message_iter_recurse (&iter, &iter_struct);
+  dbus_message_iter_get_basic (&iter_struct, &sender);
+  dbus_message_iter_get_basic (&iter_struct, &path);
+  app = get_application (sender);
+  a = ref_accessible (sender, path);
+  if (a->accessible_parent && g_list_find (a->accessible_parent->children, a))
+  {
+    a->accessible_parent->children = g_list_remove (a->accessible_parent->children, a);
+    g_object_unref (a);
+  }
+  if (sscanf (a->path, "/org/a11y/atspi/accessible/%d", &id) == 1)
+  {
+    g_warning("atspi: FIX HASH REMOVE");
+    g_hash_table_remove (app->hash, id);
+  }
+  else
+    g_warning ("libspi: Strange path %s\n", a->path);
+  g_object_unref (a);	/* unref our own ref */
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static gboolean
+add_app_to_desktop (AtspiAccessible *a, const char *bus_name)
+{
+  DBusError error;
+  char *root_path;
+
+  dbus_error_init (&error);
+  AtspiAccessible *obj = ref_accessible (bus_name, atspi_path_root);
+  if (obj)
+  {
+    GList *new_list = g_list_append (a->children, obj);
+    if (new_list)
+    {
+      a->children = new_list;
+      return TRUE;
+    }
+  }
+  else
+  {
+    g_warning ("Error calling getRoot for %s: %s", bus_name, error.message);
+  }
+  return FALSE;
+}
+
+static void
+send_children_changed (AtspiAccessible *parent, AtspiAccessible *child, gboolean add)
+{
+  AtspiEvent e;
+
+  memset (&e, 0, sizeof(e));
+  e.type = (add? "object:children-changed:add": "object:children-changed:remove");
+  e.source = parent;
+  e.detail1 = g_list_index (parent->children, child);
+  atspi_dispatch_event (&e);
+}
+
+static void
+unref_object_and_descendants (AtspiAccessible *obj)
+{
+  GList *l;
+
+  for (l = obj->children; l; l = l->next)
+  {
+    unref_object_and_descendants (l->data);
+  }
+  g_object_unref_internal (obj, TRUE);
+}
+
+static gboolean
+remove_app_from_desktop (AtspiAccessible *a, const char *bus_name)
+{
+  GList *l;
+  AtspiAccessible *child;
+
+  for (l = a->children; l; l = l->next)
+  {
+    child = l->data;
+    if (!strcmp (bus_name, child->app->bus_name)) break;
+  }
+  if (!l)
+  {
+    g_warning ("Removing unregistered app %s; doing nothing\n", bus_name);
+    return FALSE;
+  }
+  send_children_changed (a, child, FALSE);
+  a->children = g_list_remove (a->children, child);
+  unref_object_and_descendants (child);
+  return TRUE;
+}
+
+static AtspiAccessible *desktop;
+
+static void
+get_reference_from_iter (DBusMessageIter *iter, const char **app_name, const char **path)
+{
+  DBusMessageIter iter_struct;
+
+  dbus_message_iter_recurse (iter, &iter_struct);
+  dbus_message_iter_get_basic (&iter_struct, &app_name);
+  dbus_message_iter_get_basic (&iter_struct, &path);
+  dbus_message_iter_next (iter);
+}
+
+static void
+add_accessible_from_iter (DBusMessageIter *iter)
+{
+  gint i;
+  GList *new_list;
+  DBusMessageIter iter_struct, iter_array;
+  const char *app_name, *path;
+  AtspiApplication *app;
+  AtspiAccessible *accessible;
+  const char *name, *description;
+  dbus_uint32_t role;
+  dbus_uint32_t *states;
+  int count;
+
+  dbus_message_iter_recurse (iter, &iter_struct);
+
+  /* get accessible */
+  get_reference_from_iter (&iter_struct, &app_name, &path);
+  accessible = ref_accessible (app_name, path);
+
+  /* get parent */
+  get_reference_from_iter (&iter_struct, &app_name, &path);
+  accessible->accessible_parent = ref_accessible (app_name, path);
+
+  /* Get children */
+  dbus_message_iter_recurse (&iter_struct, &iter_array);
+  while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+  {
+    AtspiAccessible *child;
+    get_reference_from_iter (&iter_array, &app_name, &path);
+    child = ref_accessible (app_name, path);
+    new_list = g_list_append (accessible->children, child);
+    if (new_list) accessible->children = new_list;
+  }
+
+  /* interfaces */
+  accessible->interfaces = 0;
+  dbus_message_iter_next (&iter_struct);
+  dbus_message_iter_recurse (&iter_struct, &iter_array);
+  while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+  {
+    const char *iface;
+    gint n;
+    dbus_message_iter_get_basic (&iter_array, &iface);
+    if (!strcmp (iface, "org.freedesktop.DBus.Introspectable")) continue;
+    n = get_iface_num (iface);
+    if (n == -1)
+    {
+      g_warning ("Unknown interface %s", iface);
+    }
+    else accessible->interfaces |= (1 << n);
+  }
+  dbus_message_iter_next (&iter_struct);
+
+  /* name */
+  dbus_message_iter_get_basic (&iter_struct, &name);
+  accessible->name = g_strdup (name);
+  dbus_message_iter_next (&iter_struct);
+
+  /* role */
+  dbus_message_iter_get_basic (&iter_struct, &role);
+  accessible->role = role;
+  dbus_message_iter_next (&iter_struct);
+
+  /* description */
+  dbus_message_iter_get_basic (&iter_struct, &description);
+  accessible->description = g_strdup (description);
+  dbus_message_iter_next (&iter_struct);
+
+  dbus_message_iter_recurse (&iter_struct, &iter_array);
+  dbus_message_iter_get_fixed_array (&iter_array, &states, &count);
+  if (count != 2)
+  {
+    g_warning ("at-spi: expected 2 values in states array; got %d\n", count);
+    accessible->states = atspi_state_set_new (0);
+  }
+  else
+  {
+    guint64 val = ((guint64)states [1]) << 32;
+    val += states [0];
+    accessible->states = atspi_state_set_new (val);
+  }
+  dbus_message_iter_next (&iter_struct);
+
+  /* This is a bit of a hack since the cache holds a ref, so we don't need
+   * the one provided for us anymore */
+  g_object_unref (accessible);
+}
+
+static void
+add_accessibles (const char *app_name)
+{
+  DBusError error;
+  DBusMessage *message, *reply;
+  DBusMessageIter iter, iter_array;
+
+  AtspiApplication *app = get_application (app_name);
+  /* TODO: Move this functionality into app initializer? */
+  dbus_error_init (&error);
+  message = dbus_message_new_method_call (app_name, "/org/a11y/atspi/accessible/cache", atspi_interface_cache, "GetItems");
+  reply = _atspi_dbus_send_with_reply_and_block (message);
+  if (!reply || strcmp (dbus_message_get_signature (reply), "a((so)(so)a(so)assusau)") != 0)
+  {
+    g_warning ("at-spi: Error in GetItems");
+    return;
+    if (reply)
+      dbus_message_unref (reply);
+  }
+  dbus_message_iter_init (reply, &iter);
+  dbus_message_iter_recurse (&iter, &iter_array);
+  while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+  {
+    add_accessible_from_iter (&iter_array);
+    dbus_message_iter_next (&iter_array);
+  }
+  dbus_message_unref (reply);
+}
+
+/* TODO: Do we stil need this function? */
+static AtspiAccessible *
+ref_accessible_desktop (AtspiApplication *app)
+{
+  DBusError error;
+  GArray *apps = NULL;
+  GArray *additions;
+  gint i;
+  DBusMessage *message, *reply;
+  DBusMessageIter iter, iter_array;
+
+  if (desktop)
+  {
+    g_object_ref (desktop);
+    return desktop;
+  }
+  desktop = atspi_accessible_new ();
+  if (!desktop)
+  {
+    return NULL;
+  }
+  g_hash_table_insert (app->hash, 0, desktop);
+  desktop->app = app;
+  g_object_ref (desktop);	/* for the hash */
+  desktop->name = g_strdup ("main");
+  dbus_error_init (&error);
+  message = dbus_message_new_method_call (atspi_bus_registry,
+	atspi_path_root,
+	atspi_interface_accessible,
+	"GetChildren");
+  if (!message)
+    return;
+  reply = _atspi_dbus_send_with_reply_and_block (message);
+  if (!reply || strcmp (dbus_message_get_signature (reply), "a(so") != 0)
+  {
+    g_error ("Couldn't get application list: %s", error.message);
+    if (reply)
+      dbus_message_unref (reply);
+    return;
+  }
+  dbus_message_iter_init (reply, &iter);
+  dbus_message_iter_recurse (&iter, &iter_array);
+  while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+  {
+    const char *app_name, *path;
+    get_reference_from_iter (&iter_array, &app_name, &path);
+    add_accessibles (app_name);
+    add_app_to_desktop (desktop, app_name);
+  }
+  dbus_message_unref (reply);
+  return desktop;
+}
+
+AtspiAccessible *
+_atspi_ref_accessible (const char *app, const char *path)
+{
+  AtspiApplication *a = get_application (app);
+  if (!a) return NULL;
+  if ( APP_IS_REGISTRY(a))
+  {
+    return ref_accessible_desktop (a);
+  }
+  return ref_accessible (app, path);
+}
+
+AtspiAccessible *
+_atspi_ref_related_accessible (AtspiAccessible *obj, const AtspiReference *ref)
+{
+  const char *app = (ref->name && ref->name[0]? ref->name: obj->app->bus_name);
+  return ref_accessible (app, obj->path);
+}
+
+const char *cache_signal_type = "((so)(so)a(so)assusau)";
+
+static DBusHandlerResult
+handle_add_accessible (DBusConnection *bus, DBusMessage *message, void *user_data)
+{
+  DBusMessageIter iter;
+  const char *sender = dbus_message_get_sender (message);
+  AtspiApplication *app = get_application (sender);
+  const char *type = cache_signal_type;
+
+  if (strcmp (dbus_message_get_signature (message), cache_signal_type) != 0)
+  {
+    g_warning ("atspi: AddAccessible with unknown signature %s\n", dbus_message_get_signature (message));
+    return;
+  }
+
+  dbus_message_iter_init (message, &iter);
+  add_accessible_from_iter (&iter);
+}
+
+static DBusHandlerResult
+atspi_dbus_filter (DBusConnection *bus, DBusMessage *message, void *data)
+{
+  int type = dbus_message_get_type (message);
+  const char *interface = dbus_message_get_interface (message);
+  const char *member = dbus_message_get_member (message); 
+  dbus_uint32_t v;
+  char *bus_name;
+
+  if (type == DBUS_MESSAGE_TYPE_SIGNAL &&
+      !strncmp (interface, "org.a11y.atspi.Event.", 28))
+  {
+    g_warning ("atspi: TODO: event");
+    //return handle_event (bus, message, data);
+  }
+  if (dbus_message_is_method_call (message, atspi_interface_device_event_listener, "notifyEvent"))
+  {
+    g_warning ("atspi: TODO: DeviceEvent");
+    //return handle_device_event (bus, message, data);
+  }
+  if (dbus_message_is_signal (message, atspi_interface_cache, "AddAccessible"))
+  {
+    return handle_add_accessible (bus, message, data);
+  }
+  if (dbus_message_is_signal (message, atspi_interface_cache, "RemoveAccessible"))
+  {
+    return handle_remove_accessible (bus, message, data);
+  }
+  /* TODO: Handle ChildrenChanged, StateChanged, PropertyChanged */
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static const char *signal_interfaces[] =
+{
+  "org.a11y.atspi.Event.Object",
+  "org.a11y.atspi.Event.Window",
+  "org.a11y.atspi.Event.Mouse",
+  "org.a11y.atspi.Event.Terminal",
+  "org.a11y.atspi.Event.Document",
+  "org.a11y.atspi.Event.Focus",
+  NULL
+};
+
+/**
+ * atspi_init:
+ *
+ * Connects to the accessibility registry and initializes the SPI.
+ *
+ * Returns: 0 on success, otherwise an integer error code.  
+ **/
+int
+atspi_init (void)
+{
+  DBusError error;
+  char *match;
+  int i;
+
+  if (atspi_inited)
+    {
+      return 1;
+    }
+
+  atspi_inited = TRUE;
+
+  g_type_init ();
+
+  get_live_refs();
+  g_atexit (cleanup);
+
+  dbus_error_init (&error);
+  bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
+  if (!bus)
+  {
+    g_error ("Couldn't get session bus");
+    return 2;
+  }
+  dbus_bus_register (bus, &error);
+  dbus_connection_setup_with_g_main(bus, g_main_context_default());
+  dbus_connection_add_filter (bus, atspi_dbus_filter, NULL, NULL);
+  match = g_strdup_printf ("type='signal',interface='%s',member='AddAccessible'", atspi_interface_cache);
+  dbus_error_init (&error);
+  dbus_bus_add_match (bus, match, &error);
+  g_free (match);
+  match = g_strdup_printf ("type='signal',interface='%s',member='RemoveAccessible'", atspi_interface_cache);
+  dbus_bus_add_match (bus, match, &error);
+  g_free (match);
+  for (i = 0; signal_interfaces[i]; i++)
+  {
+    match = g_strdup_printf ("type='signal',interface='%s'", signal_interfaces[i]);
+    dbus_bus_add_match (bus, match, &error);
+    g_free (match);
+  }
+  return 0;
+}
+
+  static GMainLoop *mainloop;
+
+/**
+ * atspi_event_main:
+ *
+ * Starts/enters the main event loop for the AT-SPI services.
+ *
+ * (NOTE: This method does not return control, it is exited via a call to
+ *  atspi_event_quit () from within an event handler).
+ *
+ **/
+void
+atspi_event_main (void)
+{
+  mainloop = g_main_loop_new (NULL, FALSE);
+  g_main_loop_run (mainloop);
+}
+
+/**
+ * atspi_event_quit:
+ *
+ * Quits the last main event loop for the SPI services,
+ * see atspi_event_main
+ **/
+void
+atspi_event_quit (void)
+{
+  g_main_loop_quit (mainloop);
+}
+
+/**
+ * atspi_exit:
+ *
+ * Disconnects from the Accessibility Registry and releases 
+ * any floating resources. Call only once at exit.
+ *
+ * Returns: 0 if there were no leaks, otherwise non zero.
+ **/
+int
+atspi_exit (void)
+{
+  int leaked;
+
+  if (!atspi_inited)
+    {
+      return 0;
+    }
+
+  atspi_inited = FALSE;
+
+  if (live_refs)
+    {
+      leaked = g_hash_table_size (live_refs);
+    }
+  else
+    {
+      leaked = 0;
+    }
+
+  cleanup ();
+
+  return leaked;
+}
+
+dbus_bool_t
+_atspi_dbus_call (AtspiAccessible *obj, const char *interface, const char *method, GError **error, const char *type, ...)
+{
+  va_list args;
+  dbus_bool_t retval;
+  DBusError err;
+
+  dbus_error_init (&err);
+  va_start (args, type);
+  retval = dbind_method_call_reentrant_va (_atspi_bus(), obj->app->bus_name, obj->path, interface, method, &err, type, args);
+  va_end (args);
+  if (dbus_error_is_set (&err))
+  {
+    /* TODO: Set gerror */
+    dbus_error_free (&err);
+  }
+  return retval;
+}
+
+DBusMessage *
+_atspi_dbus_call_partial (AtspiAccessible *obj, const char *interface, const char *method, GError **error, const char *type, ...)
+{
+  va_list args;
+  dbus_bool_t retval;
+  DBusError err;
+    DBusMessage *msg = NULL, *reply = NULL;
+    DBusMessageIter iter;
+    const char *p;
+
+  dbus_error_init (&err);
+  va_start (args, type);
+
+    msg = dbus_message_new_method_call (obj->app->bus_name, obj->path, interface, method);
+    if (!msg)
+        goto out;
+
+    p = type;
+    dbus_message_iter_init_append (msg, &iter);
+    dbind_any_marshal_va (&iter, &p, args);
+
+    reply = dbind_send_and_allow_reentry (_atspi_bus(), msg, &err);
+out:
+  va_end (args);
+  if (dbus_error_is_set (&err))
+  {
+    /* TODO: Set gerror */
+    dbus_error_free (&err);
+  }
+  return reply;
+}
+
+dbus_bool_t
+_atspi_dbus_get_property (AtspiAccessible *obj, const char *interface, const char *name, GError **error, const char *type, void *data)
+{
+  DBusMessage *message, *reply;
+  DBusMessageIter iter, iter_variant;
+  DBusError err;
+  dbus_bool_t retval = FALSE;
+
+  message = dbus_message_new_method_call (obj->app->bus_name, obj->path, "org.freedesktop.DBus.Properties", "Get");
+  if (!message)
+  {
+    // TODO: throw exception
+    goto done;
+  }
+  dbus_message_append_args (message, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
+  dbus_error_init (&err);
+  reply = dbus_connection_send_with_reply_and_block (_atspi_bus(), message, 1000, &err);
+  dbus_message_unref (message);
+  if (!reply)
+  {
+    // TODO: throw exception
+    goto done;
+  }
+  dbus_message_iter_init (reply, &iter);
+  dbus_message_iter_recurse (&iter, &iter_variant);
+  if (dbus_message_iter_get_arg_type (&iter_variant) != type[0])
+  {
+    g_warning ("atspi_dbus_get_property: Wrong type: expected %s, got %c\n", type, dbus_message_iter_get_arg_type (&iter_variant));
+    goto done;
+  }
+  dbus_message_iter_get_basic (&iter_variant, data);
+  dbus_message_unref (reply);
+  if (type[0] == 's') *(char **)data = g_strdup (*(char **)data);
+  retval = TRUE;
+done:
+  return retval;
+}
+
+DBusMessage *
+_atspi_dbus_send_with_reply_and_block (DBusMessage *message)
+{
+  DBusMessage *reply;
+  DBusError err;
+
+  dbus_error_init (&err);
+  g_warning ("TODO: Write _atspi_dbus_send_with_reply_and_block");
+  reply = dbus_connection_send_with_reply_and_block (_atspi_bus(), message, 1000, &err);
+  dbus_message_unref (message);
+  return reply;
+}
+
+GHashTable *
+_atspi_dbus_hash_from_message (DBusMessage *message)
+{
+  GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal);
+  DBusMessageIter iter, iter_array, iter_dict;
+  const char *signature;
+
+  signature = dbus_message_get_signature (message);
+
+  if (strcmp (signature, "a{ss}") != 0)
+    {
+      g_warning ("Trying to get hash from message of unexpected type %s\n", signature);
+      return NULL;
+    }
+
+  dbus_message_iter_init (message, &iter);
+  dbus_message_iter_recurse (&iter, &iter_array);
+  do
+  {
+    const char *name, *value;
+    dbus_message_iter_recurse (&iter_array, &iter_dict);
+    dbus_message_iter_get_basic (&iter_dict, &name);
+    dbus_message_iter_get_basic (&iter_dict, &value);
+    g_hash_table_insert (hash, g_strdup (name), g_strdup (value));
+  } while (dbus_message_iter_next (&iter_array));
+  return hash;
+}
+
diff --git a/atspi/atspi-misc.h b/atspi/atspi-misc.h
new file mode 100644
index 0000000..7cf13c7
--- /dev/null
+++ b/atspi/atspi-misc.h
@@ -0,0 +1,36 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ *           2002 Sun Microsystems Inc.
+ *           
+ *
+ * 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 _ATSPI_MISC_H_
+#define _ATSPI_MISC_H_
+
+int atspi_init (void);
+
+void atspi_event_main ();
+
+void atspi_event_quit ();
+
+int atspi_exit ();
+
+#endif	/* _ATSPI_MISC_H_ */
diff --git a/atspi/atspi-private.h b/atspi/atspi-private.h
new file mode 100644
index 0000000..fe06c1f
--- /dev/null
+++ b/atspi/atspi-private.h
@@ -0,0 +1,33 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ *           2002 Sun Microsystems Inc.
+ *           
+ *
+ * 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 _ATSPI_PRIVATE_H_
+#define _ATSPI_PRIVATE_H_
+
+#include "atspi-listener-private.h"
+#include "atspi-misc-private.h"
+
+#include "atspi.h"
+
+#endif	/* _ATSPI_PRIVATE_H_ */
diff --git a/atspi/atspi-registry.c b/atspi/atspi-registry.c
new file mode 100644
index 0000000..2e4763b
--- /dev/null
+++ b/atspi/atspi-registry.c
@@ -0,0 +1,364 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/* atspi_registry.c: Global functions wrapping the registry */
+
+#include "atspi-private.h"
+
+static GArray *desktops;
+
+/**
+ * atspi_get_desktop_count:
+ *
+ * Get the number of virtual desktops.
+ * NOTE: currently multiple virtual desktops are not implemented, this
+ *       function always returns '1'.
+ *
+ * Returns: an integer indicating the number of active virtual desktops.
+ **/
+gint
+atspi_get_desktop_count ()
+{
+  return 1;
+}
+
+/**
+ * atspi_get_desktop:
+ * @i: an integer indicating which of the accessible desktops is to be returned.
+ *
+ * Get the virtual desktop indicated by index @i.
+ * NOTE: currently multiple virtual desktops are not implemented.
+ *
+ * Returns: a pointer to the 'i-th' virtual desktop's #AtspiAccessible
+ * representation.
+ **/
+AtspiAccessible*
+atspi_get_desktop (gint i)
+{
+  if (i != 0) return NULL;
+  return _atspi_ref_accessible (atspi_bus_registry, atspi_path_root);
+}
+
+/**
+ * atspi_get_desktop_list:
+ * @desktop_list: a pointer to an array of #Accessible references.
+ *
+ * Get the list of virtual desktops.  On return, @list will point
+ *     to a newly-created, NULL terminated array of virtual desktop
+ *     pointers.
+ *     It is the responsibility of the caller to free this array when
+ *     it is no longer needed.
+ *
+ * Not Yet Implemented : this implementation always returns a single
+ * #Accessible desktop.
+ *
+ * Returns: an integer indicating how many virtual desktops have been
+ *          placed in the list pointed to by parameter @list.
+ **/
+/* TODO: Make this a garray */
+GArray *
+atspi_get_desktop_list ()
+{
+  GArray *array = g_array_new (TRUE, TRUE, sizeof (AtspiAccessible *));
+  AtspiAccessible *desktop;
+
+  desktop = _atspi_ref_accessible (atspi_bus_registry, atspi_path_root);
+  if (array)
+    g_array_index (array, AtspiAccessible *, 0) = desktop;
+  return array;
+}
+
+/**
+ * ATSPI_KEYSET_ALL_KEYS:
+ * @ATSPI_KEYSET_ALL_KEYS: A special value for an AccessibleKeySet type, which tacitly
+ *                       includes all keycodes and keyvals for the specified modifier set.
+ **/
+
+/**
+ * atspi_register_accessible_keystroke_listener:
+ * @listener:  a pointer to the #AccessibleKeystrokeListener for which
+ *             keystroke events are requested.
+ * @keys:      a pointer to the #AccessibleKeySet indicating which
+ *             keystroke events are requested, or #ATSPI_KEYSET_ALL_KEYS
+ *             to indicate that all keycodes and keyvals for the specified
+ *             modifier set are to be included.
+ * @modmask:   an #AccessibleKeyMaskType mask indicating which
+ *             key event modifiers must be set in combination with @keys,
+ *             events will only be reported for key events for which all
+ *             modifiers in @modmask are set.  If you wish to listen for
+ *             events with multiple modifier combinations you must call
+ *             registerAccessibleKeystrokeListener() once for each combination.
+ * @eventmask: an #AccessibleKeyMaskType mask indicating which
+ *             types of key events are requested (#ATSPI_KEY_PRESSED, etc.).
+ * @sync_type: a #AccessibleKeyListenerSyncType parameter indicating
+ *             the behavior of the notification/listener transaction.
+ *             
+ * Register a listener for keystroke events, either pre-emptively for
+ *             all windows (ATSPI_KEYLISTENER_ALL_WINDOWS),
+ *             non-preemptively (ATSPI_KEYLISTENER_NOSYNC), or
+ *             pre-emptively at the toolkit level (ATSPI_KEYLISTENER_CANCONSUME).
+ *             If ALL_WINDOWS or CANCONSUME are used, the event is consumed
+ *             upon receipt if one of @listener's callbacks returns #TRUE.
+ *             ( Other sync_type values may be available in the future )
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_register_accessible_keystroke_listener (AtspiKeystrokeListener  *listener,
+					 AtspiKeySet             *keys,
+					 AtspiKeyMaskType         modmask,
+					 AtspiKeyEventMask        eventmask,
+					 AtspiKeyListenerSyncType sync_type, GError **error)
+{
+  gchar *path = _atspi_device_listener_get_path (listener);
+  gint                                i;
+  GArray *key_set;
+  dbus_uint32_t key_events = 0;
+  AtspiControllerEventMask   controller_event_mask;
+  AtspiEventListenerMode     listener_mode;
+  gboolean                          retval = FALSE;
+  DBusError d_error;
+
+  if (!listener)
+    {
+      return retval;
+    }
+
+  /* copy the keyval filter values from the C api into the DBind KeySet */
+  if (keys)
+    {
+      key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), keys->len);
+      key_set->len = keys->len;
+      for (i = 0; i < keys->len; ++i)
+        {
+	  AtspiKeyDefinition *kd =  ((AtspiKeyDefinition *) key_set->data) + i;
+          kd->keycode = keys->keycodes[i];
+	  kd->keysym = keys->keysyms[i];
+	  if (keys->keystrings && keys->keystrings[i])
+	    {
+	      kd->keystring = keys->keystrings[i];
+	    } 
+          else 
+            {
+	      kd->keystring = "";
+	    }
+        }
+    }
+  else
+    {
+      key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0);
+    }
+	
+  /* copy the event filter values from the C api into the DBus key_events */
+  if (eventmask & ATSPI_KEY_PRESSED)
+    {
+      key_events |= (1 << ATSPI_KEY_PRESSED_EVENT);
+    }
+  if (eventmask & ATSPI_KEY_RELEASED)
+    {
+      key_events |= (1 << ATSPI_KEY_RELEASED_EVENT);
+    }
+  
+  controller_event_mask = (dbus_uint32_t) modmask;
+
+  listener_mode.synchronous =
+	  (dbus_bool_t) ((sync_type & ATSPI_KEYLISTENER_SYNCHRONOUS)!=0);
+  listener_mode.preemptive =
+	  (dbus_bool_t) ((sync_type & ATSPI_KEYLISTENER_CANCONSUME)!=0);
+  listener_mode.global =
+	  (dbus_bool_t) ((sync_type & ATSPI_KEYLISTENER_ALL_WINDOWS)!=0);
+
+    dbus_error_init (&d_error);
+    dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "RegisterKeystrokeListener", &d_error, "oa(iisi)uu(bbb)=>b", path, key_set, controller_event_mask, key_events, &listener_mode, &retval);
+
+  g_array_free (key_set, TRUE);
+  g_free (path);
+
+  return retval;
+}
+
+/**
+ * atspi_deregister_accessible_keystroke_listener:
+ * @listener: a pointer to the #AccessibleKeystrokeListener for which
+ *            keystroke events are requested.
+ * @modmask:  the key modifier mask for which this listener is to be
+ *            'deregistered' (of type #AtspiKeyMaskType).
+ *
+ * Removes a keystroke event listener from the registry's listener queue,
+ *            ceasing notification of events with modifiers matching @modmask.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_deregister_accessible_keystroke_listener (AtspiKeystrokeListener *listener,
+					   AtspiKeyMaskType        modmask, GError **error)
+{
+  gchar *path = _atspi_device_listener_get_path (listener);
+  AtspiControllerEventMask   controller_event_mask;
+  GArray *key_set;
+  dbus_uint32_t key_events = 0;
+  DBusError d_error;
+
+  dbus_error_init (&d_error);
+  if (!listener)
+    {
+      return FALSE;
+    }
+
+  controller_event_mask = (dbus_uint32_t) modmask;
+
+      key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0);
+    dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "DeregisterKeystrokeListener", &d_error, "oa(iisi)uu", path, &key_set, key_events, controller_event_mask);
+  g_free (path);
+  return TRUE;
+}
+
+/**
+ * atspi_register_device_event_listener:
+ * @listener:  a pointer to the #AtspiDeviceListener which requests
+ *             the events.
+ * @eventmask: an #AtspiDeviceEventMask mask indicating which
+ *             types of key events are requested (#ATSPI_KEY_PRESSED, etc.).
+ * @filter: Unused parameter.
+ *             
+ * Register a listener for device events, for instance button events.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_register_device_event_listener (AtspiDeviceListener  *listener,
+				 AtspiDeviceEventMask  event_mask,
+				 void                      *filter, GError **error)
+{
+  gboolean                          retval = FALSE;
+  dbus_uint32_t d_event_mask = event_mask;
+  gint                                i;
+  gchar *path = _atspi_device_listener_get_path (listener);
+  DBusError d_error;
+
+  dbus_error_init (&d_error);
+  if (!listener)
+    {
+      return retval;
+    }
+
+    dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "RegisterDeviceEventListener", &d_error, "ou=>b", path, d_event_mask, &retval);
+  g_free (path);
+  return retval;
+}
+
+/**
+ * atspi_deregister_device_event_listener:
+ * @listener: a pointer to the #AtspiDeviceListener for which
+ *            device events are requested.
+ * @filter: Unused parameter.
+ *
+ * Removes a device event listener from the registry's listener queue,
+ *            ceasing notification of events of the specified type.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_deregister_device_event_listener (AtspiDeviceListener *listener,
+				   void                     *filter, GError **error)
+{
+  dbus_uint32_t event_types = 0;
+  gchar *path = _atspi_device_listener_get_path (listener);
+  DBusError d_error;
+
+  dbus_error_init (&d_error);
+
+  if (!listener)
+    {
+      return FALSE;
+    }
+
+  event_types |= (1 << ATSPI_BUTTON_PRESSED_EVENT);
+  event_types |= (1 << ATSPI_BUTTON_RELEASED_EVENT);
+
+    dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "DeregisterDeviceEventListener", &d_error, "ou", path, event_types);
+  g_free (path);
+  return TRUE;
+}
+
+/**
+ * atspi_generate_keyboard_event:
+ * @keyval: a long integer indicating the keycode or keysym of the key event
+ *           being synthesized.
+ * @keystring: an (optional) UTF-8 string which, if @keyval is NULL,
+ *           indicates a 'composed' keyboard input string which is 
+ *           being synthesized; this type of keyboard event synthesis does
+ *           not emulate hardware keypresses but injects the string 
+ *           as though a composing input method (such as XIM) were used.
+ * @synth_type: a #AccessibleKeySynthType flag indicating whether @keyval
+ *           is to be interpreted as a keysym rather than a keycode
+ *           (ATSPI_KEYSYM), or whether to synthesize
+ *           ATSPI_KEY_PRESS, ATSPI_KEY_RELEASE, or both (ATSPI_KEY_PRESSRELEASE).
+ *
+ * Synthesize a keyboard event (as if a hardware keyboard event occurred in the
+ * current UI context).
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_generate_keyboard_event (glong keyval,
+			   const gchar *keystring,
+			   AtspiKeySynthType synth_type, GError **error)
+{
+  dbus_uint32_t d_synth_type = synth_type;
+  dbus_int32_t d_keyval = keyval;
+  DBusError d_error;
+
+  dbus_error_init (&d_error);
+  if (!keystring) keystring = "";
+    dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "GenerateKeyboardEvent", &d_error, "isu", d_keyval, keystring, d_synth_type);
+
+  return TRUE;
+}
+
+/**
+ * atspi_generate_mouse_event:
+ * @x: a #long indicating the screen x coordinate of the mouse event.
+ * @y: a #long indicating the screen y coordinate of the mouse event.
+ * @name: a string indicating which mouse event to be synthesized
+ *        (e.g. "b1p", "b1c", "b2r", "rel", "abs").
+ *
+ * Synthesize a mouse event at a specific screen coordinate.
+ * Most AT clients should use the #AccessibleAction interface when
+ * tempted to generate mouse events, rather than this method.
+ * Event names: b1p = button 1 press; b2r = button 2 release;
+ *              b3c = button 3 click; b2d = button 2 double-click;
+ *              abs = absolute motion; rel = relative motion.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_generate_mouse_event (glong x, glong y, const gchar *name, GError **error)
+{
+  dbus_int32_t dbus_x = x, dbus__y = y;
+  DBusError d_error;
+
+  dbus_error_init (&d_error);
+    dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "GenerateMouseEvent", &d_error, "iis", x, y, name);
+  return TRUE;
+}
diff --git a/atspi/atspi-registry.h b/atspi/atspi-registry.h
new file mode 100644
index 0000000..4fa64e9
--- /dev/null
+++ b/atspi/atspi-registry.h
@@ -0,0 +1,66 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ *           2002 Sun Microsystems Inc.
+ *           
+ *
+ * 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 _ATSPI_REGISTRY_H_
+#define _ATSPI_REGISTRY_H_
+
+#include "atspi-accessible.h"
+#include "atspi-event-types.h"
+#include "atspi-listener.h"
+
+gint atspi_get_desktop_count ();
+
+AtspiAccessible* atspi_get_desktop (gint i);
+
+GArray *atspi_get_desktop_list ();
+
+gboolean
+atspi_register_accessible_keystroke_listener (AtspiKeystrokeListener  *listener,
+					 AtspiKeySet             *keys,
+					 AtspiKeyMaskType         modmask,
+					 AtspiKeyEventMask        event_mask,
+					 AtspiKeyListenerSyncType sync_type, GError **error);
+
+gboolean
+atspi_deregister_accessible_keystroke_listener (AtspiKeystrokeListener *listener,
+					   AtspiKeyMaskType        modmask, GError **error);
+
+gboolean
+atspi_register_device_event_listener (AtspiDeviceListener  *listener,
+				 AtspiDeviceEventMask  eventmask,
+				 void                      *filter, GError **error);
+
+gboolean
+atspi_deregister_device_event_listener (AtspiDeviceListener *listener,
+				   void                     *filter, GError **error);
+
+gboolean
+atspi_generate_keyboard_event (glong keyval,
+			   const gchar *keystring,
+			   AtspiKeySynthType synth_type, GError **error);
+
+gboolean
+atspi_generate_mouse_event (glong x, glong y, const gchar *name, GError **error);
+
+#endif	/* _ATSPI_REGISTRY_H_ */
diff --git a/atspi/atspi-stateset.c b/atspi/atspi-stateset.c
new file mode 100644
index 0000000..74d45c3
--- /dev/null
+++ b/atspi/atspi-stateset.c
@@ -0,0 +1,28 @@
+#include "atspi-private.h"
+
+static void atspi_state_set_class_init (AtspiStateSetClass *klass);
+
+G_DEFINE_TYPE (AtspiStateSet, atspi_state_set, G_TYPE_OBJECT)
+
+static void
+atspi_state_set_init (AtspiStateSet *set)
+{
+  set->states = 0;
+}
+
+static void
+atspi_state_set_class_init (AtspiStateSetClass* klass)
+{
+}
+
+AtspiStateSet *
+atspi_state_set_new (gint64 states)
+{
+  AtspiStateSet *set;
+  
+  set = g_object_new (ATSPI_TYPE_STATE_SET, NULL);
+  g_return_val_if_fail (set != NULL, NULL);
+
+  set->states = states;
+  return set;
+}
diff --git a/atspi/atspi-stateset.h b/atspi/atspi-stateset.h
new file mode 100644
index 0000000..44690b5
--- /dev/null
+++ b/atspi/atspi-stateset.h
@@ -0,0 +1,29 @@
+#ifndef _ATSPI_STATE_SET_H_
+#define _ATSPI_STATE_SET_H_
+
+#define ATSPI_TYPE_STATE_SET                        (atspi_state_set_get_type ())
+#define ATSPI_STATE_SET(obj)                        (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_STATE_SET, AtspiStateSet))
+#define ATSPI_STATE_SET_CLASS(klass)                (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_STATE_SET, AtspiStateSetClass))
+#define ATSPI_IS_STATE_SET(obj)                     (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_STATE_SET))
+#define ATSPI_IS_STATE_SET_CLASS(klass)             (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_STATE_SET))
+#define ATSPI_STATE_SET_GET_CLASS(obj)              (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_STATE_SET, AtspiStateSetClass))
+
+typedef struct _AtspiStateSet AtspiStateSet;
+struct _AtspiStateSet
+{
+  GObject parent;
+  gint64 states;
+};
+
+typedef struct _AtspiStateSetClass AtspiStateSetClass;
+struct _AtspiStateSetClass
+{
+  GObjectClass parent_class;
+};
+
+GType atspi_state_set_get_type (void);
+
+AtspiStateSet *
+atspi_state_set_new (gint64 states);
+
+#endif	/* _ATSPI_STATE_SET_H_ */
diff --git a/atspi/atspi.h b/atspi/atspi.h
new file mode 100644
index 0000000..1d4c134
--- /dev/null
+++ b/atspi/atspi.h
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ *
+ * 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 _ATSPI_H
+#define _ATSPI_H
+
+#include "glib.h"
+
+#include "atspi-constants.h"
+#include "atspi-event-types.h"
+#include "atspi-accessible.h"
+#include "atspi-listener.h"
+#include "atspi-misc.h"
+#include "atspi-registry.h"
+
+#endif
diff --git a/configure.ac b/configure.ac
index 70533dc..8706931 100644
--- a/configure.ac
+++ b/configure.ac
@@ -160,6 +160,8 @@ else
 fi
 AC_SUBST(DBUS_SERVICES_DIR)
 
+GOBJECT_INTROSPECTION_CHECK([0.9.6])
+
 AC_SUBST(LIBTOOL_EXPORT_OPTIONS)
 
 AC_ARG_ENABLE([relocate],
@@ -175,7 +177,9 @@ AC_SUBST(enable_relocate)
 
 AC_CONFIG_FILES([Makefile
 	xml/Makefile
-libspi/Makefile
+	dbind/Makefile
+dbind/dbind-config.h
+	atspi/Makefile
 	registryd/Makefile
 	bus/at-spi-dbus-bus
 	bus/Makefile])
diff --git a/dbind/Makefile.am b/dbind/Makefile.am
new file mode 100644
index 0000000..f7e6f53
--- /dev/null
+++ b/dbind/Makefile.am
@@ -0,0 +1,22 @@
+noinst_LTLIBRARIES = libdbind.la
+
+AM_CPPFLAGS = \
+	-DG_LOG_DOMAIN=\"dbind\" \
+	-I$(top_srcdir) \
+	$(WARN_CFLAGS) \
+	$(DBUS_CFLAGS) \
+	$(GLIB_CFLAGS)
+
+libdbind_la_SOURCES = \
+        dbind-config.h \
+        dbind.h \
+	dbind.c \
+        dbind-any.h \
+	dbind-any.c
+libdbind_la_LIBADD = $(DBUS_LIBS) $(GLIB_LIBS)
+
+TESTS = dbtest
+
+check_PROGRAMS = dbtest
+dbtest_SOURCES = dbtest.c
+dbtest_LDFLAGS = libdbind.la
diff --git a/dbind/dbind-any.c b/dbind/dbind-any.c
new file mode 100644
index 0000000..95dd9ab
--- /dev/null
+++ b/dbind/dbind-any.c
@@ -0,0 +1,670 @@
+/* type driven marshalling */
+#include <stdio.h>
+#include <glib.h>
+
+#include "config.h"
+#include "dbind-config.h"
+#include "dbind-any.h"
+
+#undef DEBUG
+
+/*  Align a value upward to a boundary, expressed as a number of bytes.
+ *  E.g. align to an 8-byte boundary with argument of 8.
+ *
+ *   (this + boundary - 1)
+ *          &
+ *    ~(boundary - 1)
+ */
+#define ALIGN_VALUE(this, boundary) \
+  (( ((gulong)(this)) + (((gulong)(boundary)) -1)) & (~(((gulong)(boundary))-1)))
+
+#define ALIGN_ADDRESS(this, boundary) \
+  ((gpointer)ALIGN_VALUE(this, boundary))
+
+#define PTR_PLUS(ptr, offset) \
+        ((gpointer) (((guchar *)(ptr)) + (offset)))
+
+#define DBIND_POD_CASES \
+         DBUS_TYPE_BYTE: \
+    case DBUS_TYPE_INT16: \
+    case DBUS_TYPE_UINT16: \
+    case DBUS_TYPE_INT32: \
+    case DBUS_TYPE_UINT32: \
+    case DBUS_TYPE_BOOLEAN: \
+    case DBUS_TYPE_INT64: \
+    case DBUS_TYPE_UINT64: \
+    case DBUS_TYPE_DOUBLE
+
+/*---------------------------------------------------------------------------*/
+
+static void
+warn_braces ()
+{
+    fprintf (stderr, "Error: dbus flags structures & dicts with braces rather than "
+             " an explicit type member of 'struct'\n");
+}
+
+/*---------------------------------------------------------------------------*/
+
+static unsigned int
+dbind_find_c_alignment_r (const char **type)
+{
+    unsigned int retval = 1;
+
+    char t = **type;
+    (*type)++;
+
+#ifdef DEBUG
+    fprintf (stderr, "\tfind align for %c (0x%x)\n", t, t);
+#endif
+
+        switch (t) {
+    case DBUS_TYPE_BYTE:
+        return DBIND_ALIGNOF_CHAR;
+    case DBUS_TYPE_BOOLEAN:
+        return DBIND_ALIGNOF_DBUS_BOOL_T;
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+        return DBIND_ALIGNOF_DBUS_INT16_T;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+        return DBIND_ALIGNOF_DBUS_INT32_T;
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+        return DBIND_ALIGNOF_DBUS_INT64_T;
+    case DBUS_TYPE_DOUBLE:
+        return DBIND_ALIGNOF_DOUBLE;
+    /* ptr types */
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_OBJECT_PATH:
+    case DBUS_TYPE_SIGNATURE:
+    case DBUS_TYPE_ARRAY:
+        return DBIND_ALIGNOF_DBIND_POINTER;
+    case DBUS_STRUCT_BEGIN_CHAR:
+      /* TODO: I think this would break with a nested struct */
+#if DBIND_ALIGNOF_DBIND_STRUCT > 1
+                retval = MAX (retval, DBIND_ALIGNOF_DBIND_STRUCT);
+#endif
+        while (**type != DBUS_STRUCT_END_CHAR) {
+            int elem_align = dbind_find_c_alignment_r (type);
+                        retval = MAX (retval, elem_align);
+        }
+        (*type)++;
+        return retval;
+    case DBUS_DICT_ENTRY_BEGIN_CHAR:
+#if DBIND_ALIGNOF_DBIND_STRUCT > 1
+                retval = MAX (retval, DBIND_ALIGNOF_DBIND_STRUCT);
+#endif
+        while (**type != DBUS_DICT_ENTRY_END_CHAR) {
+            int elem_align = dbind_find_c_alignment_r (type);
+                        retval = MAX (retval, elem_align);
+        }
+        (*type)++;
+        return retval;
+    case DBUS_TYPE_STRUCT:
+    case DBUS_TYPE_DICT_ENTRY:
+        warn_braces ();
+        return DBIND_ALIGNOF_DBIND_POINTER;
+    case '\0':
+        g_assert_not_reached();
+        break;
+    default:
+                return 1;
+  }
+}
+
+/*---------------------------------------------------------------------------*/
+
+/* gather immediate allocation information for this type */
+static size_t
+dbind_gather_alloc_info_r (const char **type)
+{
+  char t = **type;
+  (*type)++;
+  if (t == DBUS_TYPE_ARRAY)
+    {
+      switch (**type)
+        {
+          case DBUS_STRUCT_BEGIN_CHAR:
+              while (**type != DBUS_STRUCT_END_CHAR && **type != '\0') (*type)++;
+              if (**type != '\0') (*type)++;
+              break;
+          case DBUS_DICT_ENTRY_BEGIN_CHAR:
+              while (**type != DBUS_DICT_ENTRY_END_CHAR && **type != '\0') (*type)++;
+              if (**type != '\0') (*type)++;
+              break;
+          case '\0':
+              break;
+          default:
+              (*type)++;
+              break;
+        }
+    }
+
+  switch (t) {
+    case DBUS_TYPE_BYTE:
+        return sizeof (char);
+    case DBUS_TYPE_BOOLEAN:
+        return sizeof (dbus_bool_t);
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+        return sizeof (dbus_int16_t);
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+        return sizeof (dbus_int32_t);
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+        return sizeof (dbus_int64_t);
+    case DBUS_TYPE_DOUBLE:
+        return sizeof (double);
+    /* ptr types */
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_OBJECT_PATH:
+    case DBUS_TYPE_SIGNATURE:
+    case DBUS_TYPE_ARRAY:
+        return sizeof (void *);
+    case DBUS_STRUCT_BEGIN_CHAR: {
+                int sum = 0, stralign;
+
+        stralign = dbind_find_c_alignment (*type - 1);
+
+        while (**type != DBUS_STRUCT_END_CHAR) {
+                        sum = ALIGN_VALUE (sum, dbind_find_c_alignment (*type));
+                        sum += dbind_gather_alloc_info_r (type);
+        }
+                sum = ALIGN_VALUE (sum, stralign);
+
+        g_assert (**type == DBUS_STRUCT_END_CHAR);
+        (*type)++;
+
+                return sum;
+    }
+    case DBUS_DICT_ENTRY_BEGIN_CHAR: {
+                int sum = 0, stralign;
+
+        stralign = dbind_find_c_alignment (*type - 1);
+
+        while (**type != DBUS_DICT_ENTRY_END_CHAR) {
+                        sum = ALIGN_VALUE (sum, dbind_find_c_alignment (*type));
+                        sum += dbind_gather_alloc_info_r (type);
+        }
+                sum = ALIGN_VALUE (sum, stralign);
+
+        g_assert (**type == DBUS_DICT_ENTRY_END_CHAR);
+        (*type)++;
+
+                return sum;
+    }
+    case DBUS_TYPE_STRUCT:
+    case DBUS_TYPE_DICT_ENTRY:
+        warn_braces ();
+    default:
+        return 0;
+  }
+}
+
+static size_t
+dbind_gather_alloc_info (const char *type)
+{
+  return dbind_gather_alloc_info_r (&type);
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void
+dbind_any_free_r (const char **type, void **data)
+{
+#ifdef DEBUG
+    fprintf (stderr, "any free '%c' to %p\n", **type, *data);
+#endif
+
+    switch (**type) {
+    case DBIND_POD_CASES:
+        *data = ((guchar *)*data) + dbind_gather_alloc_info (*type);
+        (*type)++;
+        break;
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_OBJECT_PATH:
+    case DBUS_TYPE_SIGNATURE:
+#ifdef DEBUG
+        fprintf (stderr, "string free %p\n", **(void ***)data);
+#endif
+        g_free (**(void ***)data);
+        *data = ((guchar *)*data) + dbind_gather_alloc_info (*type);
+        (*type)++;
+        break;
+    case DBUS_TYPE_ARRAY: {
+        int i;
+        GArray *vals = **(void ***)data;
+        size_t elem_size, elem_align;
+        const char *saved_child_type;
+
+        (*type)++;
+        saved_child_type = *type;
+
+        elem_size = dbind_gather_alloc_info (*type);
+        elem_align = dbind_find_c_alignment_r (type); 
+
+        for (i = 0; i < vals->len; i++) {
+            void *ptr = vals->data + elem_size * i;
+            *type = saved_child_type; /* rewind type info */
+            ptr = ALIGN_ADDRESS (ptr, elem_align);
+            dbind_any_free_r (type, &ptr);
+        }
+        g_array_free (vals, TRUE);
+        break;
+    }
+    case DBUS_STRUCT_BEGIN_CHAR: {
+                gconstpointer data0 = *data;
+                int offset = 0, stralign;
+
+        stralign = dbind_find_c_alignment (*type);
+        (*type)++;
+
+        offset = 0 ;
+        while (**type != DBUS_STRUCT_END_CHAR) {
+            const char *subt = *type;
+                        offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
+                        *data = PTR_PLUS (data0, offset);
+            dbind_any_free_r (type, data);
+            offset += dbind_gather_alloc_info (subt);
+        }
+
+                offset = ALIGN_VALUE (offset, stralign);
+                *data = PTR_PLUS (data0, offset);
+
+        g_assert (**type == DBUS_STRUCT_END_CHAR);
+        (*type)++;
+
+        break;
+    }
+    case DBUS_DICT_ENTRY_BEGIN_CHAR: {
+                gconstpointer data0 = *data;
+                int offset = 0, stralign;
+
+        stralign = dbind_find_c_alignment (*type);
+        (*type)++;
+
+        offset = 0 ;
+        while (**type != DBUS_DICT_ENTRY_END_CHAR) {
+            char *subt = *type;
+                        offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
+                        *data = PTR_PLUS (data0, offset);
+            dbind_any_free_r (type, data);
+            offset += dbind_gather_alloc_info (subt);
+        }
+
+                offset = ALIGN_VALUE (offset, stralign);
+                *data = PTR_PLUS (data0, offset);
+
+        g_assert (**type == DBUS_DICT_ENTRY_END_CHAR);
+        (*type)++;
+
+        break;
+    }
+    case DBUS_TYPE_STRUCT:
+    case DBUS_TYPE_DICT_ENTRY:
+        warn_braces ();
+        break;
+    }
+}
+
+/*---------------------------------------------------------------------------*/
+
+void
+dbind_any_marshal (DBusMessageIter *iter,
+                   const char           **type,
+                   void           **data)
+{
+    size_t len;
+
+#ifdef DEBUG
+    fprintf (stderr, "any marshal '%c' to %p\n", **type, *data);
+#endif
+
+    switch (**type) {
+    case DBIND_POD_CASES:
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_OBJECT_PATH:
+    case DBUS_TYPE_SIGNATURE:
+        len = dbind_gather_alloc_info (*type);
+        dbus_message_iter_append_basic (iter, **type, *data);
+        *data = ((guchar *)*data) + len;
+        (*type)++;
+        break;
+    case DBUS_TYPE_ARRAY: {
+        int i;
+        GArray *vals = **(void ***)data;
+        size_t elem_size, elem_align;
+        DBusMessageIter sub;
+        const char *saved_child_type;
+        char *child_type_string;
+
+        (*type)++;
+        saved_child_type = *type;
+
+        elem_size = dbind_gather_alloc_info (*type);
+        elem_align = dbind_find_c_alignment_r (type); 
+
+        /* wow this part of the API sucks too ... */
+        child_type_string = g_strndup (saved_child_type, *type - saved_child_type);
+        /* fprintf (stderr, "array child type '%s'\n", child_type_string); */
+        dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY,
+                                          child_type_string, &sub);
+        for (i = 0; i < vals->len; i++) {
+            void *ptr = vals->data + elem_size * i;
+            *type = saved_child_type; /* rewind type info */
+            ptr = ALIGN_ADDRESS (ptr, elem_align);
+            dbind_any_marshal (&sub, type, &ptr);
+        }
+
+        dbus_message_iter_close_container (iter, &sub);
+        g_free (child_type_string);
+        break;
+    }
+    case DBUS_STRUCT_BEGIN_CHAR: {
+                gconstpointer data0 = *data;
+                int offset = 0, stralign;
+        DBusMessageIter sub;
+
+        stralign = dbind_find_c_alignment (*type);
+
+        (*type)++;
+
+        dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, &sub);
+
+        offset = 0 ;
+        while (**type != DBUS_STRUCT_END_CHAR) {
+            const char *subt = *type;
+                        offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
+                        *data = PTR_PLUS (data0, offset);
+            dbind_any_marshal (&sub, type, data);
+            offset += dbind_gather_alloc_info (subt);
+        }
+
+                offset = ALIGN_VALUE (offset, stralign);
+                *data = PTR_PLUS (data0, offset);
+
+        dbus_message_iter_close_container (iter, &sub);
+
+        g_assert (**type == DBUS_STRUCT_END_CHAR);
+        (*type)++;
+
+        break;
+    }
+    case DBUS_DICT_ENTRY_BEGIN_CHAR: {
+                gconstpointer data0 = *data;
+                int offset = 0, stralign;
+        DBusMessageIter sub;
+
+        stralign = dbind_find_c_alignment (*type);
+
+        (*type)++;
+
+        dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL, &sub);
+
+        offset = 0 ;
+        while (**type != DBUS_DICT_ENTRY_END_CHAR) {
+            char *subt = *type;
+                        offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
+                        *data = PTR_PLUS (data0, offset);
+            dbind_any_marshal (&sub, type, data);
+            offset += dbind_gather_alloc_info (subt);
+        }
+
+                offset = ALIGN_VALUE (offset, stralign);
+                *data = PTR_PLUS (data0, offset);
+
+        dbus_message_iter_close_container (iter, &sub);
+
+        g_assert (**type == DBUS_DICT_ENTRY_END_CHAR);
+        (*type)++;
+
+        break;
+    }
+    case DBUS_TYPE_STRUCT:
+    case DBUS_TYPE_DICT_ENTRY:
+        warn_braces ();
+        break;
+    }
+}
+
+/*---------------------------------------------------------------------------*/
+
+void
+dbind_any_marshal_va (DBusMessageIter *iter,
+                      const char           **arg_types,
+                      va_list          args)
+{
+    const char *p = *arg_types;
+
+    /* Guard against null arg types 
+       Fix for - http://bugs.freedesktop.org/show_bug.cgi?id=23027
+     */
+    if (p == NULL)
+        p = "";
+
+    {
+        /* special case base-types since we need to walk the stack worse-luck */
+        for (;*p != '\0' && *p != '=';) {
+            int intarg;
+            void *ptrarg;
+            double doublearg;
+            dbus_int64_t int64arg;
+            void *arg = NULL;
+
+            switch (*p) {
+            case DBUS_TYPE_BYTE:
+            case DBUS_TYPE_BOOLEAN:
+            case DBUS_TYPE_INT16:
+            case DBUS_TYPE_UINT16:
+            case DBUS_TYPE_INT32:
+            case DBUS_TYPE_UINT32:
+                intarg = va_arg (args, int);
+                arg = &intarg;
+                break;
+            case DBUS_TYPE_INT64:
+            case DBUS_TYPE_UINT64:
+                int64arg = va_arg (args, dbus_int64_t);
+                arg = &int64arg;
+                break;
+            case DBUS_TYPE_DOUBLE:
+                doublearg = va_arg (args, double);
+                arg = &doublearg;
+                break;
+            /* ptr types */
+            case DBUS_TYPE_STRING:
+            case DBUS_TYPE_OBJECT_PATH:
+            case DBUS_TYPE_SIGNATURE:
+            case DBUS_TYPE_ARRAY:
+            case DBUS_TYPE_DICT_ENTRY:
+                ptrarg = va_arg (args, void *);
+                arg = &ptrarg;
+                break;
+            case DBUS_STRUCT_BEGIN_CHAR:
+                ptrarg = va_arg (args, void *);
+                arg = ptrarg;
+                break;
+            case DBUS_DICT_ENTRY_BEGIN_CHAR:
+                ptrarg = va_arg (args, void *);
+                arg = ptrarg;
+                break;
+
+            case DBUS_TYPE_VARIANT:
+                fprintf (stderr, "No variant support yet - very toolkit specific\n");
+                ptrarg = va_arg (args, void *);
+                arg = &ptrarg;
+                break;
+            default:
+                fprintf (stderr, "Unknown / invalid arg type %c\n", *p);
+                break;
+            }
+            if (arg != NULL)
+                dbind_any_marshal (iter, &p, &arg);
+            }
+    }
+}
+
+/*---------------------------------------------------------------------------*/
+
+void
+dbind_any_demarshal (DBusMessageIter *iter,
+                     const char           **type,
+                     void           **data)
+{
+    size_t len;
+
+#ifdef DEBUG
+    fprintf (stderr, "any demarshal '%c' to %p\n", **type, *data);
+#endif
+
+    switch (**type) {
+    case DBIND_POD_CASES:
+        len = dbind_gather_alloc_info (*type);
+        dbus_message_iter_get_basic (iter, *data);
+        *data = ((guchar *)*data) + len;
+        (*type)++;
+        break;
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_OBJECT_PATH:
+    case DBUS_TYPE_SIGNATURE:
+        len = dbind_gather_alloc_info (*type);
+        dbus_message_iter_get_basic (iter, *data);
+#ifdef DEBUG
+        fprintf (stderr, "dup string '%s' (%p)\n", **(void ***)data, **(void ***)data);
+#endif
+        **(void ***)data = g_strdup (**(void ***)data);
+        *data = ((guchar *)*data) + len;
+        (*type)++;
+        break;
+    case DBUS_TYPE_ARRAY: {
+        GArray *vals;
+        DBusMessageIter child;
+        size_t elem_size, elem_align;
+        const char *stored_child_type;
+        int i;
+
+        (*type)++;
+        stored_child_type = *type;
+
+        elem_size = dbind_gather_alloc_info (*type);
+        elem_align = dbind_find_c_alignment_r (type);
+        vals = g_array_new (FALSE, FALSE, elem_size);
+        (**(void ***)data) = vals;
+        *data = ((guchar *)*data) + sizeof (void *);
+
+        i = 0;
+        dbus_message_iter_recurse (iter, &child);
+        while (dbus_message_iter_get_arg_type (&child) != DBUS_TYPE_INVALID) {
+            void *ptr;
+            const char *subt = stored_child_type;
+            g_array_set_size (vals, i + 1);
+            ptr = vals->data + elem_size * i;
+            ptr = ALIGN_ADDRESS (ptr, elem_align);
+            dbind_any_demarshal (&child, &subt, &ptr);
+            i++;
+        };
+        break;
+    }
+    case DBUS_STRUCT_BEGIN_CHAR: {
+                gconstpointer data0 = *data;
+                int offset = 0, stralign;
+        DBusMessageIter child;
+
+        stralign = dbind_find_c_alignment (*type);
+
+        (*type)++;
+
+        dbus_message_iter_recurse (iter, &child);
+
+        while (**type != DBUS_STRUCT_END_CHAR) {
+            const char *subt = *type;
+                        offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
+                        *data = PTR_PLUS (data0, offset);
+            dbind_any_demarshal (&child, type, data);
+            offset += dbind_gather_alloc_info (subt);
+        }
+
+                offset = ALIGN_VALUE (offset, stralign);
+                *data = PTR_PLUS (data0, offset);
+
+        g_assert (**type == DBUS_STRUCT_END_CHAR);
+        (*type)++;
+
+        break;
+    }
+    case DBUS_DICT_ENTRY_BEGIN_CHAR: {
+                gconstpointer data0 = *data;
+                int offset = 0, stralign;
+        DBusMessageIter child;
+
+        stralign = dbind_find_c_alignment (*type);
+
+        (*type)++;
+
+        dbus_message_iter_recurse (iter, &child);
+
+        while (**type != DBUS_DICT_ENTRY_END_CHAR) {
+            char *subt = *type;
+                        offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
+                        *data = PTR_PLUS (data0, offset);
+            dbind_any_demarshal (&child, type, data);
+            offset += dbind_gather_alloc_info (subt);
+        }
+
+                offset = ALIGN_VALUE (offset, stralign);
+                *data = PTR_PLUS (data0, offset);
+
+        g_assert (**type == DBUS_DICT_ENTRY_END_CHAR);
+        (*type)++;
+
+        break;
+    }
+    case DBUS_TYPE_STRUCT:
+    case DBUS_TYPE_DICT_ENTRY:
+        warn_braces ();
+        break;
+    }
+    dbus_message_iter_next (iter);
+}
+
+/*---------------------------------------------------------------------------*/
+
+void
+dbind_any_demarshal_va (DBusMessageIter *iter,
+                        const char           **arg_types,
+                        va_list          args)
+{
+    const char *p = *arg_types;
+    for (;*p != '\0';) {
+        void *arg = va_arg (args, void *);
+        dbind_any_demarshal (iter, &p, &arg);
+    }
+}
+
+/*---------------------------------------------------------------------------*/
+
+/* nice deep free ... */
+void
+dbind_any_free (const char *type,
+                void *ptr)
+{
+    dbind_any_free_r (&type, &ptr);
+}
+
+/* should this be the default normalization ? */
+void
+dbind_any_free_ptr (const char *type, void *ptr)
+{
+    dbind_any_free (type, &ptr);
+}
+
+/*---------------------------------------------------------------------------*/
+
+unsigned int
+dbind_find_c_alignment (const char *type)
+{
+    return dbind_find_c_alignment_r (&type);
+}
+
+/*END------------------------------------------------------------------------*/
diff --git a/dbind/dbind-any.h b/dbind/dbind-any.h
new file mode 100644
index 0000000..4aa0b95
--- /dev/null
+++ b/dbind/dbind-any.h
@@ -0,0 +1,31 @@
+#ifndef _DBIND_ANY_H_
+#define _DBIND_ANY_H_
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus.h>
+
+unsigned int dbind_find_c_alignment (const char *type);
+
+void   dbind_any_marshal       (DBusMessageIter *iter,
+                                const char           **type,
+                                void           **val);
+
+void   dbind_any_marshal_va    (DBusMessageIter *iter,
+                                const const char           **arg_types,
+                                va_list          args);
+
+void   dbind_any_demarshal     (DBusMessageIter *iter,
+                                const char           **type,
+                                void           **val);
+
+void   dbind_any_demarshal_va  (DBusMessageIter *iter,
+                                const char           **arg_types,
+                                va_list          args);
+
+void   dbind_any_free          (const char      *type,
+                                void            *ptr_to_ptr);
+
+void   dbind_any_free_ptr      (const char      *type,
+                                void            *ptr);
+
+#endif /* _DBIND_ANY_H_ */
diff --git a/dbind/dbind.c b/dbind/dbind.c
new file mode 100644
index 0000000..5c49d66
--- /dev/null
+++ b/dbind/dbind.c
@@ -0,0 +1,230 @@
+
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <glib.h>
+
+#include "config.h"
+#include "dbind/dbind.h"
+
+/*
+ * FIXME: compare types - to ensure they match &
+ *        do dynamic padding of structures etc.
+ */
+
+/*---------------------------------------------------------------------------*/
+
+static void
+set_reply (DBusPendingCall *pending, void *user_data)
+{
+    void **replyptr = (void **)user_data;
+
+    *replyptr = dbus_pending_call_steal_reply (pending);
+}
+
+DBusMessage *
+dbind_send_and_allow_reentry (DBusConnection *bus, DBusMessage *message, DBusError *error)
+{
+    DBusPendingCall *pending;
+    DBusMessage *reply = NULL;
+
+    if (!dbus_connection_send_with_reply (bus, message, &pending, -1))
+    {
+        return NULL;
+    }
+    dbus_pending_call_set_notify (pending, set_reply, (void *)&reply, NULL);
+    while (!reply)
+    {
+      if (!dbus_connection_read_write_dispatch (bus, -1)) return NULL;
+    }
+    return reply;
+}
+
+dbus_bool_t
+dbind_method_call_reentrant_va (DBusConnection *cnx,
+                                const char     *bus_name,
+                                const char     *path,
+                                const char     *interface,
+                                const char     *method,
+                                DBusError      *opt_error,
+                                const char     *arg_types,
+                                va_list         args)
+{
+    dbus_bool_t success = FALSE;
+    DBusMessage *msg = NULL, *reply = NULL;
+    DBusMessageIter iter;
+    DBusError *err, real_err;
+    const char *p;
+
+    if (opt_error)
+        err = opt_error;
+    else {
+        dbus_error_init (&real_err);
+        err = &real_err;
+    }
+
+    msg = dbus_message_new_method_call (bus_name, path, interface, method);
+    if (!msg)
+        goto out;
+
+    p = arg_types;
+    dbus_message_iter_init_append (msg, &iter);
+    dbind_any_marshal_va (&iter, &p, args);
+
+    reply = dbind_send_and_allow_reentry (cnx, msg, err);
+    if (!reply)
+        goto out;
+
+    if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      const char *name = dbus_message_get_error_name (reply);
+      dbus_set_error (err, name, g_strdup (""));
+      goto out;
+    }
+    /* demarshal */
+    if (p[0] == '=' && p[1] == '>')
+    {
+        DBusMessageIter iter;
+        p += 2;
+        dbus_message_iter_init (reply, &iter);
+        dbind_any_demarshal_va (&iter, &p, args);
+    }
+
+    success = TRUE;
+out:
+    if (msg)
+        dbus_message_unref (msg);
+
+    if (reply)
+        dbus_message_unref (reply);
+
+    if (err == &real_err)
+        dbus_error_free (err);
+
+    return success;
+}
+
+/**
+ * dbind_method_call_reentrant:
+ *
+ * @cnx:       A D-Bus Connection used to make the method call.
+ * @bus_name:  The D-Bus bus name of the program where the method call should
+ *             be made.
+ * @path:      The D-Bus object path that should handle the method.
+ * @interface: The D-Bus interface used to scope the method name.
+ * @method:    Method to be invoked.
+ * @opt_error: D-Bus error.
+ * @arg_types: Variable length arguments interleaving D-Bus argument types
+ *             and pointers to argument data.
+ *
+ * Makes a D-Bus method call using the supplied location data, method name and
+ * argument data.This function is re-entrant. It continuously reads from the D-Bus
+ * bus and dispatches messages until a reply has been recieved.
+ **/
+dbus_bool_t
+dbind_method_call_reentrant (DBusConnection *cnx,
+                             const char     *bus_name,
+                             const char     *path,
+                             const char     *interface,
+                             const char     *method,
+                             DBusError      *opt_error,
+                             const char     *arg_types,
+                             ...)
+{
+    dbus_bool_t success = FALSE;
+    va_list args;
+
+    va_start (args, arg_types);
+    success = dbind_method_call_reentrant_va (cnx,
+                                              bus_name,
+                                              path,
+                                              interface,
+                                              method,
+                                              opt_error,
+                                              arg_types,
+                                              args);
+    va_end (args);
+
+    return success;
+}
+
+/*---------------------------------------------------------------------------*/
+
+dbus_bool_t
+dbind_emit_signal_va (DBusConnection *cnx,
+                      const char     *path,
+                      const char     *interface,
+                      const char     *signal,
+                      DBusError      *opt_error,
+                      const char     *arg_types,
+                      va_list         args)
+{
+    dbus_bool_t success = FALSE;
+    DBusMessage *msg = NULL;
+    DBusMessageIter iter;
+    DBusError *err, real_err;
+    const char *p;
+
+    if (opt_error)
+        err = opt_error;
+    else {
+        dbus_error_init (&real_err);
+        err = &real_err;
+    }
+
+    msg = dbus_message_new_signal (path, interface, signal);
+    if (!msg)
+        goto out;
+
+    p = arg_types;
+    dbus_message_iter_init_append (msg, &iter);
+    dbind_any_marshal_va (&iter, &p, args);
+
+    if (!dbus_connection_send (cnx, msg, NULL))
+       goto out;
+
+    success = TRUE;
+out:
+
+    if (msg)
+        dbus_message_unref (msg);
+
+    if (err == &real_err)
+        dbus_error_free (err);
+
+    return success;
+}
+
+/**
+ * dbind_emit_signal:
+ *
+ * @cnx:       A D-Bus Connection used to make the method call.
+ * @path:      The D-Bus object path that this signal is emitted from.
+ * @interface: The D-Bus interface used to scope the method name.
+ * @signal:    Name of signal to emit.
+ * @opt_error: D-Bus error.
+ * @arg_types: Variable length arguments interleaving D-Bus argument types
+ *             and pointers to argument data.
+ *
+ * Emits a D-Bus signal  using the supplied signal name and argument data.
+ **/
+dbus_bool_t
+dbind_emit_signal (DBusConnection *cnx,
+                   const char     *path,
+                   const char     *interface,
+                   const char     *signal,
+                   DBusError      *opt_error,
+                   const char     *arg_types,
+                   ...)
+{
+    dbus_bool_t success = FALSE;
+    va_list args;
+
+    va_start (args, arg_types);
+    success = dbind_emit_signal_va (cnx, path, interface, signal, opt_error, arg_types, args);
+    va_end (args);
+
+    return success;
+}
+
+/*END------------------------------------------------------------------------*/
diff --git a/dbind/dbind.h b/dbind/dbind.h
new file mode 100644
index 0000000..3a8b209
--- /dev/null
+++ b/dbind/dbind.h
@@ -0,0 +1,49 @@
+#ifndef _DBIND_H_
+#define _DBIND_H_
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus.h>
+#include <dbind/dbind-any.h>
+
+DBusMessage *
+dbind_send_and_allow_reentry (DBusConnection *bus, DBusMessage *message, DBusError *error);
+
+dbus_bool_t
+dbind_method_call_reentrant_va (DBusConnection *cnx,
+                                const char     *bus_name,
+                                const char     *path,
+                                const char     *interface,
+                                const char     *method,
+                                DBusError      *opt_error,
+                                const char     *arg_types,
+                                va_list         args);
+
+dbus_bool_t
+dbind_method_call_reentrant (DBusConnection *cnx,
+                             const char     *bus_name,
+                             const char     *path,
+                             const char     *interface,
+                             const char     *method,
+                             DBusError      *opt_error,
+                             const char     *arg_types,
+                             ...);
+
+dbus_bool_t
+dbind_emit_signal_va (DBusConnection *cnx,
+                      const char     *path,
+                      const char     *interface,
+                      const char     *signal,
+                      DBusError      *opt_error,
+                      const char     *arg_types,
+                      va_list         args);
+
+dbus_bool_t
+dbind_emit_signal (DBusConnection *cnx,
+                   const char     *path,
+                   const char     *interface,
+                   const char     *signal,
+                   DBusError      *opt_error,
+                   const char     *arg_types,
+                   ...);
+
+#endif /* _DBIND_H_ */
diff --git a/dbind/dbtest.c b/dbind/dbtest.c
new file mode 100644
index 0000000..3ff4ddc
--- /dev/null
+++ b/dbind/dbtest.c
@@ -0,0 +1,404 @@
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <dbind/dbind.h>
+
+/* Wow! dbus is unpleasant to use */
+
+#define DESKICE_PATH      "/Novell/ICEDesktop/Daemon"
+#define DESKICE_NAMESPACE "Novell.ICEDesktop.Daemon"
+
+void marshal (DBusMessage *msg, char *type, void *ptr)
+{
+    DBusMessageIter iter;
+
+    dbus_message_iter_init_append (msg, &iter);
+    dbind_any_marshal (&iter, &type, &ptr);
+}
+
+void demarshal (DBusMessage *msg, char *type, void *ptr)
+{
+    DBusMessageIter iter;
+
+    if (!dbus_message_iter_init (msg, &iter))
+        fprintf (stderr, "no data in msg\n");
+    else
+        dbind_any_demarshal (&iter, &type, &ptr);
+}
+
+#if 0
+dbus_bool_t  dbus_message_marshal   (DBusMessage  *msg,
+                                     char        **marshalled_data_p,
+                                     int          *len_p);
+
+void dump_msg (DBusMessage *msg)
+{
+    char *data = NULL;
+    int   len, i, j;
+
+    dbus_message_marshal (msg, &data, &len);
+    for (i = 0; i < (len+15)/16; i++) {
+        fprintf (stderr, "%4.d | ", i * 16);
+        for (j = 0; j < 16; j++) {
+            unsigned char c = (i*16+j <= len) ? data[i*16+j] : 0;
+            fprintf (stderr, "0x%.2x ", c);
+        }
+        fprintf (stderr, " | ");
+        for (j = 0; j < 16; j++) {
+            char c = (i*16+j <= len) ? data[i*16+j] : '\0';
+            fprintf (stderr, "%c", g_ascii_isprint (c) ? c : '.');
+        }
+    }
+}
+#endif
+
+void test_simple ()
+{
+    dbus_int32_t v1, v2;
+    DBusMessage *msg;
+
+    msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
+    v1 = 42;
+    marshal (msg, "i", &v1);
+    demarshal (msg, "i", &v2);
+    g_assert (v2 == 42);
+    g_assert (v1 == v2);
+
+    dbind_any_free ("i", &v2); /* nop */
+    dbus_message_unref (msg);
+
+    fprintf (stderr, "simple ok\n");
+}
+
+void test_array ()
+{
+    GArray *a1, *a2;
+    DBusMessage *msg;
+
+    /* pod types */
+    a1 = g_array_new (FALSE, FALSE, sizeof (dbus_int32_t));
+    g_array_set_size (a1, 4);
+    g_array_index (a1, dbus_int32_t, 0) = 42;
+    g_array_index (a1, dbus_int32_t, 1) = 17;
+    g_array_index (a1, dbus_int32_t, 2) = 26;
+    g_array_index (a1, dbus_int32_t, 3) = 38;
+
+    msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
+    marshal (msg, "ai", &a1);
+    demarshal (msg, "ai", &a2);
+
+    g_assert (a2 != NULL);
+    g_assert (a2->len == 4);
+    g_assert (g_array_index (a2, dbus_int32_t, 0) == 42);
+    g_assert (g_array_index (a2, dbus_int32_t, 1) == 17);
+    g_assert (g_array_index (a2, dbus_int32_t, 2) == 26);
+    g_assert (g_array_index (a2, dbus_int32_t, 3) == 38);
+    g_array_free (a1, TRUE);
+
+    dbind_any_free ("ai", &a2);
+    dbus_message_unref (msg);
+
+    fprintf (stderr, "array ok\n");
+}
+
+/* this taught me that the struct type is a mis-nomer, 
+   it is generated by brackets */
+void test_struct_native ()
+{
+    DBusMessage *msg;
+    DBusMessageIter iter, arr, str;
+
+    /* manually create ar(ss) */
+    msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
+
+    dbus_message_iter_init_append (msg, &iter);
+
+    dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ss)", &arr);
+    {
+        char *foo;
+        dbus_message_iter_open_container (&arr, DBUS_TYPE_STRUCT, NULL, &str);
+
+        foo = "foo";
+        dbus_message_iter_append_basic (&str, DBUS_TYPE_STRING, &foo);
+        foo = "baa";
+        dbus_message_iter_append_basic (&str, DBUS_TYPE_STRING, &foo);
+        
+        dbus_message_iter_close_container (&arr, &str);
+    }
+    dbus_message_iter_close_container (&iter, &arr);
+
+    fprintf (stderr, "native struct marshalling ok\n");
+    
+    dbus_message_unref (msg);
+}
+
+
+void test_struct_simple ()
+{
+    typedef struct {
+        char *foo;
+        char *baa;
+        char *baz;
+    } FooBaa;
+    GArray *a1 = NULL, *a2 = NULL;
+    DBusMessage *msg;
+
+    a1 = g_array_new (FALSE, FALSE, sizeof (FooBaa));
+    g_array_set_size (a1, 2);
+    g_array_index (a1, FooBaa, 0).foo = "foo";
+    g_array_index (a1, FooBaa, 0).baa = "baa";
+    g_array_index (a1, FooBaa, 0).baz = "baz";
+    g_array_index (a1, FooBaa, 1).foo = "Foo";
+    g_array_index (a1, FooBaa, 1).baa = "baA";
+    g_array_index (a1, FooBaa, 1).baz = "BaZ";
+
+    msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
+    marshal (msg, "a(sss)", &a1);
+    demarshal (msg, "a(sss)", &a2);
+
+    g_assert (a2 != NULL);
+    g_assert (a2 != a1);
+    g_assert (a2->len == 2);
+    g_assert (!strcmp (g_array_index (a2, FooBaa, 0).foo, "foo"));
+    g_assert (!strcmp (g_array_index (a2, FooBaa, 0).baa, "baa"));
+    g_assert (!strcmp (g_array_index (a2, FooBaa, 0).baz, "baz"));
+    g_assert (!strcmp (g_array_index (a2, FooBaa, 1).foo, "Foo"));
+    g_assert (!strcmp (g_array_index (a2, FooBaa, 1).baa, "baA"));
+    g_assert (!strcmp (g_array_index (a2, FooBaa, 1).baz, "BaZ"));
+    
+    fprintf (stderr, "simple struct ok\n");
+
+    dbind_any_free ("a(sss)", &a2);
+    dbus_message_unref (msg);
+}
+
+void test_struct_complex ()
+{
+    typedef struct {
+        dbus_int32_t x, y;
+    } Point;
+    typedef struct {
+        unsigned char pad1;
+        double        val;
+        Point         tl, br;
+        char          pad2;
+        char         *name;
+    } Complex;
+#define TYPEOF_POINT \
+    DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
+        DBUS_TYPE_INT32_AS_STRING \
+        DBUS_TYPE_INT32_AS_STRING \
+    DBUS_STRUCT_END_CHAR_AS_STRING
+#define TYPEOF_COMPLEX \
+    DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
+        DBUS_TYPE_BYTE_AS_STRING \
+        DBUS_TYPE_DOUBLE_AS_STRING \
+        TYPEOF_POINT \
+        TYPEOF_POINT \
+        DBUS_TYPE_BYTE_AS_STRING \
+        DBUS_TYPE_STRING_AS_STRING \
+    DBUS_STRUCT_END_CHAR_AS_STRING
+
+
+    DBusMessage *msg;
+    Complex c1, c2;
+
+    memset (&c1, 0, sizeof (c1));
+    memset (&c2, 0, sizeof (c2));
+
+    c1.pad1 = 2;
+    c1.val = 0.1327569;
+    c1.tl.x = 1;
+    c1.tl.y = 17;
+    c1.br.x = 2587;
+    c1.br.y = -1;
+    c1.pad2 = 1;
+    c1.name = "stroustrup";
+
+    msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
+    marshal (msg, TYPEOF_COMPLEX, &c1);
+    demarshal (msg, TYPEOF_COMPLEX, &c2);
+
+    g_assert (c2.pad1 == 2);
+    g_assert (c2.val == c1.val);
+    g_assert (c2.val != 0);
+    g_assert (c2.tl.x == 1);
+    g_assert (c2.tl.y == 17);
+    g_assert (c2.br.x == 2587);
+    g_assert (c2.br.y == -1);
+    g_assert (c2.pad2 == 1);
+    g_assert (!strcmp (c1.name, "stroustrup"));
+    
+    fprintf (stderr, "complex struct ok\n");
+
+    dbind_any_free (TYPEOF_COMPLEX, &c2);
+    dbus_message_unref (msg);
+}
+
+void test_struct_with_array ()
+{
+    typedef struct {
+        GArray *vals;
+        unsigned char pad1;
+    } ArrayStruct;
+#define TYPEOF_ARRAYSTRUCT \
+        DBUS_TYPE_ARRAY_AS_STRING \
+    DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
+        DBUS_TYPE_ARRAY_AS_STRING \
+        DBUS_TYPE_UINT32_AS_STRING \
+        DBUS_TYPE_BYTE_AS_STRING \
+    DBUS_STRUCT_END_CHAR_AS_STRING
+
+
+    DBusMessage *msg;
+    GArray *a1, *a2;
+    ArrayStruct *p, *q;
+
+
+    a1 = g_array_new (FALSE, FALSE, sizeof (ArrayStruct));
+    g_array_set_size (a1, 2);
+    p = &g_array_index (a1, ArrayStruct, 0);
+    p[0].vals = g_array_new (FALSE, FALSE, sizeof (dbus_uint32_t));
+    g_array_set_size (p[0].vals, 2);
+    g_array_index (p[0].vals, dbus_uint32_t, 0) = 1;
+    g_array_index (p[0].vals, dbus_uint32_t, 1) = 1000;
+    p[0].pad1 = 2;
+    p[1].vals = g_array_new (FALSE, FALSE, sizeof (dbus_uint32_t));
+    g_array_set_size (p[1].vals, 2);
+    g_array_index (p[1].vals, dbus_uint32_t, 0) = 1000000;
+    g_array_index (p[1].vals, dbus_uint32_t, 1) = 1000000000;
+    p[1].pad1 = 8;
+
+    msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
+    marshal (msg, TYPEOF_ARRAYSTRUCT, &a1);
+    demarshal (msg, TYPEOF_ARRAYSTRUCT, &a2);
+
+    q = &g_array_index (a2, ArrayStruct, 0);
+    g_assert (p[0].pad1 == 2);
+    g_assert (g_array_index (p[1].vals, dbus_uint32_t, 1) == 1000000000);
+    
+    fprintf (stderr, "struct with array ok\n");
+
+    dbind_any_free (TYPEOF_ARRAYSTRUCT, &a2);
+    dbus_message_unref (msg);
+    g_array_free (p[0].vals, TRUE);
+    g_array_free (p[1].vals, TRUE);
+}
+
+void test_twovals ()
+{
+    typedef struct {
+        dbus_int32_t v1;
+        dbus_int32_t v2;
+    } TwoVal;
+#define TYPEOF_TWOVAL \
+        DBUS_TYPE_INT32_AS_STRING \
+        DBUS_TYPE_INT32_AS_STRING \
+
+    DBusMessage *msg;
+    DBusMessageIter iter;
+    TwoVal i, o;
+    char *type_twoval = TYPEOF_TWOVAL;
+    char *type;
+    void *ptr;
+
+    msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
+    i.v1 = 42;
+  i.v2 = 1764;
+    dbus_message_iter_init_append (msg, &iter);
+    type = type_twoval;
+    ptr = &i;
+    dbind_any_marshal (&iter, &type, &ptr);
+    dbind_any_marshal (&iter, &type, &ptr);
+    dbus_message_iter_init (msg, &iter);
+    type = type_twoval;
+    ptr = &o;
+    dbind_any_demarshal (&iter, &type, &ptr);
+    dbind_any_demarshal (&iter, &type, &ptr);
+    g_assert (o.v1 == 42);
+    g_assert (o.v2 == 1764);
+    g_assert (i.v1 == o.v1);
+    g_assert (i.v2 == o.v2);
+
+    dbind_any_free ("ii", &o); /* nop */
+    dbus_message_unref (msg);
+
+    fprintf (stderr, "two-val ok\n");
+}
+
+void test_marshalling ()
+{
+    test_simple ();
+    test_array ();
+    test_struct_native ();
+    test_struct_simple ();
+    test_struct_complex ();
+    test_struct_with_array ();
+    test_twovals ();
+
+    fprintf (stderr, "Marshalling ok\n");
+}
+
+void test_teamspaces (DBusConnection *bus)
+{
+    GArray *spaces;
+    DBusError error;
+    int i;
+    typedef struct {
+        char *name;
+        char *id;
+        char *url;
+    } TeamSpace;
+
+    dbus_error_init (&error);
+    if (!dbind_method_call_reentrant (bus,
+                                      NULL,
+                                      DESKICE_PATH,
+                                      DESKICE_NAMESPACE,
+                                      "GetTeamList",
+                                      &error,
+                                      "=>a(sss)",
+                                      &spaces)) {
+        fprintf (stderr, "Error getting team spaces %s: %s\n",
+                 error.name, error.message);
+        dbus_error_free (&error);
+        return;
+    }
+
+    if (!spaces) {
+        fprintf (stderr, "no teamspaces\n");
+        return;
+    }
+    fprintf (stderr, "%d teamspace(s)\n", spaces->len);
+    for (i = 0; i < spaces->len; i++) {
+        TeamSpace *space = &g_array_index (spaces, TeamSpace, i);
+        fprintf (stderr, "\t%d: %s, %s, %s\n", i, space->name, space->id, space->url);
+    }
+
+    dbind_any_free_ptr ("a(sss)", spaces);
+}
+
+void test_helpers ()
+{
+    dbind_find_c_alignment ("(sss)");
+    dbind_find_c_alignment ("a(sss)");
+    dbind_find_c_alignment ("(s(s)yd(d)s)");
+    dbind_find_c_alignment ("a{ss}");
+    fprintf (stderr, "helpers passed\n");
+}
+
+int main (int argc, char **argv)
+{
+    DBusConnection *bus;
+    DBusError err;
+
+    dbus_error_init (&err);
+
+    bus = dbus_bus_get (DBUS_BUS_SESSION, &err);
+
+    test_helpers ();
+    test_marshalling ();
+    test_teamspaces (bus);
+
+    return 0;
+}
diff --git a/xml/Makefile.am b/xml/Makefile.am
index c56e7e0..ad5a8f0 100644
--- a/xml/Makefile.am
+++ b/xml/Makefile.am
@@ -29,8 +29,10 @@ CLEANFILES = \
 	introspection.h \
 	Processed.xml
 
-BUILT_SOURCES = spec.xml
-CLEANFILES = spec.xml
+#BUILT_SOURCES = spec.xml
+#CLEANFILES += spec.xml
+
+XML_SPEC = $(filter %.xml,$(EXTRA_DIST))
 
 spec.xml: $(XML_SPEC)
 	xsltproc --xinclude $(top_srcdir)/tools/identity.xsl Accessibility.xml >spec.xml



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