summaryrefslogtreecommitdiff
path: root/atspi
diff options
context:
space:
mode:
authorjk7744.park <jk7744.park@samsung.com>2015-10-26 15:41:08 +0900
committerjk7744.park <jk7744.park@samsung.com>2015-10-26 15:41:08 +0900
commit728e3f7e6866b63f3c3772de381d4f40d66b7487 (patch)
tree768ee2fb4e95e5119ed03100c63cfe73490dd42e /atspi
parentb178bd1793db6d0385664b6e1930ab417de34cf5 (diff)
downloadat-spi2-core-tizen_2.4.tar.gz
at-spi2-core-tizen_2.4.tar.bz2
at-spi2-core-tizen_2.4.zip
Diffstat (limited to 'atspi')
-rw-r--r--atspi/Makefile.am164
-rw-r--r--atspi/atspi-accessible-private.h46
-rw-r--r--atspi/atspi-accessible.c1802
-rw-r--r--atspi/atspi-accessible.h177
-rw-r--r--atspi/atspi-action.c239
-rw-r--r--atspi/atspi-action.h67
-rw-r--r--atspi/atspi-application.c99
-rw-r--r--atspi/atspi-application.h68
-rw-r--r--atspi/atspi-collection.c296
-rw-r--r--atspi/atspi-collection.h62
-rw-r--r--atspi/atspi-component.c494
-rw-r--r--atspi/atspi-component.h118
-rw-r--r--atspi/atspi-constants.h1382
-rw-r--r--atspi/atspi-device-listener-private.h40
-rw-r--r--atspi/atspi-device-listener.c409
-rw-r--r--atspi/atspi-device-listener.h97
-rw-r--r--atspi/atspi-document.c198
-rw-r--r--atspi/atspi-document.h68
-rw-r--r--atspi/atspi-editabletext.c258
-rw-r--r--atspi/atspi-editabletext.h66
-rw-r--r--atspi/atspi-enum-types.c.template39
-rw-r--r--atspi/atspi-enum-types.h.template27
-rw-r--r--atspi/atspi-event-listener-private.h46
-rw-r--r--atspi/atspi-event-listener.c1079
-rw-r--r--atspi/atspi-event-listener.h140
-rw-r--r--atspi/atspi-gmain.c665
-rw-r--r--atspi/atspi-gmain.h39
-rw-r--r--atspi/atspi-hyperlink.c215
-rw-r--r--atspi/atspi-hyperlink.h77
-rw-r--r--atspi/atspi-hypertext.c124
-rw-r--r--atspi/atspi-hypertext.h57
-rw-r--r--atspi/atspi-image.c177
-rw-r--r--atspi/atspi-image.h61
-rw-r--r--atspi/atspi-matchrule-private.h41
-rw-r--r--atspi/atspi-matchrule.c269
-rw-r--r--atspi/atspi-matchrule.h80
-rw-r--r--atspi/atspi-misc-private.h171
-rw-r--r--atspi/atspi-misc.c1796
-rw-r--r--atspi/atspi-misc.h52
-rw-r--r--atspi/atspi-object.c64
-rw-r--r--atspi/atspi-object.h60
-rw-r--r--atspi/atspi-private.h43
-rw-r--r--atspi/atspi-registry.c545
-rw-r--r--atspi/atspi-registry.h76
-rw-r--r--atspi/atspi-relation.c135
-rw-r--r--atspi/atspi-relation.h67
-rw-r--r--atspi/atspi-selection.c264
-rw-r--r--atspi/atspi-selection.h69
-rw-r--r--atspi/atspi-stateset.c279
-rw-r--r--atspi/atspi-stateset.h75
-rw-r--r--atspi/atspi-table-cell.c306
-rw-r--r--atspi/atspi-table-cell.h74
-rw-r--r--atspi/atspi-table.c745
-rw-r--r--atspi/atspi-table.h105
-rw-r--r--atspi/atspi-text.c913
-rw-r--r--atspi/atspi-text.h142
-rw-r--r--atspi/atspi-types.h158
-rw-r--r--atspi/atspi-value.c177
-rw-r--r--atspi/atspi-value.h61
-rw-r--r--atspi/atspi.h56
60 files changed, 15719 insertions, 0 deletions
diff --git a/atspi/Makefile.am b/atspi/Makefile.am
new file mode 100644
index 0000000..a860fcc
--- /dev/null
+++ b/atspi/Makefile.am
@@ -0,0 +1,164 @@
+lib_LTLIBRARIES = libatspi.la
+
+libatspi_la_LDFLAGS = @LDFLAGS@ @LT_VERSION_INFO@ @LIBTOOL_EXPORT_OPTIONS@ -no-undefined
+
+libatspi_la_CFLAGS = $(DBUS_CFLAGS) \
+ $(DBIND_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ -I$(top_srcdir)/registryd \
+ -I$(top_builddir)/registryd \
+ -I$(top_builddir) \
+ -I$(top_srcdir)
+
+libatspi_la_LIBADD = $(DBUS_LIBS) \
+ $(GOBJ_LIBS) \
+ $(X_LIBS) \
+ $(top_builddir)/dbind/libdbind.la
+
+libatspiincludedir = $(includedir)/at-spi-2.0/atspi
+
+libatspiinclude_HEADERS = \
+ atspi.h \
+ atspi-accessible.h \
+ atspi-action.h \
+ atspi-application.h \
+ atspi-collection.h \
+ atspi-component.h \
+ atspi-constants.h \
+ atspi-device-listener.h \
+ atspi-device-listener-private.h \
+ atspi-document.h \
+ atspi-editabletext.h \
+ atspi-enum-types.h \
+ atspi-event-listener.h \
+ atspi-event-listener-private.h \
+atspi-gmain.c \
+atspi-gmain.h \
+ atspi-hyperlink.h \
+ atspi-hypertext.h \
+ atspi-image.h \
+ atspi-matchrule.h \
+ atspi-misc.h \
+ atspi-object.h \
+ atspi-private.h \
+ atspi-registry.h \
+ atspi-relation.h \
+ atspi-selection.h \
+ atspi-stateset.h \
+ atspi-table.h \
+ atspi-table-cell.h \
+ atspi-text.h \
+ atspi-types.h \
+ atspi-value.h
+
+libatspi_la_SOURCES = \
+ $(BUILT_SOURCES) \
+ $(libatspiinclude_HEADERS) \
+ atspi.h \
+ atspi-accessible.c \
+ atspi-accessible.h \
+ atspi-accessible-private.h \
+ atspi-action.c \
+ atspi-action.h \
+ atspi-application.c \
+ atspi-application.h \
+ atspi-collection.c \
+ atspi-collection.h \
+ atspi-component.c \
+ atspi-component.h \
+ atspi-constants.h \
+ atspi-device-listener.c \
+ atspi-device-listener.h \
+ atspi-device-listener-private.h \
+ atspi-document.c \
+ atspi-document.h \
+ atspi-editabletext.c \
+ atspi-editabletext.h \
+ atspi-event-listener.c \
+ atspi-event-listener.h \
+ atspi-event-listener-private.h \
+ atspi-hyperlink.c \
+ atspi-hyperlink.h \
+ atspi-hypertext.c \
+ atspi-hypertext.h \
+ atspi-image.c \
+ atspi-image.h \
+ atspi-matchrule.c \
+ atspi-matchrule.h \
+ atspi-matchrule-private.h \
+ atspi-misc.c \
+ atspi-misc.h \
+ atspi-misc-private.h \
+ atspi-object.c \
+ atspi-object.h \
+ atspi-private.h \
+ atspi-registry.c \
+ atspi-registry.h \
+ atspi-relation.c \
+ atspi-relation.h \
+ atspi-selection.c \
+ atspi-selection.h \
+ atspi-stateset.c \
+ atspi-stateset.h \
+ atspi-table.c \
+ atspi-table-cell.c \
+ atspi-table.h \
+ atspi-text.c \
+ atspi-text.h \
+ atspi-types.h \
+ atspi-value.c \
+ atspi-value.h
+
+BUILT_SOURCES = \
+ atspi-enum-types.c \
+ atspi-enum-types.h
+
+#CLEANFILES = atspi-constants.h
+
+#atspi-constants.h: $(top_srcdir)/xml/spec.xml $(top_srcdir)/tools/c-constants-gen.py
+# python $(top_srcdir)/tools/c-constants-gen.py Atspi $(top_srcdir)/xml/spec.xml atspi-constants
+
+ENUM_TYPES = \
+ atspi-constants.h \
+ atspi-types.h
+
+atspi-enum-types.h: atspi-enum-types.h.template $(ENUM_TYPES) $(GLIB_MKENUMS)
+ $(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) --template atspi-enum-types.h.template $(ENUM_TYPES)) > $@
+
+atspi-enum-types.c: atspi-enum-types.c.template $(ENUM_TYPES) $(GLIB_MKENUMS)
+ $(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) --template atspi-enum-types.c.template $(ENUM_TYPES)) > $@
+
+-include $(INTROSPECTION_MAKEFILE)
+INTROSPECTION_GIRS =
+INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) --warn-all
+INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
+
+EXTRA_DIST = \
+ atspi-enum-types.c.template \
+ atspi-enum-types.h.template
+
+if HAVE_INTROSPECTION
+Atspi-2.0.gir: libatspi.la
+Atspi_2_0_gir_INCLUDES = GLib-2.0 GObject-2.0
+Atspi_2_0_gir_PACKAGES = dbus-1
+Atspi_2_0_gir_EXPORT_PACKAGES = atspi-2
+Atspi_2_0_gir_CFLAGS = -I$(top_builddir) -I$(top_srcdir)
+Atspi_2_0_gir_LIBS = libatspi.la $(top_builddir)/dbind/libdbind.la
+Atspi_2_0_gir_FILES = $(libatspi_la_SOURCES)
+Atspi_2_0_gir_SCANNERFLAGS = --namespace Atspi --nsversion=2.0
+INTROSPECTION_SCANNER_ARGS += --c-include='atspi/atspi.h'
+INTROSPECTION_GIRS += Atspi-2.0.gir
+
+girdir = $(datadir)/gir-1.0
+gir_DATA = $(INTROSPECTION_GIRS)
+
+typelibdir = $(libdir)/girepository-1.0
+typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
+
+CLEANFILES = \
+ $(gir_DATA) \
+ $(typelib_DATA)
+
+endif
+
+-include $(top_srcdir)/git.mk
diff --git a/atspi/atspi-accessible-private.h b/atspi/atspi-accessible-private.h
new file mode 100644
index 0000000..496f7d7
--- /dev/null
+++ b/atspi/atspi-accessible-private.h
@@ -0,0 +1,46 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_PRIVATE_H_
+#define _ATSPI_ACCESSIBLE_PRIVATE_H_
+
+G_BEGIN_DECLS
+
+#include "atspi-accessible.h"
+
+struct _AtspiAccessiblePrivate
+{
+ GHashTable *cache;
+ guint cache_ref_count;
+};
+
+GHashTable *
+_atspi_accessible_ref_cache (AtspiAccessible *accessible);
+
+void
+_atspi_accessible_unref_cache (AtspiAccessible *accessible);
+G_END_DECLS
+
+#endif /* _ATSPI_ACCESSIBLE_H_ */
diff --git a/atspi/atspi-accessible.c b/atspi/atspi-accessible.c
new file mode 100644
index 0000000..2d77357
--- /dev/null
+++ b/atspi/atspi-accessible.c
@@ -0,0 +1,1802 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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"
+#include "atspi-accessible-private.h"
+#include <string.h>
+
+static gboolean enable_caching = FALSE;
+static guint quark_locale;
+
+static void
+atspi_action_interface_init (AtspiAction *action)
+{
+}
+
+static void
+atspi_collection_interface_init (AtspiCollection *component)
+{
+}
+
+static void
+atspi_component_interface_init (AtspiComponent *component)
+{
+}
+
+static void
+atspi_document_interface_init (AtspiDocument *document)
+{
+}
+
+static void
+atspi_editable_text_interface_init (AtspiEditableText *editable_text)
+{
+}
+
+static void
+atspi_hypertext_interface_init (AtspiHypertext *hypertext)
+{
+}
+
+static void
+atspi_image_interface_init (AtspiImage *image)
+{
+}
+
+static void
+atspi_selection_interface_init (AtspiSelection *selection)
+{
+}
+
+static void
+atspi_table_interface_init (AtspiTable *table)
+{
+}
+
+static void
+atspi_table_cell_interface_init (AtspiTableCell *cell)
+{
+}
+
+static void
+atspi_text_interface_init (AtspiText *text)
+{
+}
+
+static void
+atspi_value_interface_init (AtspiValue *value)
+{
+}
+
+G_DEFINE_TYPE_WITH_CODE (AtspiAccessible, atspi_accessible, ATSPI_TYPE_OBJECT,
+ G_ADD_PRIVATE (AtspiAccessible)
+ G_IMPLEMENT_INTERFACE (ATSPI_TYPE_ACTION, atspi_action_interface_init)
+ G_IMPLEMENT_INTERFACE (ATSPI_TYPE_COLLECTION, atspi_collection_interface_init)
+ G_IMPLEMENT_INTERFACE (ATSPI_TYPE_COMPONENT, atspi_component_interface_init)
+ G_IMPLEMENT_INTERFACE (ATSPI_TYPE_DOCUMENT, atspi_document_interface_init)
+ G_IMPLEMENT_INTERFACE (ATSPI_TYPE_EDITABLE_TEXT, atspi_editable_text_interface_init)
+ G_IMPLEMENT_INTERFACE (ATSPI_TYPE_HYPERTEXT, atspi_hypertext_interface_init)
+ G_IMPLEMENT_INTERFACE (ATSPI_TYPE_IMAGE, atspi_image_interface_init)
+ G_IMPLEMENT_INTERFACE (ATSPI_TYPE_SELECTION, atspi_selection_interface_init)
+ G_IMPLEMENT_INTERFACE (ATSPI_TYPE_TABLE, atspi_table_interface_init)
+ G_IMPLEMENT_INTERFACE (ATSPI_TYPE_TABLE_CELL, atspi_table_cell_interface_init)
+ G_IMPLEMENT_INTERFACE (ATSPI_TYPE_TEXT, atspi_text_interface_init)
+ G_IMPLEMENT_INTERFACE (ATSPI_TYPE_VALUE, atspi_value_interface_init))
+
+#ifdef DEBUG_REF_COUNTS
+static gint accessible_count = 0;
+#endif
+
+static void
+atspi_accessible_init (AtspiAccessible *accessible)
+{
+#ifdef DEBUG_REF_COUNTS
+ accessible_count++;
+ g_hash_table_insert (_atspi_get_live_refs (), accessible, NULL);
+ g_print("at-spi: init: %d objects\n", accessible_count);
+#endif
+
+ accessible->priv = atspi_accessible_get_instance_private (accessible);
+}
+
+static void
+atspi_accessible_dispose (GObject *object)
+{
+ AtspiAccessible *accessible = ATSPI_ACCESSIBLE (object);
+ AtspiEvent e;
+ AtspiAccessible *parent;
+ GList *children;
+ GList *l;
+
+ /* TODO: Only fire if object not already marked defunct */
+ memset (&e, 0, sizeof (e));
+ e.type = "object:state-changed:defunct";
+ e.source = accessible;
+ e.detail1 = 1;
+ e.detail2 = 0;
+ _atspi_send_event (&e);
+
+ if (accessible->states)
+ {
+ g_object_unref (accessible->states);
+ accessible->states = NULL;
+ }
+
+ parent = accessible->accessible_parent;
+ if (parent && parent->children)
+ {
+ GList*ls = g_list_find (parent->children, accessible);
+ if(ls)
+ {
+ gboolean replace = (ls == parent->children);
+ ls = g_list_remove (ls, accessible);
+ if (replace)
+ parent->children = ls;
+ g_object_unref (object);
+ }
+ }
+
+ if (parent)
+ {
+ g_object_unref (parent);
+ accessible->accessible_parent = NULL;
+ }
+
+ children = accessible->children;
+ accessible->children = NULL;
+ for (l = children; l; l = l->next)
+ {
+ AtspiAccessible *child = l->data;
+ if (child && child->accessible_parent == accessible)
+ {
+ g_object_unref (accessible);
+ child->accessible_parent = NULL;
+ }
+ g_object_unref (child);
+ }
+ g_list_free (children);
+
+ G_OBJECT_CLASS (atspi_accessible_parent_class) ->dispose (object);
+}
+
+static void
+atspi_accessible_finalize (GObject *object)
+{
+ AtspiAccessible *accessible = ATSPI_ACCESSIBLE (object);
+
+ g_free (accessible->description);
+ g_free (accessible->name);
+ if (accessible->attributes)
+ g_hash_table_unref (accessible->attributes);
+
+ if (accessible->priv->cache)
+ g_hash_table_destroy (accessible->priv->cache);
+
+#ifdef DEBUG_REF_COUNTS
+ accessible_count--;
+ g_hash_table_remove (_atspi_get_live_refs (), accessible);
+ g_print ("at-spi: finalize: %d objects\n", accessible_count);
+#endif
+
+ G_OBJECT_CLASS (atspi_accessible_parent_class)
+ ->finalize (object);
+}
+
+static void
+atspi_accessible_class_init (AtspiAccessibleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = atspi_accessible_dispose;
+ object_class->finalize = atspi_accessible_finalize;
+
+ quark_locale = g_quark_from_string ("accessible-locale");
+}
+
+/**
+ * atspi_accessible_get_name:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Gets 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, g_strdup (""));
+ if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_NAME))
+ {
+ if (!_atspi_dbus_get_property (obj, atspi_interface_accessible, "Name", error,
+ "s", &obj->name))
+ return g_strdup ("");
+ _atspi_accessible_add_cache (obj, ATSPI_CACHE_NAME);
+ }
+ return g_strdup (obj->name);
+}
+
+/**
+ * atspi_accessible_get_description:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Gets 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, g_strdup (""));
+
+ if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_DESCRIPTION))
+ {
+ if (!_atspi_dbus_get_property (obj, atspi_interface_accessible,
+ "Description", error, "s",
+ &obj->description))
+ return g_strdup ("");
+ _atspi_accessible_add_cache (obj, ATSPI_CACHE_DESCRIPTION);
+ }
+ return g_strdup (obj->description);
+}
+
+const char *str_parent = "Parent";
+
+/**
+ * atspi_accessible_get_parent:
+ * @obj: a pointer to the #AtspiAccessible object to query.
+ *
+ * Gets an #AtspiAccessible object's parent container.
+ *
+ * Returns: (nullable) (transfer full): a pointer to the
+ * #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);
+
+ if (obj->parent.app &&
+ !_atspi_accessible_test_cache (obj, ATSPI_CACHE_PARENT))
+ {
+ DBusMessage *message, *reply;
+ DBusMessageIter iter, iter_variant;
+ message = dbus_message_new_method_call (obj->parent.app->bus_name,
+ obj->parent.path,
+ DBUS_INTERFACE_PROPERTIES, "Get");
+ if (!message)
+ return NULL;
+ dbus_message_append_args (message, DBUS_TYPE_STRING, &atspi_interface_accessible,
+ DBUS_TYPE_STRING, &str_parent,
+ DBUS_TYPE_INVALID);
+ reply = _atspi_dbus_send_with_reply_and_block (message, error);
+ if (!reply)
+ return NULL;
+ if (strcmp (dbus_message_get_signature (reply), "v") != 0)
+ {
+ dbus_message_unref (reply);
+ return NULL;
+ }
+ dbus_message_iter_init (reply, &iter);
+ dbus_message_iter_recurse (&iter, &iter_variant);
+ obj->accessible_parent = _atspi_dbus_return_accessible_from_iter (&iter_variant);
+ dbus_message_unref (reply);
+ _atspi_accessible_add_cache (obj, ATSPI_CACHE_PARENT);
+ }
+ if (!obj->accessible_parent)
+ return NULL;
+ return g_object_ref (obj->accessible_parent);
+}
+
+/**
+ * atspi_accessible_get_child_count:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Gets 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);
+
+ if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_CHILDREN))
+ {
+ dbus_int32_t ret;
+ if (!_atspi_dbus_get_property (obj, atspi_interface_accessible,
+ "ChildCount", error, "i", &ret))
+ return -1;
+ return ret;
+ }
+
+ return g_list_length (obj->children);
+}
+
+/**
+ * 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.
+ *
+ * Gets the #AtspiAccessible child of an #AtspiAccessible object at a given index.
+ *
+ * Returns: (transfer full): 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);
+
+ if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_CHILDREN))
+ {
+ DBusMessage *reply;
+ reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible,
+ "GetChildAtIndex", error, "i",
+ child_index);
+ return _atspi_dbus_return_accessible_from_message (reply);
+ }
+
+ child = g_list_nth_data (obj->children, child_index);
+ if (!child)
+ return NULL;
+ return g_object_ref (child);
+}
+
+/**
+ * atspi_accessible_get_index_in_parent:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Gets the index of an #AtspiAccessible object within its parent's
+ * #AtspiAccessible children list.
+ *
+ * Returns: a #glong indicating the index of the #AtspiAccessible object
+ * in its parent,
+ * 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 = 0;
+
+ g_return_val_if_fail (obj != NULL, -1);
+ if (_atspi_accessible_test_cache (obj, ATSPI_CACHE_PARENT) &&
+ !obj->accessible_parent)
+ return -1;
+ if (!obj->accessible_parent ||
+ !_atspi_accessible_test_cache (obj->accessible_parent,
+ ATSPI_CACHE_CHILDREN))
+ {
+ dbus_int32_t ret = -1;
+ _atspi_dbus_call (obj, atspi_interface_accessible,
+ "GetIndexInParent", NULL, "=>i", &ret);
+ return ret;
+ }
+
+ 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.
+ *
+ * Gets the set of #AtspiRelation objects which describes this #AtspiAccessible object's
+ * relationships with other #AtspiAccessible objects.
+ *
+ * Returns: (element-type AtspiRelation*) (transfer full): a #GArray of
+ * #AtspiRelation pointers or NULL on exception.
+ **/
+GArray *
+atspi_accessible_get_relation_set (AtspiAccessible *obj, GError **error)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter, iter_array;
+ GArray *ret;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetRelationSet", error, "");
+ if (!reply)
+ return NULL;
+ _ATSPI_DBUS_CHECK_SIG (reply, "a(ua(so))", error, NULL);
+
+ ret = g_array_new (TRUE, TRUE, sizeof (AtspiRelation *));
+ dbus_message_iter_init (reply, &iter);
+ dbus_message_iter_recurse (&iter, &iter_array);
+ while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+ {
+ AtspiRelation *relation;
+ relation = _atspi_relation_new_from_iter (&iter_array);
+ ret = g_array_append_val (ret, relation);
+ dbus_message_iter_next (&iter_array);
+ }
+ dbus_message_unref (reply);
+ return ret;
+}
+
+/**
+ * atspi_accessible_get_role:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Gets the UI role played by an #AtspiAccessible object.
+ * This role's name can be obtained via atspi_accessible_get_role_name ().
+ *
+ * Returns: the #AtspiRole of an #AtspiAccessible object.
+ *
+ **/
+AtspiRole
+atspi_accessible_get_role (AtspiAccessible *obj, GError **error)
+{
+ g_return_val_if_fail (obj != NULL, ATSPI_ROLE_INVALID);
+
+ if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_ROLE))
+ {
+ dbus_uint32_t role;
+ /* TODO: Make this a property */
+ if (_atspi_dbus_call (obj, atspi_interface_accessible, "GetRole", error, "=>u", &role))
+ {
+ obj->role = role;
+ _atspi_accessible_add_cache (obj, ATSPI_CACHE_ROLE);
+ }
+ }
+ return obj->role;
+}
+
+/**
+ * atspi_accessible_get_role_name:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Gets a UTF-8 string corresponding to the name of the role played by an object.
+ * This method will return useful values for roles that fall outside the
+ * enumeration used in atspi_accessible_get_role ().
+ *
+ * Returns: a UTF-8 string specifying the type of UI role played by an
+ * #AtspiAccessible object.
+ *
+ **/
+gchar *
+atspi_accessible_get_role_name (AtspiAccessible *obj, GError **error)
+{
+ gchar *retval = NULL;
+ AtspiRole role;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ role = atspi_accessible_get_role (obj, error);
+ if (role >= 0 && role < ATSPI_ROLE_COUNT && role != ATSPI_ROLE_EXTENDED)
+ return atspi_role_get_name (role);
+
+ _atspi_dbus_call (obj, atspi_interface_accessible, "GetRoleName", error, "=>s", &retval);
+
+ if (!retval)
+ retval = g_strdup ("");
+
+ return retval;
+}
+
+/**
+ * atspi_accessible_get_localized_role_name:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Gets a UTF-8 string corresponding to the name of the role played by an
+ * object, translated to the current locale.
+ * This method will return useful values for roles that fall outside the
+ * enumeration used in atspi_accessible_getRole ().
+ *
+ * Returns: a localized, UTF-8 string specifying the type of UI role played
+ * by an #AtspiAccessible object.
+ *
+ **/
+gchar *
+atspi_accessible_get_localized_role_name (AtspiAccessible *obj, GError **error)
+{
+ char *retval = NULL;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ _atspi_dbus_call (obj, atspi_interface_accessible, "GetLocalizedRoleName", error, "=>s", &retval);
+
+ if (!retval)
+ return g_strdup ("");
+
+ return retval;
+}
+
+static AtspiStateSet *
+defunct_set ()
+{
+ AtspiStateSet *set = atspi_state_set_new (NULL);
+ atspi_state_set_add (set, ATSPI_STATE_DEFUNCT);
+ return set;
+}
+
+/**
+ * atspi_accessible_get_state_set:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Gets the states currently held by an object.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiStateSet representing an
+ * object's current state set.
+ **/
+AtspiStateSet *
+atspi_accessible_get_state_set (AtspiAccessible *obj)
+{
+ /* TODO: Should take a GError **, but would be an API break */
+ if (!obj->parent.app || !obj->parent.app->bus)
+ return defunct_set ();
+
+ if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_STATES))
+ {
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible,
+ "GetState", NULL, "");
+ _ATSPI_DBUS_CHECK_SIG (reply, "au", NULL, defunct_set ());
+ dbus_message_iter_init (reply, &iter);
+ _atspi_dbus_set_state (obj, &iter);
+ dbus_message_unref (reply);
+ _atspi_accessible_add_cache (obj, ATSPI_CACHE_STATES);
+ }
+
+ return g_object_ref (obj->states);
+}
+
+/**
+ * atspi_accessible_get_attributes:
+ * @obj: The #AtspiAccessible being queried.
+ *
+ * Gets 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: (element-type gchar* gchar*) (transfer full): The name-value-pair
+ * attributes assigned to this object.
+ */
+GHashTable *
+atspi_accessible_get_attributes (AtspiAccessible *obj, GError **error)
+{
+ DBusMessage *message;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ if (obj->priv->cache)
+ {
+ GValue *val = g_hash_table_lookup (obj->priv->cache, "Attributes");
+ if (val)
+ return g_value_dup_boxed (val);
+ }
+
+ if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_ATTRIBUTES))
+ {
+ message = _atspi_dbus_call_partial (obj, atspi_interface_accessible,
+ "GetAttributes", error, "");
+ obj->attributes = _atspi_dbus_return_hash_from_message (message);
+ _atspi_accessible_add_cache (obj, ATSPI_CACHE_ATTRIBUTES);
+ }
+
+ if (!obj->attributes)
+ return NULL;
+ return g_hash_table_ref (obj->attributes);
+}
+
+static void
+add_to_attribute_array (gpointer key, gpointer value, gpointer data)
+{
+ GArray **array = (GArray **)data;
+ gchar *str = g_strconcat (key, ":", value, NULL);
+ *array = g_array_append_val (*array, str);
+}
+
+/**
+ * atspi_accessible_get_attributes_as_array:
+ * @obj: The #AtspiAccessible being queried.
+ *
+ * Gets a #GArray representing any assigned
+ * name-value pair attributes or annotations for this object.
+ * For typographic, textual, or textually-semantic attributes, see
+ * atspi_text_get_attributes_as_array instead.
+ *
+ * Returns: (element-type gchar*) (transfer full): The name-value-pair
+ * attributes assigned to this object.
+ */
+GArray *
+atspi_accessible_get_attributes_as_array (AtspiAccessible *obj, GError **error)
+{
+ DBusMessage *message;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ if (obj->priv->cache)
+ {
+ GValue *val = g_hash_table_lookup (obj->priv->cache, "Attributes");
+ if (val)
+ {
+ GArray *array = g_array_new (TRUE, TRUE, sizeof (gchar *));
+ GHashTable *attributes = g_value_get_boxed (val);
+ g_hash_table_foreach (attributes, add_to_attribute_array, &array);
+ return array;
+ }
+ }
+
+ message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetAttributes", error, "");
+ return _atspi_dbus_return_attribute_array_from_message (message);
+}
+
+/**
+ * atspi_accessible_get_application:
+ * @obj: The #AtspiAccessible being queried.
+ *
+ * Gets the containing #AtspiApplication for an object.
+ *
+ * Returns: (transfer full): the containing #AtspiApplication instance for
+ * this object.
+ */
+AtspiAccessible *
+atspi_accessible_get_application (AtspiAccessible *obj, GError **error)
+{
+ AtspiAccessible *parent;
+
+ g_object_ref (obj);
+ for (;;)
+ {
+ parent = atspi_accessible_get_parent (obj, NULL);
+ if (!parent && obj->parent.app &&
+ atspi_accessible_get_role (obj, NULL) != ATSPI_ROLE_APPLICATION)
+ {
+ AtspiAccessible *root = g_object_ref (obj->parent.app->root);
+ if (root)
+ {
+ g_object_unref (obj);
+ if (atspi_accessible_get_role (root, NULL) == ATSPI_ROLE_DESKTOP_FRAME)
+ {
+ g_object_unref (root);
+ return NULL;
+ }
+ return root;
+ }
+ }
+ if (!parent || parent == obj ||
+ atspi_accessible_get_role (parent, NULL) == ATSPI_ROLE_DESKTOP_FRAME)
+ {
+ if (parent)
+ g_object_unref (parent);
+ return obj;
+ }
+ g_object_unref (obj);
+ obj = parent;
+ }
+}
+
+/* Application-specific methods */
+
+/**
+ * atspi_accessible_get_toolkit_name:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Gets the toolkit name for an #AtspiAccessible object.
+ * Only works on application root objects.
+ *
+ * Returns: a UTF-8 string indicating the toolkit name for the #AtspiAccessible object or NULL on exception.
+ **/
+gchar *
+atspi_accessible_get_toolkit_name (AtspiAccessible *obj, GError **error)
+{
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ if (!obj->parent.app)
+ return NULL;
+
+ if (!obj->parent.app->toolkit_name)
+ _atspi_dbus_get_property (obj, atspi_interface_application, "ToolkitName",
+ error, "s", &obj->parent.app->toolkit_name);
+
+ return g_strdup (obj->parent.app->toolkit_name);
+}
+
+/**
+ * atspi_accessible_get_toolkit_version:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Gets the toolkit version for an #AtspiAccessible object.
+ * Only works on application root objects.
+ *
+ * Returns: a UTF-8 string indicating the toolkit version for the #AtspiAccessible object or NULL on exception.
+ **/
+gchar *
+atspi_accessible_get_toolkit_version (AtspiAccessible *obj, GError **error)
+{
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ if (!obj->parent.app)
+ return NULL;
+
+ if (!obj->parent.app->toolkit_version)
+ _atspi_dbus_get_property (obj, atspi_interface_application, "Version",
+ error, "s", &obj->parent.app->toolkit_version);
+
+ return g_strdup (obj->parent.app->toolkit_version);
+}
+
+/**
+ * atspi_accessible_get_atspi_version:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Gets the AT-SPI IPC specification version supported by the application
+ * pointed to by the #AtspiAccessible object.
+ * Only works on application root objects.
+ *
+ * Returns: a UTF-8 string indicating the AT-SPI version for the #AtspiAccessible object or NULL on exception.
+ **/
+gchar *
+atspi_accessible_get_atspi_version (AtspiAccessible *obj, GError **error)
+{
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ if (!obj->parent.app)
+ return NULL;
+
+ if (!obj->parent.app->atspi_version)
+ _atspi_dbus_get_property (obj, atspi_interface_application, "AtspiVersion",
+ error, "s", &obj->parent.app->atspi_version);
+
+ return g_strdup (obj->parent.app->atspi_version);
+}
+
+/**
+ * atspi_accessible_get_id:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Gets the application id for a #AtspiAccessible object.
+ * Only works on application root objects.
+ *
+ * Returns: a positive #gint indicating the id for the #AtspiAccessible object
+ * or -1 on exception.
+ **/
+gint
+atspi_accessible_get_id (AtspiAccessible *obj, GError **error)
+{
+ gint ret = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ if (!_atspi_dbus_get_property (obj, atspi_interface_application, "Id", error, "i", &ret))
+ return -1;
+ return ret;
+}
+
+
+/* Interface query methods */
+
+static gboolean
+_atspi_accessible_is_a (AtspiAccessible *accessible,
+ const char *interface_name)
+{
+ int n;
+
+ if (accessible == NULL)
+ {
+ return FALSE;
+ }
+
+ if (!_atspi_accessible_test_cache (accessible, ATSPI_CACHE_INTERFACES))
+ {
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ reply = _atspi_dbus_call_partial (accessible, atspi_interface_accessible,
+ "GetInterfaces", NULL, "");
+ _ATSPI_DBUS_CHECK_SIG (reply, "as", NULL, FALSE);
+ dbus_message_iter_init (reply, &iter);
+ _atspi_dbus_set_interfaces (accessible, &iter);
+ dbus_message_unref (reply);
+ _atspi_accessible_add_cache (accessible, ATSPI_CACHE_INTERFACES);
+ }
+
+ n = _atspi_get_iface_num (interface_name);
+ if (n == -1) return FALSE;
+ return (gboolean) ((accessible->interfaces & (1 << n))? TRUE: FALSE);
+}
+
+/**
+ * atspi_accessible_is_action:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements the
+ * #AtspiAction interface.
+ *
+ * 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 the
+ * #AtspiApplication interface.
+ *
+ * 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 the
+ * #AtspiCollection interface.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiCollection interface,
+ * #FALSE otherwise.
+ **/
+gboolean
+atspi_accessible_is_collection (AtspiAccessible *obj)
+{
+ return _atspi_accessible_is_a (obj,
+ atspi_interface_collection);
+}
+
+/**
+ * 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 the
+ * #AtspiDocument interface.
+ *
+ * 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 the
+ * #AtspiEditableText interface.
+ *
+ * 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 the
+ * #AtspiHypertext interface.
+ *
+ * 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_hyperlink:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements the
+ * #AtspiHyperlink interface.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiHypertext interface,
+ * #FALSE otherwise.
+ **/
+gboolean
+atspi_accessible_is_hyperlink (AtspiAccessible *obj)
+{
+ return _atspi_accessible_is_a (obj,
+ atspi_interface_hyperlink);
+}
+
+/**
+ * atspi_accessible_is_image:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements the
+ * #AtspiImage interface.
+ *
+ * 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 the
+ * #AtspiSelection interface.
+ *
+ * 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 the
+ * #AtspiTable interface.
+ *
+ * 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_table_cell:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements the
+ * #AtspiTableCell interface.
+ *
+ * Returns: #TRUE if @obj implements the #AtspiTable interface,
+ * #FALSE otherwise.
+**/
+gboolean
+atspi_accessible_is_table_cell (AtspiAccessible *obj)
+{
+ return _atspi_accessible_is_a (obj,
+ atspi_interface_table_cell);
+}
+
+/**
+ * atspi_accessible_is_streamable_content:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Query whether the specified #AtspiAccessible implements the
+ * #AtspiStreamableContent interface.
+ *
+ * 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 the
+ * #AtspiText interface.
+ *
+ * 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 the
+ * #AtspiValue interface.
+ *
+ * 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_action: (rename-to atspi_accessible_get_action_iface)
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiAction interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiAction interface
+ * instance, or NULL if @obj does not implement #AtspiAction.
+ *
+ * Deprecated: 2.10: Use atspi_accessible_get_action_iface instead.
+ **/
+AtspiAction *
+atspi_accessible_get_action (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_action) ?
+ g_object_ref (ATSPI_ACTION (accessible)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_action_iface:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiAction interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiAction interface
+ * instance, or NULL if @obj does not implement #AtspiAction.
+ **/
+AtspiAction *
+atspi_accessible_get_action_iface (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_action) ?
+ g_object_ref (ATSPI_ACTION (accessible)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_collection: (rename-to atspi_accessible_get_collection_iface)
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiCollection interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiCollection interface
+ * instance, or NULL if @obj does not implement #AtspiCollection.
+ *
+ * Deprecated: 2.10: Use atspi_accessible_get_collection_iface instead.
+ **/
+AtspiCollection *
+atspi_accessible_get_collection (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_collection) ?
+ g_object_ref (ATSPI_COLLECTION (accessible)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_collection_iface:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiCollection interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiCollection interface
+ * instance, or NULL if @obj does not implement #AtspiCollection.
+ **/
+AtspiCollection *
+atspi_accessible_get_collection_iface (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_collection) ?
+ g_object_ref (ATSPI_COLLECTION (accessible)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_component: (rename-to atspi_accessible_get_component_iface)
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiComponent interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiComponent interface
+ * instance, or NULL if @obj does not implement #AtspiComponent.
+ *
+ * Deprecated: 2.10: Use atspi_accessible_get_component_iface instead.
+ **/
+AtspiComponent *
+atspi_accessible_get_component (AtspiAccessible *obj)
+{
+ return (_atspi_accessible_is_a (obj, atspi_interface_component) ?
+ g_object_ref (ATSPI_COMPONENT (obj)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_component_iface:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiComponent interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiComponent interface
+ * instance, or NULL if @obj does not implement #AtspiComponent.
+ **/
+AtspiComponent *
+atspi_accessible_get_component_iface (AtspiAccessible *obj)
+{
+ return (_atspi_accessible_is_a (obj, atspi_interface_component) ?
+ g_object_ref (ATSPI_COMPONENT (obj)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_document: (rename-to atspi_accessible_get_document_iface)
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiDocument interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiDocument interface
+ * instance, or NULL if @obj does not implement #AtspiDocument.
+ *
+ * Deprecated: 2.10: Use atspi_accessible_get_document_iface instead.
+ **/
+AtspiDocument *
+atspi_accessible_get_document (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_document) ?
+ g_object_ref (ATSPI_DOCUMENT (accessible)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_document_iface:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiDocument interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiDocument interface
+ * instance, or NULL if @obj does not implement #AtspiDocument.
+ **/
+AtspiDocument *
+atspi_accessible_get_document_iface (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_document) ?
+ g_object_ref (ATSPI_DOCUMENT (accessible)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_editable_text: (rename-to atspi_accessible_get_editable_text_iface)
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiEditableText interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiEditableText interface
+ * instance, or NULL if @obj does not implement #AtspiEditableText.
+ *
+ * Deprecated: 2.10: Use atspi_accessible_get_editable_text_iface instead.
+ **/
+AtspiEditableText *
+atspi_accessible_get_editable_text (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_editable_text) ?
+ g_object_ref (ATSPI_EDITABLE_TEXT (accessible)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_editable_text_iface:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiEditableText interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiEditableText interface
+ * instance, or NULL if @obj does not implement #AtspiEditableText.
+ **/
+AtspiEditableText *
+atspi_accessible_get_editable_text_iface (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_editable_text) ?
+ g_object_ref (ATSPI_EDITABLE_TEXT (accessible)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_hyperlink:
+ * @obj: a pointer to the #AtspiAccessible object on which to operate.
+ *
+ * Gets the #AtspiHyperlink interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): the #AtspiHyperlink object associated with
+ * the given #AtspiAccessible, or NULL if not supported.
+ **/
+AtspiHyperlink *
+atspi_accessible_get_hyperlink (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_hyperlink) ?
+ _atspi_hyperlink_new (accessible->parent.app, accessible->parent.path) : NULL);
+}
+
+/**
+ * atspi_accessible_get_hypertext: (rename-to atspi_accessible_get_hypertext_iface)
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiHypertext interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiHypertext interface
+ * instance, or NULL if @obj does not implement #AtspiHypertext.
+ *
+ * Deprecated: 2.10: Use atspi_accessible_get_hypertext_iface instead.
+ **/
+AtspiHypertext *
+atspi_accessible_get_hypertext (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_hypertext) ?
+ g_object_ref (ATSPI_HYPERTEXT (accessible)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_hypertext_iface:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiHypertext interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiHypertext interface
+ * instance, or NULL if @obj does not implement #AtspiHypertext.
+ **/
+AtspiHypertext *
+atspi_accessible_get_hypertext_iface (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_hypertext) ?
+ g_object_ref (ATSPI_HYPERTEXT (accessible)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_image: (rename-to atspi_accessible_get_image_iface)
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiImage interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiImage interface instance, or
+ * NULL if @obj does not implement #AtspiImage.
+ *
+ * Deprecated: 2.10: Use atspi_accessible_get_image_iface instead.
+ **/
+AtspiImage *
+atspi_accessible_get_image (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_image) ?
+ g_object_ref (ATSPI_IMAGE (accessible)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_image_iface:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiImage interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiImage interface instance, or
+ * NULL if @obj does not implement #AtspiImage.
+ **/
+AtspiImage *
+atspi_accessible_get_image_iface (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_image) ?
+ g_object_ref (ATSPI_IMAGE (accessible)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_selection: (rename-to atspi_accessible_get_selection_iface)
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiSelection interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiSelection interface
+ * instance, or NULL if @obj does not implement #AtspiSelection.
+ *
+ * Deprecated: 2.10: Use atspi_accessible_get_selection_iface instead.
+ **/
+AtspiSelection *
+atspi_accessible_get_selection (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_selection) ?
+ g_object_ref (ATSPI_SELECTION (accessible)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_selection_iface:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiSelection interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiSelection interface
+ * instance, or NULL if @obj does not implement #AtspiSelection.
+ **/
+AtspiSelection *
+atspi_accessible_get_selection_iface (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_selection) ?
+ g_object_ref (ATSPI_SELECTION (accessible)) : NULL);
+}
+
+#if 0
+/**
+ * atspi_accessible_get_streamable_content:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiStreamableContent interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiStreamableContent interface
+ * instance, or NULL if @obj does not implement #AtspiStreamableContent.
+ **/
+AtspiStreamableContent *
+atspi_accessible_get_streamable_content (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_streamable_content) ?
+ accessible : NULL);
+}
+#endif
+
+/**
+ * atspi_accessible_get_table: (rename-to atspi_accessible_get_table_iface)
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiTable interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiTable interface instance, or
+ * NULL if @obj does not implement #AtspiTable.
+ *
+ * Deprecated: 2.10: Use atspi_accessible_get_table_iface instead.
+ **/
+AtspiTable *
+atspi_accessible_get_table (AtspiAccessible *obj)
+{
+ return (_atspi_accessible_is_a (obj, atspi_interface_table) ?
+ g_object_ref (ATSPI_TABLE (obj)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_table_iface:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiTable interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiTable interface instance, or
+ * NULL if @obj does not implement #AtspiTable.
+ **/
+AtspiTable *
+atspi_accessible_get_table_iface (AtspiAccessible *obj)
+{
+ return (_atspi_accessible_is_a (obj, atspi_interface_table) ?
+ g_object_ref (ATSPI_TABLE (obj)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_table_cell:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiTableCell interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiTableCell interface instance,
+ * or NULL if @obj does not implement #AtspiTable.
+ **/
+AtspiTableCell *
+atspi_accessible_get_table_cell (AtspiAccessible *obj)
+{
+ return (_atspi_accessible_is_a (obj, atspi_interface_table_cell) ?
+ g_object_ref (ATSPI_TABLE_CELL (obj)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_text: (rename-to atspi_accessible_get_text_iface)
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiTable interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiText interface instance, or
+ * NULL if @obj does not implement #AtspiText.
+ *
+ * Deprecated: 2.10: Use atspi_accessible_get_text_iface instead.
+ **/
+AtspiText *
+atspi_accessible_get_text (AtspiAccessible *obj)
+{
+ return (_atspi_accessible_is_a (obj, atspi_interface_text) ?
+ g_object_ref (ATSPI_TEXT (obj)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_text_iface:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiTable interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiText interface instance, or
+ * NULL if @obj does not implement #AtspiText.
+ **/
+AtspiText *
+atspi_accessible_get_text_iface (AtspiAccessible *obj)
+{
+ return (_atspi_accessible_is_a (obj, atspi_interface_text) ?
+ g_object_ref (ATSPI_TEXT (obj)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_value: (rename-to atspi_accessible_get_value_iface)
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiTable interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiValue interface instance, or
+ * NULL if @obj does not implement #AtspiValue.
+ *
+ * Deprecated: 2.10: Use atspi_accessible_get_value_iface instead.
+ **/
+AtspiValue *
+atspi_accessible_get_value (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_value) ?
+ g_object_ref (ATSPI_VALUE (accessible)) : NULL);
+}
+
+/**
+ * atspi_accessible_get_value_iface:
+ * @obj: a pointer to the #AtspiAccessible instance to query.
+ *
+ * Gets the #AtspiTable interface for an #AtspiAccessible.
+ *
+ * Returns: (transfer full): a pointer to an #AtspiValue interface instance, or
+ * NULL if @obj does not implement #AtspiValue.
+ **/
+AtspiValue *
+atspi_accessible_get_value_iface (AtspiAccessible *accessible)
+{
+ return (_atspi_accessible_is_a (accessible, atspi_interface_value) ?
+ g_object_ref (ATSPI_VALUE (accessible)) : NULL);
+}
+
+static void
+append_const_val (GArray *array, const gchar *val)
+{
+ gchar *dup = g_strdup (val);
+
+ if (dup)
+ g_array_append_val (array, dup);
+}
+
+/**
+ * atspi_accessible_get_interfaces:
+ * @obj: The #AtspiAccessible to query.
+ *
+ * A set of pointers to all interfaces supported by an #AtspiAccessible.
+ *
+ * Returns: (element-type gchar*) (transfer full): A #GArray of strings
+ * describing the interfaces supported by the object. Interfaces are
+ * denoted in short-hand (i.e. "Component", "Text" etc.).
+ **/
+GArray *
+atspi_accessible_get_interfaces (AtspiAccessible *obj)
+{
+ GArray *ret = g_array_new (TRUE, TRUE, sizeof (gchar *));
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ append_const_val (ret, "Accessible");
+ if (atspi_accessible_is_action (obj))
+ append_const_val (ret, "Action");
+ if (atspi_accessible_is_collection (obj))
+ append_const_val (ret, "Collection");
+ if (atspi_accessible_is_component (obj))
+ append_const_val (ret, "Component");
+ if (atspi_accessible_is_document (obj))
+ append_const_val (ret, "Document");
+ if (atspi_accessible_is_editable_text (obj))
+ append_const_val (ret, "EditableText");
+ if (atspi_accessible_is_hypertext (obj))
+ append_const_val (ret, "Hypertext");
+ if (atspi_accessible_is_hyperlink (obj))
+ append_const_val (ret, "Hyperlink");
+ if (atspi_accessible_is_image (obj))
+ append_const_val (ret, "Image");
+ if (atspi_accessible_is_selection (obj))
+ append_const_val (ret, "Selection");
+ if (atspi_accessible_is_table (obj))
+ append_const_val (ret, "Table");
+ if (atspi_accessible_is_table_cell (obj))
+ append_const_val (ret, "TableCell");
+ if (atspi_accessible_is_text (obj))
+ append_const_val (ret, "Text");
+ if (atspi_accessible_is_value (obj))
+ append_const_val (ret, "Value");
+
+ return ret;
+}
+
+AtspiAccessible *
+_atspi_accessible_new (AtspiApplication *app, const gchar *path)
+{
+ AtspiAccessible *accessible;
+
+ accessible = g_object_new (ATSPI_TYPE_ACCESSIBLE, NULL);
+ g_return_val_if_fail (accessible != NULL, NULL);
+
+ accessible->parent.app = g_object_ref (app);
+ accessible->parent.path = g_strdup (path);
+
+ return accessible;
+}
+
+/**
+ * atspi_accessible_set_cache_mask:
+ * @accessible: The #AtspiAccessible to operate on. Must be the desktop or
+ * the root of an application.
+ * @mask: An #AtspiCache specifying a bit mask of the types of data to cache.
+ *
+ * Sets the type of data to cache for accessibles.
+ * If this is not set for an application or is reset to ATSPI_CACHE_UNDEFINED,
+ * then the desktop's cache flag will be used.
+ * If the desktop's cache flag is also undefined, then all possible data will
+ * be cached.
+ * This function is intended to work around bugs in toolkits where the proper
+ * events are not raised / to aid in testing for such bugs.
+ **/
+void
+atspi_accessible_set_cache_mask (AtspiAccessible *accessible, AtspiCache mask)
+{
+ g_return_if_fail (accessible != NULL);
+ g_return_if_fail (accessible->parent.app != NULL);
+ g_return_if_fail (accessible == accessible->parent.app->root);
+ accessible->parent.app->cache = mask;
+ enable_caching = TRUE;
+}
+
+/**
+ * atspi_accessible_clear_cache:
+ * @accessible: The #AtspiAccessible whose cache to clear.
+ *
+ * Clears the cached information for the given accessible and all of its
+ * descendants.
+ */
+void
+atspi_accessible_clear_cache (AtspiAccessible *accessible)
+{
+ GList *l;
+
+ if (accessible)
+ {
+ accessible->cached_properties = ATSPI_CACHE_NONE;
+ for (l = accessible->children; l; l = l->next)
+ atspi_accessible_clear_cache (l->data);
+ }
+}
+
+/**
+ * atspi_accessible_get_process_id:
+ * @accessible: The #AtspiAccessible to query.
+ * @error: a pointer to a %NULL #GError pointer
+ *
+ * Returns the process id associated with the given accessible. Mainly
+ * added for debugging; it is a shortcut to explicitly querying the
+ * accessible's app->bus_name and then calling GetConnectionUnixProcessID.
+ *
+ * Returns: The process ID or undetermined value if @error is set.
+ **/
+guint
+atspi_accessible_get_process_id (AtspiAccessible *accessible, GError **error)
+{
+ DBusMessage *message, *reply;
+ DBusConnection *bus = _atspi_bus ();
+ dbus_uint32_t pid = -1;
+ DBusError d_error;
+
+ if (!accessible->parent.app || !accessible->parent.app->bus_name)
+ {
+ g_set_error_literal(error, ATSPI_ERROR, ATSPI_ERROR_IPC, "Process is defunct");
+ return -1;
+ }
+
+ message = dbus_message_new_method_call ("org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "GetConnectionUnixProcessID");
+ dbus_message_append_args (message, DBUS_TYPE_STRING,
+ &accessible->parent.app->bus_name,
+ DBUS_TYPE_INVALID);
+ dbus_error_init (&d_error);
+ reply = dbus_connection_send_with_reply_and_block (bus, message, -1, &d_error);
+ dbus_message_unref (message);
+ if (reply)
+ {
+ if (!strcmp (dbus_message_get_signature (reply), "u"))
+ dbus_message_get_args (reply, NULL, DBUS_TYPE_UINT32, &pid, DBUS_TYPE_INVALID);
+ dbus_message_unref (reply);
+ }
+ if (dbus_error_is_set (&d_error))
+ {
+ g_set_error_literal(error, ATSPI_ERROR, ATSPI_ERROR_IPC, "Process is defunct");
+ dbus_error_free (&d_error);
+ }
+ return pid;
+}
+
+AtspiCache
+_atspi_accessible_get_cache_mask (AtspiAccessible *accessible)
+{
+ AtspiCache mask;
+
+ if (!accessible->parent.app)
+ return ATSPI_CACHE_NONE;
+
+ mask = accessible->parent.app->cache;
+ if (mask == ATSPI_CACHE_UNDEFINED &&
+ accessible->parent.app->root &&
+ accessible->parent.app->root->accessible_parent)
+ {
+ AtspiAccessible *desktop = atspi_get_desktop (0);
+ mask = desktop->parent.app->cache;
+ g_object_unref (desktop);
+ }
+
+ if (mask == ATSPI_CACHE_UNDEFINED)
+ mask = ATSPI_CACHE_DEFAULT;
+
+ return mask;
+}
+
+gboolean
+_atspi_accessible_test_cache (AtspiAccessible *accessible, AtspiCache flag)
+{
+ AtspiCache mask = _atspi_accessible_get_cache_mask (accessible);
+ AtspiCache result = accessible->cached_properties & mask & flag;
+ if (accessible->states && atspi_state_set_contains (accessible->states, ATSPI_STATE_TRANSIENT))
+ return FALSE;
+ return (result != 0 && (atspi_main_loop || enable_caching ||
+ flag == ATSPI_CACHE_INTERFACES) &&
+ !atspi_no_cache);
+}
+
+void
+_atspi_accessible_add_cache (AtspiAccessible *accessible, AtspiCache flag)
+{
+ AtspiCache mask = _atspi_accessible_get_cache_mask (accessible);
+
+ accessible->cached_properties |= flag & mask;
+}
+
+/**
+ * atspi_accessible_get_locale:
+ * @accessible: an #AtspiAccessible
+ *
+ * Gets a UTF-8 string indicating the POSIX-style LC_MESSAGES locale
+ * of @accessible.
+ *
+ * Since: 2.7.91
+ *
+ * Returns: a UTF-8 string indicating the POSIX-style LC_MESSAGES
+ * locale of @accessible.
+ **/
+const gchar*
+atspi_accessible_get_object_locale (AtspiAccessible *accessible, GError **error)
+{
+ gchar *locale;
+
+ g_return_val_if_fail (accessible != NULL, NULL);
+
+ locale = g_object_get_qdata (G_OBJECT (accessible), quark_locale);
+ if (!locale)
+ {
+ if (!_atspi_dbus_get_property (accessible, atspi_interface_accessible,
+ "Locale", error, "s", &locale))
+ return NULL;
+ if (locale)
+ g_object_set_qdata_full (G_OBJECT (accessible), quark_locale, locale,
+ g_free);
+ }
+ return locale;
+}
+
+void
+free_value (gpointer data)
+{
+ GValue *value = data;
+
+ g_value_unset (value);
+ g_free (value);
+}
+
+GHashTable *
+_atspi_accessible_ref_cache (AtspiAccessible *accessible)
+{
+ AtspiAccessiblePrivate *priv = accessible->priv;
+
+ priv->cache_ref_count++;
+ if (priv->cache)
+ return g_hash_table_ref (priv->cache);
+ priv->cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+ free_value);
+ return priv->cache;
+}
+
+void
+_atspi_accessible_unref_cache (AtspiAccessible *accessible)
+{
+ AtspiAccessiblePrivate *priv = accessible->priv;
+
+ if (priv->cache)
+ {
+ g_hash_table_unref (priv->cache);
+ if (--priv->cache_ref_count == 0)
+ priv->cache = NULL;
+ }
+}
diff --git a/atspi/atspi-accessible.h b/atspi/atspi-accessible.h
new file mode 100644
index 0000000..2c3f8cc
--- /dev/null
+++ b/atspi/atspi-accessible.h
@@ -0,0 +1,177 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_
+
+G_BEGIN_DECLS
+
+#include "glib-object.h"
+
+#include "atspi-application.h"
+#include "atspi-constants.h"
+#include "atspi-object.h"
+#include "atspi-stateset.h"
+#include "atspi-types.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 _AtspiAccessiblePrivate AtspiAccessiblePrivate;
+
+struct _AtspiAccessible
+{
+ AtspiObject parent;
+ AtspiAccessible *accessible_parent;
+ GList *children;
+ AtspiRole role;
+ gint interfaces;
+ char *name;
+ char *description;
+ AtspiStateSet *states;
+ GHashTable *attributes;
+ guint cached_properties;
+ AtspiAccessiblePrivate *priv;
+};
+
+typedef struct _AtspiAccessibleClass AtspiAccessibleClass;
+struct _AtspiAccessibleClass
+{
+ AtspiObjectClass parent_class;
+};
+
+GType atspi_accessible_get_type (void);
+
+AtspiAccessible *
+_atspi_accessible_new (AtspiApplication *app, const gchar *path);
+
+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);
+
+GArray * atspi_accessible_get_attributes_as_array (AtspiAccessible *obj, GError **error);
+
+gchar * atspi_accessible_get_toolkit_name (AtspiAccessible *obj, GError **error);
+
+gchar * atspi_accessible_get_toolkit_version (AtspiAccessible *obj, GError **error);
+
+gchar * atspi_accessible_get_atspi_version (AtspiAccessible *obj, GError **error);
+
+gint atspi_accessible_get_id (AtspiAccessible *obj, GError **error);
+
+AtspiAccessible * atspi_accessible_get_application (AtspiAccessible *obj, GError **error);
+
+#ifndef ATSPI_DISABLE_DEPRECATED
+AtspiAction * atspi_accessible_get_action (AtspiAccessible *obj);
+
+AtspiCollection * atspi_accessible_get_collection (AtspiAccessible *obj);
+
+AtspiComponent * atspi_accessible_get_component (AtspiAccessible *obj);
+
+AtspiDocument * atspi_accessible_get_document (AtspiAccessible *obj);
+
+AtspiEditableText * atspi_accessible_get_editable_text (AtspiAccessible *obj);
+
+AtspiHyperlink * atspi_accessible_get_hyperlink (AtspiAccessible *obj);
+
+AtspiHypertext * atspi_accessible_get_hypertext (AtspiAccessible *obj);
+
+AtspiImage * atspi_accessible_get_image (AtspiAccessible *obj);
+
+AtspiSelection * atspi_accessible_get_selection (AtspiAccessible *obj);
+
+AtspiTable * atspi_accessible_get_table (AtspiAccessible *obj);
+
+AtspiTableCell * atspi_accessible_get_table_cell (AtspiAccessible *obj);
+
+AtspiText * atspi_accessible_get_text (AtspiAccessible *obj);
+
+AtspiValue * atspi_accessible_get_value (AtspiAccessible *obj);
+#endif
+
+AtspiAction * atspi_accessible_get_action_iface (AtspiAccessible *obj);
+
+AtspiCollection * atspi_accessible_get_collection_iface (AtspiAccessible *obj);
+
+AtspiComponent * atspi_accessible_get_component_iface (AtspiAccessible *obj);
+
+AtspiDocument * atspi_accessible_get_document_iface (AtspiAccessible *obj);
+
+AtspiEditableText * atspi_accessible_get_editable_text_iface (AtspiAccessible *obj);
+
+AtspiHypertext * atspi_accessible_get_hypertext_iface (AtspiAccessible *obj);
+
+AtspiImage * atspi_accessible_get_image_iface (AtspiAccessible *obj);
+
+AtspiSelection * atspi_accessible_get_selection_iface (AtspiAccessible *obj);
+
+AtspiTable * atspi_accessible_get_table_iface (AtspiAccessible *obj);
+
+AtspiText * atspi_accessible_get_text_iface (AtspiAccessible *obj);
+
+AtspiValue * atspi_accessible_get_value_iface (AtspiAccessible *obj);
+
+GArray * atspi_accessible_get_interfaces (AtspiAccessible *obj);
+
+const gchar* atspi_accessible_get_object_locale (AtspiAccessible *accessible, GError **error);
+
+void atspi_accessible_set_cache_mask (AtspiAccessible *accessible, AtspiCache mask);
+
+void atspi_accessible_clear_cache (AtspiAccessible *accessible);
+
+guint atspi_accessible_get_process_id (AtspiAccessible *accessible, GError **error);
+
+/* private */
+void _atspi_accessible_add_cache (AtspiAccessible *accessible, AtspiCache flag);
+AtspiCache _atspi_accessible_get_cache_mask (AtspiAccessible *accessible);
+gboolean _atspi_accessible_test_cache (AtspiAccessible *accessible, AtspiCache flag);
+
+G_END_DECLS
+
+#endif /* _ATSPI_ACCESSIBLE_H_ */
diff --git a/atspi/atspi-action.c b/atspi/atspi-action.c
new file mode 100644
index 0000000..731773a
--- /dev/null
+++ b/atspi/atspi-action.c
@@ -0,0 +1,239 @@
+/*
+ * 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"
+
+/**
+ * atspi_action_get_n_actions:
+ * @obj: a pointer to the #AtspiAction to query.
+ *
+ * Get the number of actions invokable on an #AtspiAction implementor.
+ *
+ * Returns: an integer indicating the number of invocable actions.
+ **/
+gint
+atspi_action_get_n_actions (AtspiAction *obj, GError **error)
+{
+ dbus_int32_t retval = 0;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_get_property (obj, atspi_interface_action, "NActions", error, "i", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_action_get_description: (rename-to atspi_action_get_action_description)
+ * @obj: a pointer to the #AtspiAction implementor to query.
+ * @i: an integer indicating which action to query.
+ *
+ * Get the description of '@i-th' action invocable on an
+ * object implementing #AtspiAction.
+ *
+ * Returns: a UTF-8 string describing the '@i-th' invocable action.
+ *
+ * Deprecated: 2.10: Use atspi_action_get_action_description instead.
+ **/
+gchar *
+atspi_action_get_description (AtspiAction *obj, int i, GError **error)
+{
+ return atspi_action_get_action_description (obj, i, error);
+}
+
+/**
+ * atspi_action_get_action_description:
+ * @obj: a pointer to the #AtspiAction implementor to query.
+ * @i: an integer indicating which action to query.
+ *
+ * Get the description of '@i-th' action invocable on an
+ * object implementing #AtspiAction.
+ *
+ * Returns: a UTF-8 string describing the '@i-th' invocable action.
+ **/
+gchar *
+atspi_action_get_action_description (AtspiAction *obj, int i, GError **error)
+{
+ dbus_int32_t d_i = i;
+ char *retval = NULL;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ _atspi_dbus_call (obj, atspi_interface_action, "GetDescription", error, "i=>s", d_i, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_action_get_key_binding:
+ * @obj: a pointer to the #AtspiAction implementor to query.
+ * @i: an integer indicating which action to query.
+ *
+ * Get the keybindings for the @i-th action invocable on an
+ * object implementing #AtspiAction, if any are defined.
+ * The keybindings string format is as follows:
+ * there are multiple parts to a keybinding string (typically 3).
+ * They are delimited with ";". The first is the action's
+ * keybinding which is usable if the object implementing the action
+ * is currently posted to the screen, e.g. if a menu is posted
+ * then these keybindings for the corresponding menu-items are
+ * available. The second keybinding substring is the full key sequence
+ * necessary to post the action's widget and activate it, e.g. for
+ * a menu item such as "File->Open" it would both post the menu and
+ * activate the item. Thus the second keybinding string is available
+ * during the lifetime of the containing toplevel window as a whole,
+ * whereas the first keybinding string only works while the object
+ * implementing AtkAction is posted. The third (and optional)
+ * keybinding string is the "keyboard shortcut" which invokes the
+ * action without posting any menus.
+ * Meta-keys are indicated by the conventional strings
+ * "&lt;Control&gt;", "&lt;Alt&gt;", "&lt;Shift&gt;", "&lt;Mod2&gt;",
+ * etc. (we use the same string as gtk_accelerator_name() in
+ * gtk+-2.X.
+ *
+ * Returns: a UTF-8 string which can be parsed to determine the @i-th
+ * invocable action's keybindings.
+ **/
+gchar *
+atspi_action_get_key_binding (AtspiAction *obj, gint i, GError **error)
+{
+ dbus_int32_t d_i = i;
+ char *retval = NULL;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ _atspi_dbus_call (obj, atspi_interface_action, "GetKeyBinding", error, "i=>s", d_i, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_action_get_name: (rename-to atspi_action_get_action_name)
+ * @obj: a pointer to the #AtspiAction implementor to query.
+ * @i: an integer indicating which action to query.
+ *
+ * Get the name of the '@i-th' action invocable on an
+ * object implementing #AtspiAction.
+ *
+ * Returns: the non-localized name of the action, as a UTF-8 string.
+ *
+ * Deprecated: 2.10: Use atspi_action_get_action_name instead.
+ **/
+gchar *
+atspi_action_get_name (AtspiAction *obj, gint i, GError **error)
+{
+ return atspi_action_get_action_name (obj, i, error);
+}
+
+/**
+ * atspi_action_get_action_name:
+ * @obj: a pointer to the #AtspiAction implementor to query.
+ * @i: an integer indicating which action to query.
+ *
+ * Get the name of the '@i-th' action invocable on an
+ * object implementing #AtspiAction.
+ *
+ * Returns: the non-localized name of the action, as a UTF-8 string.
+ **/
+gchar *
+atspi_action_get_action_name (AtspiAction *obj, gint i, GError **error)
+{
+ dbus_int32_t d_i = i;
+ char *retval = NULL;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ _atspi_dbus_call (obj, atspi_interface_action, "GetName", error, "i=>s", d_i, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_action_get_localized_name:
+ * @obj: a pointer to the #AtspiAction implementor to query.
+ * @i: an integer indicating which action to query.
+ *
+ * Get the name of the '@i-th' action invocable on an
+ * object implementing #AtspiAction.
+ *
+ * Returns: the name of the action, as a UTF-8 string.
+ **/
+gchar *
+atspi_action_get_localized_name (AtspiAction *obj, gint i, GError **error)
+{
+ dbus_int32_t d_i = i;
+ char *retval = NULL;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ _atspi_dbus_call (obj, atspi_interface_action, "GetLocalizedName", error,
+ "i=>s", d_i, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_action_do_action:
+ * @obj: a pointer to the #AtspiAction to query.
+ * @i: an integer specifying which action to invoke.
+ *
+ * Invoke the action indicated by #index.
+ *
+ * Returns: #TRUE if the action is successfully invoked, otherwise #FALSE.
+ **/
+gboolean
+atspi_action_do_action (AtspiAction *obj, gint i, GError **error)
+{
+ dbus_int32_t d_i = i;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_action, "DoAction", error, "i=>b", d_i, &retval);
+
+ return retval;
+}
+
+static void
+atspi_action_base_init (AtspiAction *klass)
+{
+}
+
+GType
+atspi_action_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (AtspiAction),
+ (GBaseInitFunc) atspi_action_base_init,
+ (GBaseFinalizeFunc) NULL,
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE, "AtspiAction", &tinfo, 0);
+
+ }
+ return type;
+}
diff --git a/atspi/atspi-action.h b/atspi/atspi-action.h
new file mode 100644
index 0000000..99de8af
--- /dev/null
+++ b/atspi/atspi-action.h
@@ -0,0 +1,67 @@
+/*
+ * 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_ACTION_H_
+#define _ATSPI_ACTION_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+#define ATSPI_TYPE_ACTION (atspi_action_get_type ())
+#define ATSPI_IS_ACTION(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_ACTION)
+#define ATSPI_ACTION(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_ACTION, AtspiAction)
+#define ATSPI_ACTION_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_ACTION, AtspiAction))
+
+GType atspi_action_get_type ();
+
+struct _AtspiAction
+{
+ GTypeInterface parent;
+};
+
+gchar * atspi_action_get_action_description (AtspiAction *obj, int i, GError **error);
+
+gchar * atspi_action_get_action_name (AtspiAction *obj, gint i, GError **error);
+
+gint atspi_action_get_n_actions (AtspiAction *obj, GError **error);
+
+gchar * atspi_action_get_key_binding (AtspiAction *obj, gint i, GError **error);
+
+
+gchar * atspi_action_get_localized_name (AtspiAction *obj, gint i, GError **error);
+
+gboolean atspi_action_do_action (AtspiAction *obj, gint i, GError **error);
+
+#ifndef ATSPI_DISABLE_DEPRECATED
+gchar * atspi_action_get_description (AtspiAction *obj, gint i, GError **error);
+gchar * atspi_action_get_name (AtspiAction *obj, gint i, GError **error);
+#endif
+G_END_DECLS
+
+#endif /* _ATSPI_ACTION_H_ */
diff --git a/atspi/atspi-application.c b/atspi/atspi-application.c
new file mode 100644
index 0000000..65cabdc
--- /dev/null
+++ b/atspi/atspi-application.c
@@ -0,0 +1,99 @@
+/*
+ * 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 (AtspiApplication, atspi_application, G_TYPE_OBJECT)
+
+static void
+atspi_application_init (AtspiApplication *application)
+{
+}
+
+static void
+dispose_accessible (gpointer key, gpointer obj_data, gpointer data)
+{
+ g_object_run_dispose (obj_data);
+}
+
+static void
+atspi_application_dispose (GObject *object)
+{
+ AtspiApplication *application = ATSPI_APPLICATION (object);
+
+ if (application->bus)
+ {
+ if (application->bus != _atspi_bus ())
+ dbus_connection_close (application->bus);
+ dbus_connection_unref (application->bus);
+ application->bus = NULL;
+ }
+
+ if (application->hash)
+ {
+ g_hash_table_foreach (application->hash, dispose_accessible, NULL);
+ g_hash_table_unref (application->hash);
+ application->hash = NULL;
+ }
+
+ if (application->root)
+ {
+ g_object_unref (application->root);
+ application->root = NULL;
+ }
+
+ G_OBJECT_CLASS (atspi_application_parent_class)->dispose (object);
+}
+
+static void
+atspi_application_finalize (GObject *object)
+{
+ AtspiApplication *application = ATSPI_APPLICATION (object);
+
+ g_free (application->bus_name);
+ g_free (application->toolkit_name);
+ g_free (application->toolkit_version);
+ g_free (application->atspi_version);
+
+ G_OBJECT_CLASS (atspi_application_parent_class)->finalize (object);
+}
+
+static void
+atspi_application_class_init (AtspiApplicationClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = atspi_application_dispose;
+ object_class->finalize = atspi_application_finalize;
+}
+
+AtspiApplication *
+_atspi_application_new (const gchar *bus_name)
+{
+ AtspiApplication *application;
+
+ application = g_object_new (ATSPI_TYPE_APPLICATION, NULL);
+ application->bus_name = g_strdup (bus_name);
+ application->root = NULL;
+ return application;
+}
diff --git a/atspi/atspi-application.h b/atspi/atspi-application.h
new file mode 100644
index 0000000..a2cc2e4
--- /dev/null
+++ b/atspi/atspi-application.h
@@ -0,0 +1,68 @@
+/*
+ * 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_APPLICATION_H_
+#define _ATSPI_APPLICATION_H_
+
+#include <dbus/dbus.h>
+
+#include "atspi-accessible.h"
+#include <sys/time.h>
+
+G_BEGIN_DECLS
+
+#define ATSPI_TYPE_APPLICATION (atspi_application_get_type ())
+#define ATSPI_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_APPLICATION, AtspiApplication))
+#define ATSPI_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_APPLICATION, AtspiAccessibleClass))
+#define ATSPI_IS_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_APPLICATION))
+#define ATSPI_IS_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_APPLICATION))
+#define ATSPI_APPLICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_APPLICATION, AtspiAccessibleClass))
+
+typedef struct _AtspiApplication AtspiApplication;
+struct _AtspiApplication
+{
+ GObject parent;
+ GHashTable *hash;
+ char *bus_name;
+ DBusConnection *bus;
+ struct _AtspiAccessible *root;
+ AtspiCache cache;
+ gchar *toolkit_name;
+ gchar *toolkit_version;
+ gchar *atspi_version;
+ struct timeval time_added;
+};
+
+typedef struct _AtspiApplicationClass AtspiApplicationClass;
+struct _AtspiApplicationClass
+{
+ GObjectClass parent_class;
+};
+
+AtspiApplication *
+_atspi_application_new (const char *bus_name);
+
+G_END_DECLS
+
+#endif /* _ATSPI_APPLICATION_H_ */
diff --git a/atspi/atspi-collection.c b/atspi/atspi-collection.c
new file mode 100644
index 0000000..f4e33ef
--- /dev/null
+++ b/atspi/atspi-collection.c
@@ -0,0 +1,296 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2007 IBM Corp.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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"
+
+/* TODO: Improve documentation and implement some missing functions */
+
+/**
+ * atspi_collection_is_ancestor_of:
+ *
+ * Not yet implemented.
+ *
+ **/
+gboolean
+atspi_collection_is_ancestor_of (AtspiCollection *collection,
+ AtspiAccessible *test,
+ GError **error)
+{
+ g_warning ("Atspi: TODO: Implement is_ancestor_of");
+ return FALSE;
+}
+
+static DBusMessage *
+new_message (AtspiCollection *collection, char *method)
+{
+ AtspiAccessible *accessible;
+
+ if (!collection)
+ return NULL;
+
+ accessible = ATSPI_ACCESSIBLE (collection);
+ if (!accessible->parent.app)
+ return NULL;
+ return dbus_message_new_method_call (accessible->parent.app->bus_name,
+ accessible->parent.path,
+ atspi_interface_collection,
+ method);
+}
+
+static gboolean
+append_match_rule (DBusMessage *message, AtspiMatchRule *rule)
+{
+ DBusMessageIter iter;
+
+ dbus_message_iter_init_append (message, &iter);
+ return _atspi_match_rule_marshal (rule, &iter);
+}
+
+static gboolean
+append_accessible (DBusMessage *message, AtspiAccessible *accessible)
+{
+ DBusMessageIter iter;
+
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH,
+ &accessible->parent.path);
+ return TRUE; /* TODO: Check for out-of-memory */
+}
+
+static GArray *
+return_accessibles (DBusMessage *message)
+{
+ DBusMessageIter iter, iter_array;
+ GArray *ret = g_array_new (TRUE, TRUE, sizeof (AtspiAccessible *));
+
+ _ATSPI_DBUS_CHECK_SIG (message, "a(so)", NULL, NULL);
+
+ dbus_message_iter_init (message, &iter);
+ dbus_message_iter_recurse (&iter, &iter_array);
+
+ while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+ {
+ AtspiAccessible *accessible;
+ accessible = _atspi_dbus_return_accessible_from_iter (&iter_array);
+ ret = g_array_append_val (ret, accessible);
+ /* Iter was moved already, so no need to call dbus_message_iter_next */
+ }
+ dbus_message_unref (message);
+ return ret;
+}
+
+/**
+ * atspi_collection_get_matches:
+ * @collection: A pointer to the #AtspiCollection to query.
+ * @rule: An #AtspiMatchRule describing the match criteria.
+ * @sortby: An #AtspiCollectionSortOrder specifying the way the results are to
+ * be sorted.
+ * @count: The maximum number of results to return, or 0 for no limit.
+ * @traverse: Not supported.
+ *
+ * Gets all #AtspiAccessible objects from the @collection matching a given
+ * @rule.
+ *
+ * Returns: (element-type AtspiAccessible*) (transfer full): All
+ * #AtspiAccessible objects matching the given match rule.
+ **/
+GArray *
+atspi_collection_get_matches (AtspiCollection *collection,
+ AtspiMatchRule *rule,
+ AtspiCollectionSortOrder sortby,
+ gint count,
+ gboolean traverse,
+ GError **error)
+{
+ DBusMessage *message = new_message (collection, "GetMatches");
+ DBusMessage *reply;
+ dbus_int32_t d_sortby = sortby;
+ dbus_int32_t d_count = count;
+ dbus_bool_t d_traverse = traverse;
+
+ if (!message)
+ return NULL;
+
+ if (!append_match_rule (message, rule))
+ return NULL;
+ dbus_message_append_args (message, DBUS_TYPE_UINT32, &d_sortby,
+ DBUS_TYPE_INT32, &d_count,
+ DBUS_TYPE_BOOLEAN, &d_traverse,
+ DBUS_TYPE_INVALID);
+ reply = _atspi_dbus_send_with_reply_and_block (message, error);
+ if (!reply)
+ return NULL;
+ return return_accessibles (reply);
+}
+
+/**
+ * atspi_collection_get_matches_to:
+ * @collection: A pointer to the #AtspiCollection to query.
+ * @current_object: The object at which to start searching.
+ * @rule: An #AtspiMatchRule describing the match criteria.
+ * @sortby: An #AtspiCollectionSortOrder specifying the way the results are to
+ * be sorted.
+ * @tree: An #AtspiCollectionTreeTraversalType specifying restrictions on
+ * the objects to be traversed.
+ * @limit_scope: If #TRUE, only descendants of @current_object's parent
+ * will be returned. Otherwise (if #FALSE), any accessible may be
+ * returned if it would preceed @current_object in a flattened
+ * hierarchy.
+ * @count: The maximum number of results to return, or 0 for no limit.
+ * @traverse: Not supported.
+ *
+ * Gets all #AtspiAccessible objects from the @collection, after
+ * @current_object, matching a given @rule.
+ *
+ * Returns: (element-type AtspiAccessible*) (transfer full): All
+ * #AtspiAccessible objects matching the given match rule after
+ * @current_object.
+ **/
+GArray *
+atspi_collection_get_matches_to (AtspiCollection *collection,
+ AtspiAccessible *current_object,
+ AtspiMatchRule *rule,
+ AtspiCollectionSortOrder sortby,
+ AtspiCollectionTreeTraversalType tree,
+ gboolean limit_scope,
+ gint count,
+ gboolean traverse,
+ GError **error)
+{
+ DBusMessage *message = new_message (collection, "GetMatchesTo");
+ DBusMessage *reply;
+ dbus_int32_t d_sortby = sortby;
+ dbus_int32_t d_tree = tree;
+ dbus_bool_t d_limit_scope = limit_scope;
+ dbus_int32_t d_count = count;
+ dbus_bool_t d_traverse = traverse;
+
+ if (!message)
+ return NULL;
+
+ if (!append_accessible (message, current_object))
+ return NULL;
+ if (!append_match_rule (message, rule))
+ return NULL;
+ dbus_message_append_args (message, DBUS_TYPE_UINT32, &d_sortby,
+ DBUS_TYPE_UINT32, &d_tree,
+ DBUS_TYPE_BOOLEAN, &d_limit_scope,
+ DBUS_TYPE_INT32, &d_count,
+ DBUS_TYPE_BOOLEAN, &d_traverse,
+ DBUS_TYPE_INVALID);
+ reply = _atspi_dbus_send_with_reply_and_block (message, error);
+ if (!reply)
+ return NULL;
+ return return_accessibles (reply);
+}
+
+/**
+ * atspi_collection_get_matches_from:
+ * @collection: A pointer to the #AtspiCollection to query.
+ * @current_object: Upon reaching this object, searching should stop.
+ * @rule: An #AtspiMatchRule describing the match criteria.
+ * @sortby: An #AtspiCollectionSortOrder specifying the way the results are to
+ * be sorted.
+ * @tree: An #AtspiCollectionTreeTraversalType specifying restrictions on
+ * the objects to be traversed.
+ * @count: The maximum number of results to return, or 0 for no limit.
+ * @traverse: Not supported.
+ *
+ * Gets all #AtspiAccessible objects from the @collection, before
+ * @current_object, matching a given @rule.
+ *
+ * Returns: (element-type AtspiAccessible*) (transfer full): All
+ * #AtspiAccessible objects matching the given match rule that preceed
+ * @current_object.
+ **/
+GArray *
+atspi_collection_get_matches_from (AtspiCollection *collection,
+ AtspiAccessible *current_object,
+ AtspiMatchRule *rule,
+ AtspiCollectionSortOrder sortby,
+ AtspiCollectionTreeTraversalType tree,
+ gint count,
+ gboolean traverse,
+ GError **error)
+{
+ DBusMessage *message = new_message (collection, "GetMatchesFrom");
+ DBusMessage *reply;
+ dbus_int32_t d_sortby = sortby;
+ dbus_int32_t d_tree = tree;
+ dbus_int32_t d_count = count;
+ dbus_bool_t d_traverse = traverse;
+
+ if (!message)
+ return NULL;
+
+ if (!append_accessible (message, current_object))
+ return NULL;
+ if (!append_match_rule (message, rule))
+ return NULL;
+ dbus_message_append_args (message, DBUS_TYPE_UINT32, &d_sortby,
+ DBUS_TYPE_UINT32, &d_tree,
+ DBUS_TYPE_INT32, &d_count,
+ DBUS_TYPE_BOOLEAN, &d_traverse,
+ DBUS_TYPE_INVALID);
+ reply = _atspi_dbus_send_with_reply_and_block (message, error);
+ if (!reply)
+ return NULL;
+ return return_accessibles (reply);
+}
+
+/**
+ * atspi_collection_get_active_descendant:
+ *
+* Returns: (transfer full): The active descendant of the given object.
+ * Not yet implemented.
+ **/
+AtspiAccessible *
+atspi_collection_get_active_descendant (AtspiCollection *collection, GError **error)
+{
+ g_warning ("atspi: TODO: Implement get_active_descendants");
+ return NULL;
+}
+
+static void
+atspi_collection_base_init (AtspiCollection *klass)
+{
+}
+
+GType
+atspi_collection_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (AtspiCollection),
+ (GBaseInitFunc) atspi_collection_base_init,
+ (GBaseFinalizeFunc) NULL,
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE, "AtspiCollection", &tinfo, 0);
+
+ }
+ return type;
+}
diff --git a/atspi/atspi-collection.h b/atspi/atspi-collection.h
new file mode 100644
index 0000000..2ba9361
--- /dev/null
+++ b/atspi/atspi-collection.h
@@ -0,0 +1,62 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_COLLECTION_H_
+#define _ATSPI_COLLECTION_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+
+#include "atspi-types.h"
+#include "atspi-matchrule.h"
+
+G_BEGIN_DECLS
+
+#define ATSPI_TYPE_COLLECTION (atspi_collection_get_type ())
+#define ATSPI_IS_COLLECTION(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_COLLECTION)
+#define ATSPI_COLLECTION(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_COLLECTION, AtspiCollection)
+#define ATSPI_COLLECTION_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_COLLECTION, AtspiCollection))
+
+GType atspi_collection_get_type ();
+
+struct _AtspiCollection
+{
+ GTypeInterface parent;
+};
+
+gboolean atspi_collection_is_ancestor_of (AtspiCollection *collection, AtspiAccessible *test, GError **error);
+
+GArray * atspi_collection_get_matches (AtspiCollection *collection, AtspiMatchRule *rule, AtspiCollectionSortOrder sortby, gint count, gboolean traverse, GError **error);
+
+GArray * atspi_collection_get_matches_to (AtspiCollection *collection, AtspiAccessible *current_object, AtspiMatchRule *rule, AtspiCollectionSortOrder sortby, AtspiCollectionTreeTraversalType tree, gboolean limit_scope, gint count, gboolean traverse, GError **error);
+
+GArray * atspi_collection_get_matches_from (AtspiCollection *collection, AtspiAccessible *current_object, AtspiMatchRule *rule, AtspiCollectionSortOrder sortby, AtspiCollectionTreeTraversalType tree, gint count, gboolean traverse, GError **error);
+
+AtspiAccessible * atspi_collection_get_active_descendant (AtspiCollection *collection, GError **error);
+
+G_END_DECLS
+
+#endif /* _ATSPI_COLLECTION_H_ */
diff --git a/atspi/atspi-component.c b/atspi/atspi-component.c
new file mode 100644
index 0000000..bdbe57c
--- /dev/null
+++ b/atspi/atspi-component.c
@@ -0,0 +1,494 @@
+/*
+ * 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.
+ */
+
+/*
+ *
+ * AtspiComponent function implementations
+ *
+ */
+
+#include "atspi-private.h"
+#include "atspi-accessible-private.h"
+
+void
+atspi_rect_free (AtspiRect *rect)
+{
+ g_free (rect);
+}
+
+AtspiRect *
+atspi_rect_copy (AtspiRect *src)
+{
+ AtspiRect *dst = g_new (AtspiRect, 1);
+ dst->x = src->x;
+ dst->y = src->y;
+ dst->height = src->height;
+ dst->width = src->width;
+ return dst;
+}
+
+G_DEFINE_BOXED_TYPE (AtspiRect, atspi_rect, atspi_rect_copy, atspi_rect_free)
+
+AtspiPoint *
+atspi_point_copy (AtspiPoint *src)
+{
+ AtspiPoint *dst = g_new (AtspiPoint, 1);
+ dst->x = src->x;
+ dst->y = src->y;
+ return dst;
+}
+
+G_DEFINE_BOXED_TYPE (AtspiPoint, atspi_point, atspi_point_copy, g_free)
+
+/**
+ * atspi_component_contains:
+ * @obj: a pointer to the #AtspiComponent to query.
+ * @x: a #gint specifying the x coordinate in question.
+ * @y: a #gint specifying the y coordinate in question.
+ * @ctype: the desired coordinate system of the point (@x, @y)
+ * (e.g. CSPI_COORD_TYPE_WINDOW, CSPI_COORD_TYPE_SCREEN).
+ *
+ * Queries whether a given #AtspiComponent contains a particular point.
+ *
+ * Returns: #TRUE if the specified component contains the point (@x, @y),
+ * #FALSE otherwise.
+ **/
+gboolean
+atspi_component_contains (AtspiComponent *obj,
+ gint x,
+ gint y,
+ AtspiCoordType ctype, GError **error)
+{
+ dbus_bool_t retval = FALSE;
+ dbus_int32_t d_x = x, d_y = y;
+ dbus_uint32_t d_ctype = ctype;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_component, "Contains", error, "iiu=>b", d_x, d_y, d_ctype, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_component_get_accessible_at_point:
+ * @obj: a pointer to the #AtspiComponent to query.
+ * @x: a #gint specifying the x coordinate of the point in question.
+ * @y: a #gint specifying the y coordinate of the point in question.
+ * @ctype: the coordinate system of the point (@x, @y)
+ * (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN).
+ *
+ * Gets the accessible child at a given coordinate within an #AtspiComponent.
+ *
+ * Returns: (nullable) (transfer full): a pointer to an
+ * #AtspiAccessible child of the specified component which
+ * contains the point (@x, @y), or NULL if no child contains
+ * the point.
+ **/
+AtspiAccessible *
+atspi_component_get_accessible_at_point (AtspiComponent *obj,
+ gint x,
+ gint y,
+ AtspiCoordType ctype, GError **error)
+{
+ dbus_int32_t d_x = x, d_y = y;
+ dbus_uint32_t d_ctype = ctype;
+ DBusMessage *reply;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ reply = _atspi_dbus_call_partial (obj, atspi_interface_component, "GetAccessibleAtPoint", error, "iiu", d_x, d_y, d_ctype);
+
+ return _atspi_dbus_return_accessible_from_message (reply);
+}
+
+/**
+ * atspi_component_get_extents:
+ * @obj: a pointer to the #AtspiComponent to query.
+ * @ctype: the desired coordinate system into which to return the results,
+ * (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN).
+ *
+ * Gets the bounding box of the specified #AtspiComponent.
+ *
+ * Returns: An #AtspiRect giving the accessible's extents.
+ **/
+AtspiRect *
+atspi_component_get_extents (AtspiComponent *obj,
+ AtspiCoordType ctype, GError **error)
+{
+ dbus_uint32_t d_ctype = ctype;
+ AtspiRect bbox;
+ AtspiAccessible *accessible;
+
+ bbox.x = bbox.y = bbox.width = bbox.height = -1;
+ g_return_val_if_fail (obj != NULL, atspi_rect_copy (&bbox));
+
+ accessible = ATSPI_ACCESSIBLE (obj);
+ if (accessible->priv->cache && ctype == ATSPI_COORD_TYPE_SCREEN)
+ {
+ GValue *val = g_hash_table_lookup (accessible->priv->cache, "Component.ScreenExtents");
+ if (val)
+ {
+ return g_value_dup_boxed (val);
+ }
+ }
+
+ _atspi_dbus_call (obj, atspi_interface_component, "GetExtents", error, "u=>(iiii)", d_ctype, &bbox);
+ return atspi_rect_copy (&bbox);
+}
+
+/**
+ * atspi_component_get_position:
+ * @obj: a pointer to the #AtspiComponent to query.
+ * @ctype: the desired coordinate system into which to return the results,
+ * (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN).
+ *
+ * Gets the minimum x and y coordinates of the specified #AtspiComponent.
+ *
+ * returns: An #AtspiPoint giving the @obj's position.
+ **/
+AtspiPoint *
+atspi_component_get_position (AtspiComponent *obj,
+ AtspiCoordType ctype, GError **error)
+{
+ dbus_int32_t d_x, d_y;
+ dbus_uint32_t d_ctype = ctype;
+ AtspiPoint ret;
+
+ ret.x = ret.y = -1;
+
+ if (!obj)
+ return atspi_point_copy (&ret);
+
+ _atspi_dbus_call (obj, atspi_interface_component, "GetPosition", error, "u=>ii", d_ctype, &d_x, &d_y);
+
+ ret.x = d_x;
+ ret.y = d_y;
+ return atspi_point_copy (&ret);
+}
+
+/**
+ * atspi_component_get_size:
+ * @obj: a pointer to the #AtspiComponent to query.
+ *
+ * Gets the size of the specified #AtspiComponent.
+ *
+ * returns: An #AtspiPoint giving the @obj's size.
+ **/
+AtspiPoint *
+atspi_component_get_size (AtspiComponent *obj, GError **error)
+{
+ dbus_int32_t d_w, d_h;
+ AtspiPoint ret;
+
+ ret.x = ret.y = -1;
+ if (!obj)
+ return atspi_point_copy (&ret);
+
+ _atspi_dbus_call (obj, atspi_interface_component, "GetSize", error, "=>ii", &d_w, &d_h);
+ ret.x = d_w;
+ ret.y = d_h;
+ return atspi_point_copy (&ret);
+}
+
+/**
+ * atspi_component_get_layer:
+ * @obj: a pointer to the #AtspiComponent to query.
+ *
+ * Queries which layer the component is painted into, to help determine its
+ * visibility in terms of stacking order.
+ *
+ * Returns: the #AtspiComponentLayer into which this component is painted.
+ **/
+AtspiComponentLayer
+atspi_component_get_layer (AtspiComponent *obj, GError **error)
+{
+ dbus_uint32_t zlayer = -1;
+
+ _atspi_dbus_call (obj, atspi_interface_component, "GetLayer", error, "=>u", &zlayer);
+
+ return zlayer;
+}
+
+/**
+ * atspi_component_get_mdi_z_order:
+ * @obj: a pointer to the #AtspiComponent to query.
+ *
+ * Queries the z stacking order of a component which is in the MDI or window
+ * layer. (Bigger z-order numbers mean nearer the top)
+ *
+ * Returns: a #gshort indicating the stacking order of the component
+ * in the MDI layer, or -1 if the component is not in the MDI layer.
+ **/
+gshort
+atspi_component_get_mdi_z_order (AtspiComponent *obj, GError **error)
+{
+ dbus_uint16_t retval = -1;
+
+ _atspi_dbus_call (obj, atspi_interface_component, "GetMDIZOrder", error, "=>n", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_component_grab_focus:
+ * @obj: a pointer to the #AtspiComponent on which to operate.
+ *
+ * Attempts to set the keyboard input focus to the specified
+ * #AtspiComponent.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ *
+ **/
+gboolean
+atspi_component_grab_focus (AtspiComponent *obj, GError **error)
+{
+ dbus_bool_t retval = FALSE;
+
+ _atspi_dbus_call (obj, atspi_interface_component, "GrabFocus", error, "=>b", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_component_grab_highlight:
+ * @obj: a pointer to the #AtspiComponent on which to operate.
+ *
+ * Attempts to set highlight to the specified
+ * #AtspiComponent.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ *
+ **/
+gboolean
+atspi_component_grab_highlight (AtspiComponent *obj, GError **error)
+{
+ dbus_bool_t retval = FALSE;
+
+ _atspi_dbus_call (obj, atspi_interface_component, "GrabHighlight", error, "=>b", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_component_clear_highlight:
+ * @obj: a pointer to the #AtspiComponent on which to operate.
+ *
+ * Attempts to clear highlight on the specified
+ * #AtspiComponent.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ *
+ **/
+gboolean
+atspi_component_clear_highlight (AtspiComponent *obj, GError **error)
+{
+ dbus_bool_t retval = FALSE;
+
+ _atspi_dbus_call (obj, atspi_interface_component, "ClearHighlight", error, "=>b", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_component_get_alpha:
+ * @obj: The #AtspiComponent to be queried.
+ *
+ * Gets the opacity/alpha value of a component, if alpha blending is in use.
+ *
+ * Returns: the opacity value of a component, as a #gdouble between 0.0 and 1.0.
+ **/
+gdouble
+atspi_component_get_alpha (AtspiComponent *obj, GError **error)
+{
+ double retval = 1;
+
+ _atspi_dbus_call (obj, atspi_interface_component, "GetAlpha", error, "=>d", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_component_set_extents:
+ * @obj: a pointer to the #AtspiComponent to move.
+ * @x: the new vertical position to which the component should be moved.
+ * @y: the new horizontal position to which the component should be moved.
+ * @width: the width to which the component should be resized.
+ * @height: the height to which the component should be resized.
+ * @ctype: the coordinate system in which the position is specified.
+ * (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN).
+ *
+ * Moves and resizes the specified component.
+ *
+ * Returns: #TRUE if successful; #FALSE otherwise.
+ **/
+gboolean
+atspi_component_set_extents (AtspiComponent *obj,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ AtspiCoordType ctype,
+ GError **error)
+{
+ dbus_int32_t d_x = x, d_y = y, d_width = width, d_height = height;
+ dbus_uint32_t d_ctype = ctype;
+ DBusMessageIter iter, iter_struct;
+ DBusMessage *message, *reply;
+ dbus_bool_t retval = FALSE;
+ AtspiAccessible *aobj = ATSPI_ACCESSIBLE (obj);
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ if (!aobj->parent.app || !aobj->parent.app->bus_name)
+ {
+ g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_APPLICATION_GONE,
+ _("The application no longer exists"));
+ return FALSE;
+ }
+
+ message = dbus_message_new_method_call (aobj->parent.app->bus_name,
+ aobj->parent.path,
+ atspi_interface_component,
+ "SetExtents");
+ if (!message)
+ return FALSE;
+
+ dbus_message_iter_init_append (message, &iter);
+ if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL, &iter_struct))
+ {
+ dbus_message_unref (message);
+ return FALSE;
+ }
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_x);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_y);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_width);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_height);
+ dbus_message_iter_close_container (&iter, &iter_struct);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &d_ctype);
+
+ reply = _atspi_dbus_send_with_reply_and_block (message, error);
+ dbus_message_get_args (reply, NULL, DBUS_TYPE_BOOLEAN, &retval,
+ DBUS_TYPE_INVALID);
+ dbus_message_unref (reply);
+ return retval;
+}
+
+/**
+ * atspi_component_set_position:
+ * @obj: a pointer to the #AtspiComponent to move.
+ * @x: the new vertical position to which the component should be moved.
+ * @y: the new horizontal position to which the component should be moved.
+ * @ctype: the coordinate system in which the position is specified.
+ * (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN).
+ *
+ * Moves the component to the specified position.
+ *
+ * Returns: #TRUE if successful; #FALSE otherwise.
+ **/
+gboolean
+atspi_component_set_position (AtspiComponent *obj,
+ gint x,
+ gint y,
+ AtspiCoordType ctype,
+ GError **error)
+{
+ dbus_int32_t d_x = x, d_y = y;
+ dbus_uint32_t d_ctype = ctype;
+ dbus_bool_t ret = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_component, "SetPosition", error,
+ "iiu=>b", d_x, d_y, d_ctype, &ret);
+
+ return ret;
+}
+
+/**
+ * atspi_component_set_size:
+ * @obj: a pointer to the #AtspiComponent to query.
+ * @width: the width to which the component should be resized.
+ * @height: the height to which the component should be resized.
+ *
+ * Resizes the specified component to the given coordinates.
+ *
+ * Returns: #TRUE if successful; #FALSE otherwise.
+ **/
+gboolean
+atspi_component_set_size (AtspiComponent *obj,
+ gint width,
+ gint height,
+ GError **error)
+{
+ dbus_int32_t d_width = width, d_height = height;
+ dbus_bool_t ret = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_component, "SetSize", error, "ii=>b",
+ d_width, d_height, &ret);
+
+ return ret;
+}
+
+/**
+ * atspi_component_get_highlight_index
+ * @obj: a pointer to the #AtspiComponent to query.
+ *
+ * Returns: highlight index of object if (>0), 0 if highlight index is not set
+ * or -1 if an error occured.
+ **/
+int
+atspi_component_get_highlight_index (AtspiComponent *obj, GError **error)
+{
+ gint ret = -1;
+ g_return_val_if_fail (obj != NULL, -1);
+ _atspi_dbus_get_property (obj, atspi_interface_component,
+ "HighlightIndex", error, "i", &ret);
+ return ret;
+}
+
+static void
+atspi_component_base_init (AtspiComponent *klass)
+{
+}
+
+GType
+atspi_component_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (AtspiComponent),
+ (GBaseInitFunc) atspi_component_base_init,
+ (GBaseFinalizeFunc) NULL,
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE, "AtspiComponent", &tinfo, 0);
+
+ }
+ return type;
+}
diff --git a/atspi/atspi-component.h b/atspi/atspi-component.h
new file mode 100644
index 0000000..1388072
--- /dev/null
+++ b/atspi/atspi-component.h
@@ -0,0 +1,118 @@
+/*
+ * 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_COMPONENT_H_
+#define _ATSPI_COMPONENT_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+typedef struct _AtspiRect AtspiRect;
+struct _AtspiRect
+{
+ gint x;
+ gint y;
+ gint width;
+ gint height;
+};
+
+/**
+ * ATSPI_TYPE_RECT:
+ *
+ * The #GType for a boxed type holding a #AtspiRect.
+ */
+#define ATSPI_TYPE_RECT (atspi_rect_get_type ())
+
+GType atspi_rect_get_type ();
+
+AtspiRect *atspi_rect_copy (AtspiRect *src);
+
+typedef struct _AtspiPoint AtspiPoint;
+struct _AtspiPoint
+{
+ gint x;
+ gint y;
+};
+
+/**
+ * ATSPI_TYPE_POINT:
+ *
+ * The #GType for a boxed type holding a #AtspiPoint.
+ */
+#define ATSPI_TYPE_POINT (atspi_point_get_type ())
+
+GType atspi_point_get_type ();
+
+AtspiPoint *atspi_point_copy (AtspiPoint *src);
+
+#define ATSPI_TYPE_COMPONENT (atspi_component_get_type ())
+#define ATSPI_IS_COMPONENT(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_COMPONENT)
+#define ATSPI_COMPONENT(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_COMPONENT, AtspiComponent)
+#define ATSPI_COMPONENT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_COMPONENT, AtspiComponent))
+
+GType atspi_component_get_type ();
+
+struct _AtspiComponent
+{
+ GTypeInterface parent;
+};
+
+gboolean atspi_component_contains (AtspiComponent *obj, gint x, gint y, AtspiCoordType ctype, GError **error);
+
+AtspiAccessible *atspi_component_get_accessible_at_point (AtspiComponent *obj, gint x, gint y, AtspiCoordType ctype, GError **error);
+
+AtspiRect *atspi_component_get_extents (AtspiComponent *obj, AtspiCoordType ctype, GError **error);
+
+AtspiPoint *atspi_component_get_position (AtspiComponent *obj, AtspiCoordType ctype, GError **error);
+
+AtspiPoint *atspi_component_get_size (AtspiComponent *obj, GError **error);
+
+AtspiComponentLayer atspi_component_get_layer (AtspiComponent *obj, GError **error);
+
+gshort atspi_component_get_mdi_z_order (AtspiComponent *obj, GError **error);
+
+gboolean atspi_component_grab_focus (AtspiComponent *obj, GError **error);
+
+gdouble atspi_component_get_alpha (AtspiComponent *obj, GError **error);
+
+gboolean atspi_component_set_extents (AtspiComponent *obj, gint x, gint y, gint width, gint height, AtspiCoordType ctype, GError **error);
+
+gboolean atspi_component_set_position (AtspiComponent *obj, gint x, gint y, AtspiCoordType ctype, GError **error);
+
+gboolean atspi_component_set_size (AtspiComponent *obj, gint width, gint height, GError **error);
+
+gboolean atspi_component_grab_highlight (AtspiComponent *obj, GError **error);
+
+gboolean atspi_component_clear_highlight (AtspiComponent *obj, GError **error);
+
+int atspi_component_get_highlight_index(AtspiComponent *obj, GError **error);
+
+G_END_DECLS
+
+#endif /* _ATSPI_COMPONENT_H_ */
diff --git a/atspi/atspi-constants.h b/atspi/atspi-constants.h
new file mode 100644
index 0000000..dd10679
--- /dev/null
+++ b/atspi/atspi-constants.h
@@ -0,0 +1,1382 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2010, 2011 Novell, Inc.
+ * Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * 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.
+ */
+
+/* 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
+
+/**
+ * AtspiLocaleType:
+ * @ATSPI_LOCALE_TYPE_MESSAGES: For localizable natural-language messages.
+ * @ATSPI_LOCALE_TYPE_COLLATE: For regular expression matching and string
+ * collation.
+ * @ATSPI_LOCALE_TYPE_CTYPE: For regular expression matching, character
+ * classification, conversion, case-sensitive comparison, and wide character
+ * functions.
+ * @ATSPI_LOCALE_TYPE_MONETARY: For monetary formatting.
+ * @ATSPI_LOCALE_TYPE_NUMERIC: For number formatting (such as the decimal
+ * point and the thousands separator).
+ * @ATSPI_LOCALE_TYPE_TIME: For time and date formatting.
+ *
+ * Used by interfaces #AtspiText and #AtspiDocument, this
+ * enumeration corresponds to the POSIX 'setlocale' enum values.
+ *
+ **/
+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;
+
+/**
+ * ATSPI_LOCALE_TYPE_COUNT:
+ *
+ * One higher than the highest valid value of #AtspiLocaleType.
+ **/
+#define ATSPI_LOCALE_TYPE _COUNT(5+1)
+
+/**
+ * AtspiCoordType:
+ * @ATSPI_COORD_TYPE_SCREEN: Specifies xy coordinates relative to the screen.
+ * @ATSPI_COORD_TYPE_WINDOW: Specifies xy coordinates relative to the widget's
+ * top-level window.
+ *
+ * Enumeration used by #AtspiComponent, #AtspiImage, and #AtspiText interfaces
+ * to specify whether coordinates are relative to the window or the screen.
+ *
+ **/
+typedef enum {
+ ATSPI_COORD_TYPE_SCREEN,
+ ATSPI_COORD_TYPE_WINDOW,
+} AtspiCoordType;
+
+/**
+ * ATSPI_COORD_TYPE_COUNT:
+ *
+ * One higher than the highest valid value of #AtspiCoordType.
+ **/
+#define ATSPI_COORD_TYPE_COUNT (1+1)
+
+/**
+ * AtspiCollectionSortOrder:
+ * @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:
+ *
+ * Enumeration used by interface #AtspiCollection to specify
+ * the way #AtspiAccesible objects should be sorted.
+ *
+ **/
+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;
+
+/**
+ * ATSPI_SORTORDER_COUNT:
+ *
+ * One higher than the highest valid value of #AtspiCollectionSortOrder.
+ */
+#define ATSPI_SORTORDER_COUNT (7+1)
+
+/**
+ * AtspiCollectionMatchType:
+ * @ATSPI_Collection_MATCH_INVALID: Indicates an error condition or
+ * uninitialized value.
+ * @ATSPI_Collection_MATCH_ALL: #TRUE if all of the criteria are met.
+ * @ATSPI_Collection_MATCH_ANY: #TRUE if any of the criteria are met.
+ * @ATSPI_Collection_MATCH_NONE: #TRUE if none of the criteria are met.
+ * @ATSPI_Collection_MATCH_EMPTY: Same as @ATSPI_Collection_MATCH_ALL if
+ * the criteria is non-empty; for empty criteria this rule requires returned
+ * value to also have empty set.
+ * @ATSPI_Collection_MATCH_LAST_DEFINED: Used only to determine the end of the
+ * enumeration.
+ *
+ * Enumeration used by #AtspiMatchRule to specify
+ * how to interpret #AtspiAccessible objects.
+ *
+ **/
+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;
+
+/**
+ * ATSPI_MATCHTYPE_COUNT:
+ *
+ * One higher than the highest valid value of #AtspiCollectionMatchType.
+ **/
+#define ATSPI_MATCHTYPES_COUNT (5+1)
+
+/**
+ * AtspiCollectionTreeTraversalType:
+ * @ATSPI_Collection_TREE_RESTRICT_CHILDREN:
+ * @ATSPI_Collection_TREE_RESTRICT_SIBLING:
+ * @ATSPI_Collection_TREE_INORDER:
+ * @ATSPI_Collection_TREE_LAST_DEFINED:
+ *
+ * Enumeration used by interface #AtspiCollection to specify
+ * restrictions on #AtspiAccesible objects to be traversed.
+ *
+ **/
+typedef enum {
+ ATSPI_Collection_TREE_RESTRICT_CHILDREN,
+ ATSPI_Collection_TREE_RESTRICT_SIBLING,
+ ATSPI_Collection_TREE_INORDER,
+ ATSPI_Collection_TREE_LAST_DEFINED,
+} AtspiCollectionTreeTraversalType;
+
+/**
+ * ATSPI_TREETRAVERSALTYPE_COUNT:
+ *
+ * One higher than the highest valid value of
+ * #AtspiCollection_TreeTraversalType.
+ */
+#define ATSPI_TREETRAVERSALTYPE _COUNT(3+1)
+
+/**
+ * AtspiComponentLayer:
+ * @ATSPI_LAYER_INVALID: Indicates an error condition or uninitialized value.
+ * @ATSPI_LAYER_BACKGROUND: The bottom-most layer, over which everything else
+ * is painted. The 'desktop background' is generally in this layer.
+ * @ATSPI_LAYER_CANVAS: The 'background' layer for most content renderers and
+ * UI #AtspiComponent containers.
+ * @ATSPI_LAYER_WIDGET: The layer in which the majority of ordinary
+ * 'foreground' widgets reside.
+ * @ATSPI_LAYER_MDI: A special layer between @ATSPI_LAYER_CANVAS and
+ * @ATSPI_LAYER_WIDGET, in which the 'pseudo windows' (e.g. the MDI frames)
+ * reside. See #atspi_component_get_mdi_z_order.
+ * @ATSPI_LAYER_POPUP: A layer for popup window content, above
+ * @ATSPI_LAYER_WIDGET.
+ * @ATSPI_LAYER_OVERLAY: The topmost layer.
+ * @ATSPI_LAYER_WINDOW: The layer in which a toplevel window background usually
+ * resides.
+ * @ATSPI_LAYER_LAST_DEFINED: Used only to determine the end of the
+ * enumeration.
+ *
+ * The #AtspiComponentLayer of an #AtspiComponent instance indicates its
+ * relative stacking order with respect to the onscreen visual representation
+ * of the UI. #AtspiComponentLayer, in combination with #AtspiComponent 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
+ * flat screen review models of the screen, as well as
+ * for other uses. Objects residing in two of the #AtspiComponentLayer
+ * categories support further z-ordering information, with respect to their
+ * peers in the same layer: namely, @ATSPI_LAYER_WINDOW and
+ * @ATSPI_LAYER_MDI. Relative stacking order for other objects within the
+ * same layer is not available; the recommended heuristic is
+ * first child paints first. In other words, assume that the
+ * first siblings in the child list are subject to being overpainted by later
+ * siblings if their bounds intersect. The order of layers, from bottom to top,
+ * is: @ATSPI_LAYER_BACKGROUND, @ATSPI_LAYER_WINDOW, @ATSPI_LAYER_MDI,
+ * @ATSPI_LAYER_CANVAS, @ATSPI_LAYER_WIDGET, @ATSPI_LAYER_POPUP, and
+ * @ATSPI_LAYER_OVERLAY.
+ *
+ */
+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;
+
+/**
+ * ATSPI_COMPONENTLAYER_COUNT:
+ *
+ * One higher than the highest valid value of #AtspiComponentLayer.
+ **/
+#define ATSPI_COMPONENTLAYER_COUNT (8+1)
+
+/**
+ * AtspiTextBoundaryType:
+ * @ATSPI_TEXT_BOUNDARY_CHAR: An #AtspiText instance is bounded by this
+ * character only. Start and end offsets differ by one, by definition,
+ * for this value.
+ * @ATSPI_TEXT_BOUNDARY_WORD_START: 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: 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: 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: 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: 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: 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.
+ *
+ * Specifies the boundary conditions determining a run of text as returned from
+ * #atspi_text_get_text_at_offset, #atspi_text_get_text_after_offset, and
+ * #atspi_text_get_text_before_offset.
+ *
+ * This enumerationis deprecated since 2.9.90 and should not be used. Use
+ * AtspiTextGranularity with #atspi_text_get_string_at_offset instead.
+ **/
+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;
+
+/**
+ *AtspiTextGranularity:
+ *@ATSPI_TEXT_GRANULARITY_CHAR: Granularity is defined by the boundaries between characters
+ * (including non-printing characters)
+ *@ATSPI_TEXT_GRANULARITY_WORD: Granularity is defined by the boundaries of a word,
+ * starting at the beginning of the current word and finishing at the beginning of
+ * the following one, if present.
+ *@ATSPI_TEXT_GRANULARITY_SENTENCE: Granularity is defined by the boundaries of a sentence,
+ * starting at the beginning of the current sentence and finishing at the beginning of
+ * the following one, if present.
+ *@ATSPI_TEXT_GRANULARITY_LINE: Granularity is defined by the boundaries of a line,
+ * starting at the beginning of the current line and finishing at the beginning of
+ * the following one, if present.
+ *@ATSPI_TEXT_GRANULARITY_PARAGRAPH: Granularity is defined by the boundaries of a paragraph,
+ * starting at the beginning of the current paragraph and finishing at the beginning of
+ * the following one, if present.
+ *
+ * Text granularity types used for specifying the granularity of the region of
+ * text we are interested in.
+ **/
+typedef enum {
+ ATSPI_TEXT_GRANULARITY_CHAR,
+ ATSPI_TEXT_GRANULARITY_WORD,
+ ATSPI_TEXT_GRANULARITY_SENTENCE,
+ ATSPI_TEXT_GRANULARITY_LINE,
+ ATSPI_TEXT_GRANULARITY_PARAGRAPH
+} AtspiTextGranularity;
+
+/**
+ * ATSPI_TEXT_BOUNDARY_TYPE_COUNT:
+ *
+ * One higher than the highest valid value of #AtspiTextBoundaryType.
+ */
+#define ATSPI_TEXT_BOUNDARY_TYPE_COUNT (6+1)
+
+/**
+ * AtspiTextClipType:
+ * @ATSPI_TEXT_CLIP_NONE: No characters/glyphs are omitted.
+ * @ATSPI_TEXT_CLIP_MIN: Characters/glyphs clipped by the minimum coordinate
+ * are omitted.
+ * @ATSPI_TEXT_CLIP_MAX: Characters/glyphs which intersect the maximum
+ * coordinate are omitted.
+ * @ATSPI_TEXT_CLIP_BOTH: Only glyphs falling entirely within the region
+ * bounded by min and max are retained.
+ *
+ * Enumeration used by interface #AtspiText to indicate
+ * how to treat characters intersecting bounding boxes.
+ *
+ **/
+typedef enum {
+ ATSPI_TEXT_CLIP_NONE,
+ ATSPI_TEXT_CLIP_MIN,
+ ATSPI_TEXT_CLIP_MAX,
+ ATSPI_TEXT_CLIP_BOTH,
+} AtspiTextClipType;
+
+/**
+ * ATSPI_TEXT_CLIP_TYPE_COUNT:
+ *
+ * One higher than the highest valid value of #AtspiTextClipType.
+ */
+#define ATSPI_TEXT_CLIP_TYPE_COUNT (3+1)
+
+/**
+ * AtspiStateType:
+ * @ATSPI_STATE_INVALID: Indicates an invalid state - probably an error
+ * condition.
+ * @ATSPI_STATE_ACTIVE: Indicates a window is currently the active window, or
+ * an object is the active subelement within a container or table.
+ * @ATSPI_STATE_ACTIVE should not be used for objects which have
+ * @ATSPI_STATE_FOCUSABLE or @ATSPI_STATE_SELECTABLE: Those objects should use
+ * @ATSPI_STATE_FOCUSED and @ATSPI_STATE_SELECTED respectively.
+ * @ATSPI_STATE_ACTIVE is a means to indicate that an object which is not
+ * focusable and not selectable is the currently-active item within its
+ * parent container.
+ * @ATSPI_STATE_ARMED: Indicates that the object is armed.
+ * @ATSPI_STATE_BUSY: 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: Indicates this object is currently checked.
+ * @ATSPI_STATE_COLLAPSED: Indicates this object is collapsed.
+ * @ATSPI_STATE_DEFUNCT: Indicates that this object no longer has a valid
+ * backing widget (for instance, if its peer object has been destroyed).
+ * @ATSPI_STATE_EDITABLE: Indicates the user can change the contents of this
+ * object.
+ * @ATSPI_STATE_ENABLED: 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 @ATSPI_STATE_SENSITIVE if direct
+ * user interaction cannot cause them to acquire @ATSPI_STATE_ENABLED.
+ * See @ATSPI_STATE_SENSITIVE.
+ * @ATSPI_STATE_EXPANDABLE: Indicates this object allows progressive
+ * disclosure of its children.
+ * @ATSPI_STATE_EXPANDED: Indicates this object is expanded.
+ * @ATSPI_STATE_FOCUSABLE: 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: Indicates this object currently has the keyboard
+ * focus.
+ * @ATSPI_STATE_HAS_TOOLTIP: Indicates that the object has an associated
+ * tooltip.
+ * @ATSPI_STATE_HORIZONTAL: Indicates the orientation of this object is
+ * horizontal.
+ * @ATSPI_STATE_ICONIFIED: Indicates this object is minimized and is
+ * represented only by an icon.
+ * @ATSPI_STATE_MODAL: Indicates something must be done with this object
+ * before the user can interact with an object in a different window.
+ * @ATSPI_STATE_MULTI_LINE: Indicates this (text) object can contain multiple
+ * lines of text.
+ * @ATSPI_STATE_MULTISELECTABLE: 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: 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: Indicates this object is currently pressed.
+ * @ATSPI_STATE_RESIZABLE: Indicates the size of this object's size is not
+ * fixed.
+ * @ATSPI_STATE_SELECTABLE: 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: 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: Indicates this object is sensitive, e.g. to user
+ * interaction. @ATSPI_STATE_SENSITIVE usually accompanies.
+ * @ATSPI_STATE_ENABLED for user-actionable controls, but may be found in the
+ * absence of @ATSPI_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 @ATSPI_STATE_SENSITIVE,
+ * for instance if a user makes an explicit selection using an object whose
+ * current state is ambiguous or undefined. See @ATSPI_STATE_ENABLED,
+ * @ATSPI_STATE_INDETERMINATE.
+ * @ATSPI_STATE_SHOWING: 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: Indicates this (text) object can contain only a
+ * single line of text.
+ * @ATSPI_STATE_STALE: Indicates that the information returned for this object
+ * may no longer be synchronized with the application state. This can occur
+ * if the object has @ATSPI_STATE_TRANSIENT, and can also occur towards the
+ * end of the object peer's lifecycle.
+ * @ATSPI_STATE_TRANSIENT: Indicates this object is transient.
+ * @ATSPI_STATE_VERTICAL: 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: Indicates this object is visible, e.g. has been
+ * explicitly marked for exposure to the user. @ATSPI_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
+ * @ATSPI_STATE_VISIBLE and @ATSPI_STATE_SHOWING. The absence of
+ * @ATSPI_STATE_VISIBLE and @ATSPI_STATE_SHOWING is
+ * semantically equivalent to saying that an object is 'hidden'.
+ * @ATSPI_STATE_MANAGES_DESCENDANTS: 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
+ * @ATSPI_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: 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
+ * @ATSPI_STATE_INDETERMINATE if the currently selected text contains a mixture
+ * of weight attributes. In many cases interacting with a
+ * @ATSPI_STATE_INDETERMINATE object will cause the context's corresponding
+ * boolean attribute to be homogenized, whereupon the object will lose
+ * @ATSPI_STATE_INDETERMINATE and a corresponding state-changed event will be
+ * fired.
+ * @ATSPI_STATE_REQUIRED: Indicates that user interaction with this object is
+ * 'required' from the user, for instance before completing the
+ * processing of a form.
+ * @ATSPI_STATE_TRUNCATED: Indicates that an object's onscreen content
+ * is truncated, e.g. a text value in a spreadsheet cell.
+ * @ATSPI_STATE_ANIMATED: 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: 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: This state indicates that the object
+ * in question implements some form of typeahead 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 #AtspiSelection.
+ * In some cases the typeahead behavior may result in full or partial
+ * completion 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: This state indicates that the object in
+ * question supports text selection. It should only be exposed on objects
+ * which implement the #AtspiText interface, in order to distinguish this state
+ * from @ATSPI_STATE_SELECTABLE, which infers that the object in question is a
+ * selectable child of an object which implements #AtspiSelection. While
+ * similar, text selection and subelement selection are distinct operations.
+ * @ATSPI_STATE_IS_DEFAULT: 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: 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_CHECKABLE: Indicates this object has the potential to
+ * be checked, such as a checkbox or toggle-able table cell. @Since:
+ * 2.12
+ *@ATSPI_STATE_HAS_POPUP: Indicates that the object has a popup
+ * context menu or sub-level menu which may or may not be
+ * showing. This means that activation renders conditional content.
+ * Note that ordinary tooltips are not considered popups in this
+ * context. @Since: 2.12
+ * @ATSPI_STATE_READ_ONLY: Indicates that an object which is ENABLED and
+ * SENSITIVE has a value which can be read, but not modified, by the
+ * user. @Since: 2.16
+ * @ATSPI_STATE_HIGHLIGHTED: Indicates that an object which is HIGHLIGHTABLE
+ * has been graphically marked to assits visally impared users. Only one
+ * object per window can have ATSPI_STATE_HIGHLIGHTED state.
+ * @ATSPI_STATE_HIGHLIGHTABLE: Indicates that an object can be graphically
+ * marked to assist visially impaired users.
+ * user. @Since: 2.16
+ * @ATSPI_STATE_LAST_DEFINED: This value of the enumeration should not be used
+ * as a parameter, it indicates the number of items in the #AtspiStateType
+ * enumeration.
+ *
+ *
+ * Enumeration used by various interfaces indicating every possible state
+ * an #AtspiAccesible object can assume.
+ *
+ **/
+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_CHECKABLE,
+ ATSPI_STATE_HAS_POPUP,
+ ATSPI_STATE_READ_ONLY,
+ ATSPI_STATE_HIGHLIGHTED,
+ ATSPI_STATE_HIGHLIGHTABLE,
+ ATSPI_STATE_LAST_DEFINED,
+} AtspiStateType;
+
+/**
+ * ATSPI_STATETYPE_COUNT:
+ *
+ * One higher than the highest valid value of #AtspiStateType.
+ **/
+#define ATSPI_STATETYPE_COUNT (41+1)
+
+/**
+ * AtspiKeyEventType:
+ * @ATSPI_KEY_PRESSED:
+ * @ATSPI_KEY_RELEASED:
+ *
+ * Deprecated. Should not be used.
+ *
+ **/
+typedef enum {
+ ATSPI_KEY_PRESSED,
+ ATSPI_KEY_RELEASED,
+} AtspiKeyEventType;
+
+/**
+ * ATSPI_KEYEVENTTYPE_COUNT:
+ *
+ * One higher than the highest valid value of #AtspiKeyEventType.
+ **/
+#define ATSPI_KEYEVENTTYPE_COUNT (1+1)
+
+/**
+ * AtspiEventType:
+ * @ATSPI_KEY_PRESSED_EVENT: Indicates that a key on a keyboard device was
+ * pressed.
+ * @ATSPI_KEY_RELEASED_EVENT: Indicates that a key on a keyboard device was
+ * released.
+ * @ATSPI_BUTTON_PRESSED_EVENT: Indicates that a button on a non-keyboard
+ * human interface device (HID) was pressed.
+ * @ATSPI_BUTTON_RELEASED_EVENT: Indicates that a button on a non-keyboard
+ * human interface device (HID) was released.
+ *
+ * Enumeration used to specify the event types of interest to an
+ * #AtspiEventListener, or
+ * to identify the type of an event for which notification has been sent.
+ *
+ **/
+typedef enum {
+ ATSPI_KEY_PRESSED_EVENT,
+ ATSPI_KEY_RELEASED_EVENT,
+ ATSPI_BUTTON_PRESSED_EVENT,
+ ATSPI_BUTTON_RELEASED_EVENT,
+} AtspiEventType;
+
+/**
+ * ATSPI_EVENTTYPE_COUNT:
+ *
+ * One higher than the highest valid value of #AtspiEventType.
+ */
+#define ATSPI_EVENTTYPE_COUNT (3+1)
+
+/**
+ * AtspiKeySynthType:
+ * @ATSPI_KEY_PRESS: Emulates the pressing of a hardware keyboard key.
+ * @ATSPI_KEY_RELEASE: Emulates the release of a hardware keyboard key.
+ * @ATSPI_KEY_PRESSRELEASE: Emulates the pressing and immediate releasing
+ * of a hardware keyboard key.
+ * @ATSPI_KEY_SYM: A symbolic key event is generated, without specifying a
+ * hardware key. Note: if the keysym is not present in the current keyboard
+ * map, the #AtspiDeviceEventController 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 keysyms 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: A string is converted to its equivalent keyboard events
+ * and emitted. If the string consists of complex characters or composed
+ * characters which are not in the current keymap, string emission is
+ * subject to the out-of-keymap limitations described for
+ * @ATSPI_KEY_SYM. In practice this limitation primarily effects
+ * Chinese and Japanese locales.
+ *
+ * Enumeration used when synthesizing keyboard input via
+ * #atspi_generate_keyboard_event.
+ *
+ **/
+typedef enum {
+ ATSPI_KEY_PRESS,
+ ATSPI_KEY_RELEASE,
+ ATSPI_KEY_PRESSRELEASE,
+ ATSPI_KEY_SYM,
+ ATSPI_KEY_STRING,
+} AtspiKeySynthType;
+
+/**
+ * ATSPI_KEYSYNTHTYPE_COUNT:
+ *
+ * One higher than the highest valid value of #AtspiKeySynthType.
+ **/
+#define ATSPI_KEYSYNTHTYPE_COUNT (4+1)
+
+/**
+ * AtspiModifierType:
+ * @ATSPI_MODIFIER_SHIFT: The left or right 'Shift' key.
+ * @ATSPI_MODIFIER_SHIFTLOCK: The ShiftLock or CapsLock key.
+ * @ATSPI_MODIFIER_CONTROL: 'Control'/'Ctrl'.
+ * @ATSPI_MODIFIER_ALT: The Alt key (as opposed to AltGr).
+ * @ATSPI_MODIFIER_META: 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 @ATSPI_MODIFIER_META2 means that the 'Mod2Mask' bit
+ * is set in the corresponding XEvent.
+ * @ATSPI_MODIFIER_META2: See @ATSPI_MODIFIER_META.
+ * @ATSPI_MODIFIER_META3: See @ATSPI_MODIFIER_META.
+ * @ATSPI_MODIFIER_NUMLOCK: A symbolic meta key name that is mapped by AT-SPI
+ * to the appropriate META value, for the convenience of the client.
+ *
+ *
+ *
+ **/
+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 = 14,
+} AtspiModifierType;
+
+/**
+ * ATSPI_MODIFIERTYPE_COUNT:
+ *
+ * One higher than the highest valid value of #AtspiModifierType.
+ **/
+#define ATSPI_MODIFIERTYPE_COUNT (7+1)
+
+/**
+ * AtspiRelationType:
+ * @ATSPI_RELATION_NULL: Not a meaningful relationship; clients should not
+ * normally encounter this #AtspiRelationType value.
+ * @ATSPI_RELATION_LABEL_FOR: Object is a label for one or more other objects.
+ * @ATSPI_RELATION_LABELLED_BY: Object is labelled by one or more other
+ * objects.
+ * @ATSPI_RELATION_CONTROLLER_FOR: Object is an interactive object which
+ * modifies the state, onscreen location, or other attributes of one or more
+ * target objects.
+ * @ATSPI_RELATION_CONTROLLED_BY: 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 @ATSPI_RELATION_CONTROLLED_BY
+ * scrollbars.
+ * @ATSPI_RELATION_MEMBER_OF: Object has a grouping relationship (e.g. 'same
+ * group as') to one or more other objects.
+ * @ATSPI_RELATION_TOOLTIP_FOR: Object is a tooltip associated with another
+ * object.
+ * @ATSPI_RELATION_NODE_CHILD_OF: Object is a child of the target.
+ * @ATSPI_RELATION_NODE_PARENT_OF: Object is a parent of the target.
+ * @ATSPI_RELATION_EXTENDED: Used to indicate that a relationship exists, but
+ * its type is not specified in the enumeration.
+ * @ATSPI_RELATION_FLOWS_TO: 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: Reciprocal of @ATSPI_RELATION_FLOWS_TO.
+ * @ATSPI_RELATION_SUBWINDOW_OF: 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: Similar to @ATSPI_RELATION_SUBWINDOW_OF, but
+ * specifically used for cross-process embedding.
+ * @ATSPI_RELATION_EMBEDDED_BY: Reciprocal of @ATSPI_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: Denotes that the object is a transient window or
+ * frame associated with another onscreen object. Similar to @ATSPI_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 an @ATSPI_ROLE_WINDOW
+ * object with the @ATSPI_RELATION_POPUP_FOR relation usually requires
+ * some presentation action on the part
+ * of assistive technology clients, even though the previous toplevel
+ * @ATSPI_ROLE_FRAME object may still be the active window.
+ * @ATSPI_RELATION_PARENT_WINDOW_OF: This is the reciprocal relation to
+ * @ATSPI_RELATION_POPUP_FOR.
+ * @ATSPI_RELATION_DESCRIPTION_FOR: Indicates that an object provides
+ * descriptive information about another object; more verbose than
+ * @ATSPI_RELATION_LABEL_FOR.
+ * @ATSPI_RELATION_DESCRIBED_BY: Indicates that another object provides
+ * descriptive information about this object; more verbose than
+ * @ATSPI_RELATION_LABELLED_BY.
+ * @ATSPI_RELATION_LAST_DEFINED: Do not use as a parameter value, used to
+ * determine the size of the enumeration.
+ *
+ * #AtspiRelationType 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
+ * @ATSPI_RELATION_LABELLED_BY
+ * relationship may be used to identify labelling information that should
+ * accompany the accessible name property when presenting an object's content or
+ * identity to the end user. Similarly,
+ * @ATSPI_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.
+ *
+ *
+ * Enumeration used to specify
+ * the type of relation encapsulated in an #AtspiRelation object.
+ *
+ **/
+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;
+
+/**
+ * ATSPI_RELATIONTYPE_COUNT:
+ *
+ * One higher than the highest valid value of #AtspiRelationType.
+ **/
+#define ATSPI_RELATIONTYPE_COUNT (19+1)
+
+/**
+ * AtspiRole:
+ * @ATSPI_ROLE_INVALID: A role indicating an error condition, such as
+ * uninitialized Role data.
+ * @ATSPI_ROLE_ACCELERATOR_LABEL: Object is a label indicating the keyboard
+ * accelerators for the parent.
+ * @ATSPI_ROLE_ALERT: Object is used to alert the user about something.
+ * @ATSPI_ROLE_ANIMATION: Object contains a dynamic or moving image of some
+ * kind.
+ * @ATSPI_ROLE_ARROW: Object is a 2d directional indicator.
+ * @ATSPI_ROLE_CALENDAR: Object contains one or more dates, usually arranged
+ * into a 2d list.
+ * @ATSPI_ROLE_CANVAS: Object that can be drawn into and is used to trap
+ * events.
+ * @ATSPI_ROLE_CHECK_BOX: A choice that can be checked or unchecked and
+ * provides a separate indicator for the current state.
+ * @ATSPI_ROLE_CHECK_MENU_ITEM: A menu item that behaves like a check box. See
+ * @ATSPI_ROLE_CHECK_BOX.
+ * @ATSPI_ROLE_COLOR_CHOOSER: A specialized dialog that lets the user choose a
+ * color.
+ * @ATSPI_ROLE_COLUMN_HEADER: The header for a column of data.
+ * @ATSPI_ROLE_COMBO_BOX: A list of choices the user can select from.
+ * @ATSPI_ROLE_DATE_EDITOR: An object which allows entry of a date.
+ * @ATSPI_ROLE_DESKTOP_ICON: An inconifed internal frame within a DESKTOP_PANE.
+ * @ATSPI_ROLE_DESKTOP_FRAME: A pane that supports internal frames and
+ * iconified versions of those internal frames.
+ * @ATSPI_ROLE_DIAL: 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: A top level window with title bar and a border.
+ * @ATSPI_ROLE_DIRECTORY_PANE: A pane that allows the user to navigate through
+ * and select the contents of a directory.
+ * @ATSPI_ROLE_DRAWING_AREA: 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: An object used for drawing custom user interface
+ * elements.
+ * @ATSPI_ROLE_FILLER: A object that fills up space in a user interface.
+ * @ATSPI_ROLE_FOCUS_TRAVERSABLE: Don't use, reserved for future use.
+ * @ATSPI_ROLE_FONT_CHOOSER: Allows selection of a display font.
+ * @ATSPI_ROLE_FRAME: A top level window with a title bar, border, menubar,
+ * etc.
+ * @ATSPI_ROLE_GLASS_PANE: A pane that is guaranteed to be painted on top of
+ * all panes beneath it.
+ * @ATSPI_ROLE_HTML_CONTAINER: A document container for HTML, whose children
+ * represent the document content.
+ * @ATSPI_ROLE_ICON: A small fixed size picture, typically used to decorate
+ * components.
+ * @ATSPI_ROLE_IMAGE: An image, typically static.
+ * @ATSPI_ROLE_INTERNAL_FRAME: A frame-like object that is clipped by a desktop
+ * pane.
+ * @ATSPI_ROLE_LABEL: An object used to present an icon or short string in an
+ * interface.
+ * @ATSPI_ROLE_LAYERED_PANE: A specialized pane that allows its children to be
+ * drawn in layers, providing a form of stacking order.
+ * @ATSPI_ROLE_LIST: 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: An object that represents an element of a list.
+ * @ATSPI_ROLE_MENU: An object usually found inside a menu bar that contains a
+ * list of actions the user can choose from.
+ * @ATSPI_ROLE_MENU_BAR: 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: An object usually contained in a menu that presents
+ * an action the user can choose.
+ * @ATSPI_ROLE_OPTION_PANE: A specialized pane whose primary use is inside a
+ * dialog.
+ * @ATSPI_ROLE_PAGE_TAB: An object that is a child of a page tab list.
+ * @ATSPI_ROLE_PAGE_TAB_LIST: 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: A generic container that is often used to group objects.
+ * @ATSPI_ROLE_PASSWORD_TEXT: A text object uses for passwords, or other places
+ * where the text content is not shown visibly to the user.
+ * @ATSPI_ROLE_POPUP_MENU: 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: An object used to indicate how much of a task has
+ * been completed.
+ * @ATSPI_ROLE_PUSH_BUTTON: An object the user can manipulate to tell the
+ * application to do something.
+ * @ATSPI_ROLE_RADIO_BUTTON: A specialized check box that will cause other
+ * radio buttons in the same group to become unchecked when this one is
+ * checked.
+ * @ATSPI_ROLE_RADIO_MENU_ITEM: Object is both a menu item and a "radio button"
+ * . See @ATSPI_ROLE_RADIO_BUTTON.
+ * @ATSPI_ROLE_ROOT_PANE: A specialized pane that has a glass pane and a
+ * layered pane as its children.
+ * @ATSPI_ROLE_ROW_HEADER: The header for a row of data.
+ * @ATSPI_ROLE_SCROLL_BAR: 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: An object that allows a user to incrementally view
+ * a large amount of information. @ATSPI_ROLE_SCROLL_PANE objects are usually
+ * accompanied by @ATSPI_ROLE_SCROLL_BAR controllers, on which the
+ * @ATSPI_RELATION_CONTROLLER_FOR and @ATSPI_RELATION_CONTROLLED_BY
+ * reciprocal relations are set. See #atspi_get_relation_set.
+ * @ATSPI_ROLE_SEPARATOR: An object usually contained in a menu to provide a
+ * visible and logical separation of the contents in a menu.
+ * @ATSPI_ROLE_SLIDER: An object that allows the user to select from a bounded
+ * range.
+ * @ATSPI_ROLE_SPIN_BUTTON: An object which allows one of a set of choices to
+ * be selected, and which displays the current choice. Unlike
+ * @ATSPI_ROLE_SCROLL_BAR, @ATSPI_ROLE_SLIDER objects need not control
+ * 'viewport'-like objects.
+ * @ATSPI_ROLE_SPLIT_PANE: A specialized panel that presents two other panels
+ * at the same time.
+ * @ATSPI_ROLE_STATUS_BAR: Object displays non-quantitative status information
+ * (c.f. @ATSPI_ROLE_PROGRESS_BAR)
+ * @ATSPI_ROLE_TABLE: An object used to repesent information in terms of rows
+ * and columns.
+ * @ATSPI_ROLE_TABLE_CELL: A 'cell' or discrete child within a Table. Note:
+ * Table cells need not have @ATSPI_ROLE_TABLE_CELL, other
+ * #AtspiRoleType values are valid as well.
+ * @ATSPI_ROLE_TABLE_COLUMN_HEADER: An object which labels a particular column
+ * in an #AtspiTable.
+ * @ATSPI_ROLE_TABLE_ROW_HEADER: An object which labels a particular row in a
+ * #AtspiTable. #AtspiTable rows and columns may also be labelled via the
+ * @ATSPI_RELATION_LABEL_FOR/@ATSPI_RELATION_LABELLED_BY relationships.
+ * See #atspi_get_relation_set.
+ * @ATSPI_ROLE_TEAROFF_MENU_ITEM: Object allows menu to be removed from menubar
+ * and shown in its own window.
+ * @ATSPI_ROLE_TERMINAL: An object that emulates a terminal.
+ * @ATSPI_ROLE_TEXT: An interactive widget that supports multiple lines of text
+ * and optionally accepts user input, but whose purpose is not to solicit user
+ * input. Thus @ATSPI_ROLE_TEXT is appropriate for the text view in a plain text
+ * editor but inappropriate for an input field in a dialog box or web form. For
+ * widgets whose purpose is to solicit input from the user, see @ATSPI_ROLE_ENTRY
+ * and @ATSPI_ROLE_PASSWORD_TEXT. For generic objects which display a brief amount
+ * of textual information, see @ATSPI_ROLE_STATIC.
+ * @ATSPI_ROLE_TOGGLE_BUTTON: 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: A bar or palette usually composed of push buttons or
+ * toggle buttons.
+ * @ATSPI_ROLE_TOOL_TIP: An object that provides information about another
+ * object.
+ * @ATSPI_ROLE_TREE: An object used to repsent hierarchical information to the
+ * user.
+ * @ATSPI_ROLE_TREE_TABLE: An object that presents both tabular and
+ * hierarchical info to the user.
+ * @ATSPI_ROLE_UNKNOWN: The object contains some #AtspiAccessible information,
+ * but its role is not known.
+ * @ATSPI_ROLE_VIEWPORT: 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: A top level window with no title or border.
+ * @ATSPI_ROLE_EXTENDED: means that the role for this item is known, but not
+ * included in the core enumeration.
+ * @ATSPI_ROLE_HEADER: An object that serves as a document header.
+ * @ATSPI_ROLE_FOOTER: An object that serves as a document footer.
+ * @ATSPI_ROLE_PARAGRAPH: An object which is contains a single paragraph of
+ * text content. See also @ATSPI_ROLE_TEXT.
+ * @ATSPI_ROLE_RULER: An object which describes margins and tab stops, etc.
+ * for text objects which it controls (should have
+ * @ATSPI_RELATION_CONTROLLER_FOR relation to such).
+ * @ATSPI_ROLE_APPLICATION: An object corresponding to the toplevel accessible
+ * of an application, which may contain @ATSPI_ROLE_FRAME objects or other
+ * accessible objects. Children of #AccessibleDesktop objects are generally
+ * @ATSPI_ROLE_APPLICATION objects.
+ * @ATSPI_ROLE_AUTOCOMPLETE: 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: The object is an editable text object in a toolbar.
+ * @ATSPI_ROLE_EMBEDDED: 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: The object is a component whose textual content may be
+ * entered or modified by the user, provided @ATSPI_STATE_EDITABLE is present.
+ * A readonly @ATSPI_ROLE_ENTRY object (i.e. where @ATSPI_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: 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 @ATSPI_LABELLED_BY relation is
+ * particularly important in interpreting objects of this type, as is the
+ * accessible description property. See @ATSPI_ROLE_CAPTION.
+ * @ATSPI_ROLE_CAPTION: The object contains descriptive information, usually
+ * textual, about another user interface element such as a table, chart, or
+ * image.
+ * @ATSPI_ROLE_DOCUMENT_FRAME: The object is a visual frame or container which
+ * contains a view of document content. #AtspiDocument frames may occur within
+ * another #AtspiDocument instance, in which case the second document may be
+ * said to be embedded in the containing instance. HTML frames are often
+ * ATSPI_ROLE_DOCUMENT_FRAME: Either this object, or a singleton descendant,
+ * should implement the #AtspiDocument interface.
+ * @ATSPI_ROLE_HEADING: 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: The object is a containing instance which encapsulates a
+ * page of information. @ATSPI_ROLE_PAGE is used in documents and content which
+ * support a paginated navigation model.
+ * @ATSPI_ROLE_SECTION: 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: 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: 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. @ATSPI_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, @ATSPI_ROLE_FORM containers' components are
+ * associated with the current document, rather than the current foreground
+ * application or viewer instance.
+ * @ATSPI_ROLE_LINK: 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 #AtspiHypertext/#AtspiHyperlink interfacesto indicate
+ * the range/location within a text object where an inline or embedded object
+ * lies.
+ * @ATSPI_ROLE_INPUT_METHOD_WINDOW: 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_TABLE_ROW: A row in a table.
+ * @ATSPI_ROLE_TREE_ITEM: An object that represents an element of a tree.
+ * @ATSPI_ROLE_DOCUMENT_SPREADSHEET: A document frame which contains a
+ * spreadsheet.
+ * @ATSPI_ROLE_DOCUMENT_PRESENTATION: A document frame which contains a
+ * presentation or slide content.
+ * @ATSPI_ROLE_DOCUMENT_TEXT: A document frame which contains textual content,
+ * such as found in a word processing
+ * application.
+ * @ATSPI_ROLE_DOCUMENT_WEB: A document frame which contains HTML or other
+ * markup suitable for display in a web browser.
+ * @ATSPI_ROLE_DOCUMENT_EMAIL: A document frame which contains email content
+ * to be displayed or composed either in plain text or
+ * HTML.
+ * @ATSPI_ROLE_COMMENT: An object found within a document and designed to
+ * present a comment, note, or other annotation. In some cases, this object
+ * might not be visible until activated.
+ * @ATSPI_ROLE_LIST_BOX: A non-collapsible list of choices the user can
+ * select from.
+ * @ATSPI_ROLE_GROUPING: A group of related widgets. This group typically has
+ * a label.
+ * @ATSPI_ROLE_IMAGE_MAP: An image map object. Usually a graphic with multiple
+ * hotspots, where each hotspot can be activated resulting in the loading of
+ * another document or section of a document.
+ * @ATSPI_ROLE_NOTIFICATION: A transitory object designed to present a
+ * message to the user, typically at the desktop level rather than inside a
+ * particular application.
+ * @ATSPI_ROLE_INFO_BAR: An object designed to present a message to the user
+ * within an existing window.
+ * @ATSPI_ROLE_LEVEL_BAR: A bar that serves as a level indicator to, for
+ * instance, show the strength of a password or the state of a battery.
+ * Since: 2.8
+ *@ATSPI_ROLE_TITLE_BAR: A bar that serves as the title of a window or a
+ * dialog. @Since: 2.12
+ *@ATSPI_ROLE_BLOCK_QUOTE: An object which contains a text section
+ * that is quoted from another source. @Since: 2.12
+ *@ATSPI_ROLE_AUDIO: An object which represents an audio
+ * element. @Since: 2.12
+ *@ATSPI_ROLE_VIDEO: An object which represents a video
+ * element. @Since: 2.12
+ *@ATSPI_ROLE_DEFINITION: A definition of a term or concept. @Since: 2.12
+ *@ATSPI_ROLE_ARTICLE: A section of a page that consists of a
+ * composition that forms an independent part of a document, page, or
+ * site. Examples: A blog entry, a news story, a forum post. @Since:
+ * 2.12
+ *@ATSPI_ROLE_LANDMARK: A region of a web page intended as a
+ * navigational landmark. This is designed to allow Assistive
+ * Technologies to provide quick navigation among key regions within a
+ * document. @Since: 2.12
+ *@ATSPI_ROLE_LOG: A text widget or container holding log content, such
+ * as chat history and error logs. In this role there is a
+ * relationship between the arrival of new items in the log and the
+ * reading order. The log contains a meaningful sequence and new
+ * information is added only to the end of the log, not at arbitrary
+ * points. @Since: 2.12
+ *@ATSPI_ROLE_MARQUEE: A container where non-essential information
+ * changes frequently. Common usages of marquee include stock tickers
+ * and ad banners. The primary difference between a marquee and a log
+ * is that logs usually have a meaningful order or sequence of
+ * important content changes. @Since: 2.12
+ *@ATSPI_ROLE_MATH: A text widget or container that holds a mathematical
+ * expression. @Since: 2.12
+ *@ATSPI_ROLE_RATING: A widget whose purpose is to display a rating,
+ * such as the number of stars associated with a song in a media
+ * player. Objects of this role should also implement
+ * AtspiValue. @Since: 2.12
+ *@ATSPI_ROLE_TIMER: An object containing a numerical counter which
+ * indicates an amount of elapsed time from a start point, or the time
+ * remaining until an end point. @Since: 2.12
+ *@ATSPI_ROLE_STATIC: A generic non-container object whose purpose is to display
+ * a brief amount of information to the user and whose role is known by the
+ * implementor but lacks semantic value for the user. Examples in which
+ * @ATSPI_ROLE_STATIC is appropriate include the message displayed in a message
+ * box and an image used as an alternative means to display text.
+ * @ATSPI_ROLE_STATIC should not be applied to widgets which are traditionally
+ * interactive, objects which display a significant amount of content, or any
+ * object which has an accessible relation pointing to another object. The
+ * displayed information, as a general rule, should be exposed through the
+ * accessible name of the object. For labels which describe another widget, see
+ * @ATSPI_ROLE_LABEL. For text views, see @ATSPI_ROLE_TEXT. For generic
+ * containers, see @ATSPI_ROLE_PANEL. For objects whose role is not known by the
+ * implementor, see @ATSPI_ROLE_UNKNOWN. @Since: 2.16.
+ *@ATSPI_ROLE_MATH_FRACTION: An object that represents a mathematical fraction.
+ * @Since: 2.16.
+ *@ATSPI_ROLE_MATH_ROOT: An object that represents a mathematical expression
+ * displayed with a radical. @Since: 2.16.
+ *@ATSPI_ROLE_SUBSCRIPT: An object that contains text that is displayed as a
+ * subscript. @Since: 2.16.
+ *@ATSPI_ROLE_SUPERSCRIPT: An object that contains text that is displayed as a
+ * superscript. @Since: 2.16.
+ * @ATSPI_ROLE_LAST_DEFINED: Not a valid role, used for finding end of
+ * enumeration.
+ *
+ * Enumeration used by interface #AtspiAccessible to specify the role
+ * of an #AtspiAccessible object.
+ *
+ */
+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_TABLE_ROW,
+ ATSPI_ROLE_TREE_ITEM,
+ ATSPI_ROLE_DOCUMENT_SPREADSHEET,
+ ATSPI_ROLE_DOCUMENT_PRESENTATION,
+ ATSPI_ROLE_DOCUMENT_TEXT,
+ ATSPI_ROLE_DOCUMENT_WEB,
+ ATSPI_ROLE_DOCUMENT_EMAIL,
+ ATSPI_ROLE_COMMENT,
+ ATSPI_ROLE_LIST_BOX,
+ ATSPI_ROLE_GROUPING,
+ ATSPI_ROLE_IMAGE_MAP,
+ ATSPI_ROLE_NOTIFICATION,
+ ATSPI_ROLE_INFO_BAR,
+ ATSPI_ROLE_LEVEL_BAR,
+ ATSPI_ROLE_TITLE_BAR,
+ ATSPI_ROLE_BLOCK_QUOTE,
+ ATSPI_ROLE_AUDIO,
+ ATSPI_ROLE_VIDEO,
+ ATSPI_ROLE_DEFINITION,
+ ATSPI_ROLE_ARTICLE,
+ ATSPI_ROLE_LANDMARK,
+ ATSPI_ROLE_LOG,
+ ATSPI_ROLE_MARQUEE,
+ ATSPI_ROLE_MATH,
+ ATSPI_ROLE_RATING,
+ ATSPI_ROLE_TIMER,
+ ATSPI_ROLE_STATIC,
+ ATSPI_ROLE_MATH_FRACTION,
+ ATSPI_ROLE_MATH_ROOT,
+ ATSPI_ROLE_SUBSCRIPT,
+ ATSPI_ROLE_SUPERSCRIPT,
+ ATSPI_ROLE_LAST_DEFINED,
+} AtspiRole;
+
+/**
+ * ATSPI_ROLE_COUNT:
+ *
+ * One higher than the highest valid value of #AtspiRole.
+ */
+#define ATSPI_ROLE_COUNT (121+1)
+
+typedef enum
+{
+ ATSPI_CACHE_NONE = 0,
+ ATSPI_CACHE_PARENT = 1 << 0,
+ ATSPI_CACHE_CHILDREN = 1 << 1,
+ ATSPI_CACHE_NAME = 1 << 2,
+ ATSPI_CACHE_DESCRIPTION = 1 << 3,
+ ATSPI_CACHE_STATES = 1 << 4,
+ ATSPI_CACHE_ROLE = 1 << 5,
+ ATSPI_CACHE_INTERFACES = 1 << 6,
+ ATSPI_CACHE_ATTRIBUTES = 1 << 7,
+ ATSPI_CACHE_ALL = 0x3fffffff,
+ ATSPI_CACHE_DEFAULT = ATSPI_CACHE_PARENT | ATSPI_CACHE_CHILDREN | ATSPI_CACHE_NAME | ATSPI_CACHE_DESCRIPTION | ATSPI_CACHE_STATES | ATSPI_CACHE_ROLE | ATSPI_CACHE_INTERFACES,
+ ATSPI_CACHE_UNDEFINED = 0x40000000,
+} AtspiCache;
+
+#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_EVENT_OBJECT "org.a11y.atspi.Event.Object"
+#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_TABLE_CELL "org.a11y.atspi.TableCell"
+#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"
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _ATSPI_CONSTANTS_H_ */
diff --git a/atspi/atspi-device-listener-private.h b/atspi/atspi-device-listener-private.h
new file mode 100644
index 0000000..1089e45
--- /dev/null
+++ b/atspi/atspi-device-listener-private.h
@@ -0,0 +1,40 @@
+/*
+ * 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_DEVICE_LISTENER_PRIVATE_H_
+#define _ATSPI_DEVICE_LISTENER_PRIVATE_H_
+
+#include "atspi-device-listener.h"
+
+#include "dbus/dbus.h"
+
+G_BEGIN_DECLS
+
+DBusHandlerResult _atspi_dbus_handle_DeviceEvent (DBusConnection *bus, DBusMessage *message, void *data);
+
+gchar *_atspi_device_listener_get_path (AtspiDeviceListener *listener);
+
+G_END_DECLS
+
+#endif /* _ATSPI_DEVICE_LISTENER_H_ */
diff --git a/atspi/atspi-device-listener.c b/atspi/atspi-device-listener.c
new file mode 100644
index 0000000..3ac4451
--- /dev/null
+++ b/atspi/atspi-device-listener.c
@@ -0,0 +1,409 @@
+/*
+ * 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.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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"
+#include <stdio.h>
+
+typedef struct
+{
+ AtspiDeviceListenerCB callback;
+ gpointer user_data;
+ GDestroyNotify callback_destroyed;
+} DeviceEventHandler;
+
+GObjectClass *device_parent_class;
+
+/*
+ * Misc. helpers.
+ */
+
+static DeviceEventHandler *
+device_event_handler_new (AtspiDeviceListenerCB callback,
+ GDestroyNotify callback_destroyed,
+ gpointer user_data)
+{
+ DeviceEventHandler *eh = g_new0 (DeviceEventHandler, 1);
+
+ eh->callback = callback;
+ eh->callback_destroyed = callback_destroyed;
+ eh->user_data = user_data;
+
+ return eh;
+}
+
+static gboolean
+device_remove_datum (const AtspiDeviceEvent *event, void *user_data)
+{
+ AtspiDeviceListenerSimpleCB cb = user_data;
+ return cb (event);
+}
+
+static void
+device_event_handler_free (DeviceEventHandler *eh)
+{
+#if 0
+ /* TODO; Test this; it will probably crash with pyatspi for unknown reasons */
+ if (eh->callback_destroyed)
+ {
+ gpointer rea_callback = (eh->callback == device_remove_datum ?
+ eh->user_data : eh->callback);
+ (*eh->callback_destroyed) (real_callback);
+ }
+#endif
+ g_free (eh);
+}
+
+static GList *
+event_list_remove_by_cb (GList *list, AtspiDeviceListenerCB callback)
+{
+ GList *l, *next;
+
+ for (l = list; l; l = next)
+ {
+ DeviceEventHandler *eh = l->data;
+ next = l->next;
+
+ if (eh->callback == callback)
+ {
+ list = g_list_delete_link (list, l);
+ device_event_handler_free (eh);
+ }
+ }
+
+ return list;
+}
+
+/*
+ * Standard event dispatcher
+ */
+
+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 AtspiDeviceEvent *
+atspi_device_event_copy (const AtspiDeviceEvent *src)
+{
+ AtspiDeviceEvent *dst = g_new0 (AtspiDeviceEvent, 1);
+ dst->type = src->type;
+ dst->id = src->id;
+ dst->hw_code = src->hw_code;
+ dst->modifiers = src->modifiers;
+ dst->timestamp = src->timestamp;
+ if (src->event_string)
+ dst->event_string = g_strdup (src->event_string);
+ dst->is_text = src->is_text;
+ return dst;
+}
+
+void
+atspi_device_event_free (AtspiDeviceEvent *event)
+{
+ if (event->event_string)
+ g_free (event->event_string);
+ g_free (event);
+}
+
+/*
+ * Device event handler
+ */
+static gboolean
+atspi_device_event_dispatch (AtspiDeviceListener *listener,
+ const AtspiDeviceEvent *event)
+{
+ GList *l;
+ gboolean handled = FALSE;
+
+ /* FIXME: re-enterancy hazard on this list */
+ for (l = listener->callbacks; l; l = l->next)
+ {
+ DeviceEventHandler *eh = l->data;
+
+ if ((handled = eh->callback (atspi_device_event_copy (event), eh->user_data)))
+ {
+ break;
+ }
+ }
+
+ return handled;
+}
+
+static void
+atspi_device_listener_init (AtspiDeviceListener *listener)
+{
+
+ do
+ {
+ listener->id = listener_id++;
+ } while (!id_is_free (listener->id));
+ device_listeners = g_list_append (device_listeners, listener);
+}
+
+static void
+atspi_device_listener_finalize (GObject *object)
+{
+ AtspiDeviceListener *listener = (AtspiDeviceListener *) object;
+ GList *l;
+
+ for (l = listener->callbacks; l; l = l->next)
+ {
+ device_event_handler_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)
+
+/**
+ * atspi_device_listener_new:
+ * @callback: (scope notified): an #AtspiDeviceListenerCB callback function,
+ * or NULL.
+ * @user_data: (closure): a pointer to data which will be passed to the
+ * callback when invoked.
+ * @callback_destroyed: A #GDestroyNotify called when the listener is freed
+ * and data associated with the callback should be freed. It can be NULL.
+ *
+ * Creates a new #AtspiDeviceListener with a specified callback function.
+ *
+ * Returns: (transfer full): a pointer to a newly-created #AtspiDeviceListener.
+ *
+ **/
+AtspiDeviceListener *
+atspi_device_listener_new (AtspiDeviceListenerCB callback,
+ void *user_data,
+ GDestroyNotify callback_destroyed)
+{
+ AtspiDeviceListener *listener = g_object_new (atspi_device_listener_get_type (), NULL);
+
+ if (callback)
+ atspi_device_listener_add_callback (listener, callback, callback_destroyed,
+ user_data);
+ return listener;
+}
+
+/**
+ * atspi_device_listener_new_simple: (skip)
+ * @callback: (scope notified): an #AtspiDeviceListenerCB callback function,
+ * or NULL.
+ * @callback_destroyed: A #GDestroyNotify called when the listener is freed
+ * and data associated with the callback should be freed. It an be NULL.
+ *
+ * Creates a new #AtspiDeviceListener with a specified callback function.
+ * This method is similar to #atspi_device_listener_new, but callback
+ * takes no user data.
+ *
+ * Returns: a pointer to a newly-created #AtspiDeviceListener.
+ *
+ **/
+AtspiDeviceListener *
+atspi_device_listener_new_simple (AtspiDeviceListenerSimpleCB callback,
+ GDestroyNotify callback_destroyed)
+{
+ return atspi_device_listener_new (device_remove_datum, callback, callback_destroyed);
+}
+
+/**
+ * atspi_device_listener_add_callback:
+ * @listener: the #AtspiDeviceListener instance to modify.
+ * @callback: (scope notified): an #AtspiDeviceListenerCB function pointer.
+ * @callback_destroyed: A #GDestroyNotify called when the listener is freed
+ * and data associated with the callback should be freed. It can be NULL.
+ * @user_data: (closure): a pointer to data which will be passed to the
+ * callback when invoked.
+ *
+ * Adds an in-process callback function to an existing #AtspiDeviceListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+void
+atspi_device_listener_add_callback (AtspiDeviceListener *listener,
+ AtspiDeviceListenerCB callback,
+ GDestroyNotify callback_destroyed,
+ void *user_data)
+{
+ g_return_if_fail (ATSPI_IS_DEVICE_LISTENER (listener));
+ DeviceEventHandler *new_handler;
+
+ new_handler = device_event_handler_new (callback,
+ callback_destroyed, user_data);
+
+ listener->callbacks = g_list_prepend (listener->callbacks, new_handler);
+}
+
+/**
+ * atspi_device_listener_remove_callback:
+ * @listener: the #AtspiDeviceListener instance to modify.
+ * @callback: (scope call): an #AtspiDeviceListenerCB function pointer.
+ *
+ * Removes an in-process callback function from an existing
+ * #AtspiDeviceListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+void
+atspi_device_listener_remove_callback (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 void
+read_device_event_from_iter (DBusMessageIter *iter, AtspiDeviceEvent *event)
+{
+ dbus_uint32_t type;
+ dbus_int32_t id;
+ dbus_int32_t hw_code;
+ dbus_int32_t modifiers;
+ dbus_int32_t timestamp;
+ 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);
+
+ /* TODO: Remove cast from next two on ABI break */
+ dbus_message_iter_get_basic (&iter_struct, &hw_code);
+ event->hw_code = (gushort) hw_code;
+ dbus_message_iter_next (&iter_struct);
+
+ dbus_message_iter_get_basic (&iter_struct, &modifiers);
+ event->modifiers = (gushort) 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;
+}
+
+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;
+
+ if (strcmp (dbus_message_get_signature (message), "(uiuuisb)") != 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);
+ if (retval != 0 && retval != 1)
+ {
+ g_warning ("at-spi: device event handler returned %d; should be 0 or 1", retval);
+ retval = 0;
+ }
+ }
+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);
+}
+
+G_DEFINE_BOXED_TYPE (AtspiDeviceEvent,
+ atspi_device_event,
+ atspi_device_event_copy,
+ atspi_device_event_free)
diff --git a/atspi/atspi-device-listener.h b/atspi/atspi-device-listener.h
new file mode 100644
index 0000000..3b1b96d
--- /dev/null
+++ b/atspi/atspi-device-listener.h
@@ -0,0 +1,97 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_DEVICE_LISTENER_H_
+#define _ATSPI_DEVICE_LISTENER_H_
+
+#include "glib-object.h"
+
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+GType atspi_device_event_get_type (void);
+
+/**
+ * AtspiDeviceListenerCB:
+ * @stroke: (transfer full): 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);
+
+/**
+ * AtspiDeviceListenerSimpleCB:
+ * @stroke: (transfer full): The #AtspiDeviceEvent for which notification is
+ * being received.
+ *
+ * Similar to #AtspiDeviceListenerCB, but with no user data.
+ *
+ * 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 (*AtspiDeviceListenerSimpleCB) (const AtspiDeviceEvent *stroke);
+
+#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))
+
+typedef struct _AtspiDeviceListener AtspiDeviceListener;
+struct _AtspiDeviceListener
+{
+ GObject parent;
+ guint id;
+ GList *callbacks;
+};
+
+typedef struct _AtspiDeviceListenerClass AtspiDeviceListenerClass;
+struct _AtspiDeviceListenerClass
+{
+ GObjectClass parent_class;
+ gboolean (*device_event) (AtspiDeviceListener *listener, const AtspiDeviceEvent *event);
+};
+
+GType atspi_device_listener_get_type (void);
+
+AtspiDeviceListener *atspi_device_listener_new (AtspiDeviceListenerCB callback, void *user_data, GDestroyNotify callback_destroyed);
+
+AtspiDeviceListener *atspi_device_listener_new_simple (AtspiDeviceListenerSimpleCB callback, GDestroyNotify callback_destroyed);
+
+void atspi_device_listener_add_callback (AtspiDeviceListener *listener, AtspiDeviceListenerCB callback, GDestroyNotify callback_destroyed, void *user_data);
+
+void atspi_device_listener_remove_callback (AtspiDeviceListener *listener, AtspiDeviceListenerCB callback);
+
+G_END_DECLS
+
+#endif /* _ATSPI_DEVICE_LISTENER_H_ */
diff --git a/atspi/atspi-document.c b/atspi/atspi-document.c
new file mode 100644
index 0000000..98dfc4f
--- /dev/null
+++ b/atspi/atspi-document.c
@@ -0,0 +1,198 @@
+/*
+ * 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"
+
+/**
+ * atspi_document_get_locale:
+ * @obj: a pointer to the #AtspiDocument object on which to operate.
+ *
+ * Gets the locale associated with the document's content,
+ * e.g. the locale for LOCALE_TYPE_MESSAGES.
+ *
+ * Returns: a string compliant with the POSIX standard for locale description.
+ **/
+gchar *
+atspi_document_get_locale (AtspiDocument *obj, GError **error)
+{
+ gchar *retval = NULL;
+
+ g_return_val_if_fail (obj != NULL, g_strdup ("C"));
+
+ _atspi_dbus_call (obj, atspi_interface_document, "GetLocale", error, "=>s", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_document_get_attribute_value: (rename-to atspi_document_get_document_attribute_value)
+ * @obj: a pointer to the #AtspiDocument object on which to operate.
+ * @attribute: a string indicating the name of a specific attribute.
+ *
+ * Gets the value of a single attribute, if specified for the document as a whole.
+ *
+ * Returns: a string corresponding to the value of the specified attribute, or
+ * an empty string if the attribute is unspecified for the object.
+ *
+ * Deprecated: 2.10: Use atspi_document_get_document_attribute_value instead.
+ **/
+gchar *
+atspi_document_get_attribute_value (AtspiDocument *obj,
+ gchar *attribute,
+ GError **error)
+{
+ return atspi_document_get_document_attribute_value (obj, attribute, error);
+}
+
+/**
+ * atspi_document_get_document_attribute_value:
+ * @obj: a pointer to the #AtspiDocument object on which to operate.
+ * @attribute: a string indicating the name of a specific attribute.
+ *
+ * Gets the value of a single attribute, if specified for the document as a whole.
+ *
+ * Returns: a string corresponding to the value of the specified attribute, or
+ * an empty string if the attribute is unspecified for the object.
+ **/
+gchar *
+atspi_document_get_document_attribute_value (AtspiDocument *obj,
+ gchar *attribute,
+ GError **error)
+{
+ gchar *retval = NULL;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ _atspi_dbus_call (obj, atspi_interface_document, "GetAttributeValue", error, "s=>s", attribute, &retval);
+
+ if (!retval)
+ retval = g_strdup ("");
+
+ return retval;
+}
+
+
+/**
+ * atspi_document_get_attributes: (rename-to atspi_document_get_document_attributes)
+ * @obj: a pointer to the #AtspiDocument object on which to operate.
+ *
+ * Gets all constant attributes for the document as a whole. For attributes
+ * that change within the document content, see @atspi_text_get_attribute_run instead.
+ *
+ * Returns: (element-type gchar* gchar*) (transfer full): a #GHashTable
+ * containing the constant attributes of the document, as name-value pairs.
+ *
+ * Deprecated: 2.10: Use atspi_document_get_document_attributes instead.
+ **/
+GHashTable *
+atspi_document_get_attributes (AtspiDocument *obj, GError **error)
+{
+ return atspi_document_get_document_attributes (obj, error);
+}
+
+/**
+ * atspi_document_get_document_attributes:
+ * @obj: a pointer to the #AtspiDocument object on which to operate.
+ *
+ * Gets all constant attributes for the document as a whole. For attributes
+ * that change within the document content, see @atspi_text_get_attribute_run instead.
+ *
+ * Returns: (element-type gchar* gchar*) (transfer full): a #GHashTable
+ * containing the constant attributes of the document, as name-value pairs.
+ **/
+GHashTable *
+atspi_document_get_document_attributes (AtspiDocument *obj, GError **error)
+{
+ DBusMessage *message;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ message = _atspi_dbus_call_partial (obj, atspi_interface_document, "GetAttributes", error, "");
+ return _atspi_dbus_return_hash_from_message (message);
+}
+
+/**
+ * atspi_document_get_page_count:
+ * @obj: a pointer to the #AtspiDocument object to query.
+ *
+ * Gets the page count of an #AccessibleDocument object.
+ *
+ * Returns: a #gint indicating the page count of an
+ * #AccessibleDocument object.
+ **/
+gint
+atspi_document_get_page_count (AtspiDocument *obj, GError **error)
+{
+ dbus_int32_t retval = 0;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_get_property (obj, atspi_interface_document, "PageCount", error, "i", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_document_get_current_page_number:
+ * @obj: a pointer to the #AtspiDocument object to query.
+ *
+ * Gets the current page number of an #AccessibleDocument object.
+ *
+ * Returns: a #gint indicating the current page number in the
+ * #AccessibleDocument object.
+ **/
+gint
+atspi_document_get_current_page_number (AtspiDocument *obj, GError **error)
+{
+ dbus_int32_t retval = 0;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_get_property (obj, atspi_interface_document, "CurrentPageNumber", error, "i", &retval);
+
+ return retval;
+}
+
+static void
+atspi_document_base_init (AtspiDocument *klass)
+{
+}
+
+GType
+atspi_document_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (AtspiDocument),
+ (GBaseInitFunc) atspi_document_base_init,
+ (GBaseFinalizeFunc) NULL,
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE, "AtspiDocument", &tinfo, 0);
+
+ }
+ return type;
+}
diff --git a/atspi/atspi-document.h b/atspi/atspi-document.h
new file mode 100644
index 0000000..f326d89
--- /dev/null
+++ b/atspi/atspi-document.h
@@ -0,0 +1,68 @@
+/*
+ * 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_DOCUMENT_H_
+#define _ATSPI_DOCUMENT_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+#define ATSPI_TYPE_DOCUMENT (atspi_document_get_type ())
+#define ATSPI_IS_DOCUMENT(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_DOCUMENT)
+#define ATSPI_DOCUMENT(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_DOCUMENT, AtspiDocument)
+#define ATSPI_DOCUMENT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_DOCUMENT, AtspiDocument))
+
+GType atspi_document_get_type ();
+
+struct _AtspiDocument
+{
+ GTypeInterface parent;
+};
+
+gchar * atspi_document_get_locale (AtspiDocument *obj, GError **error);
+
+#ifndef ATSPI_DISABLE_DEPRECATED
+gchar * atspi_document_get_attribute_value (AtspiDocument *obj, gchar *attribute, GError **error);
+#endif
+
+gchar * atspi_document_get_document_attribute_value (AtspiDocument *obj, gchar *attribute, GError **error);
+
+#ifndef ATSPI_DISABLE_DEPRECATED
+GHashTable * atspi_document_get_attributes (AtspiDocument *obj, GError **error);
+#endif
+
+GHashTable * atspi_document_get_document_attributes (AtspiDocument *obj, GError **error);
+
+gint atspi_document_get_page_count (AtspiDocument *obj, GError **error);
+gint atspi_document_get_current_page_number (AtspiDocument *obj, GError **error);
+
+
+G_END_DECLS
+
+#endif /* _ATSPI_DOCUMENT_H_ */
diff --git a/atspi/atspi-editabletext.c b/atspi/atspi-editabletext.c
new file mode 100644
index 0000000..58ac715
--- /dev/null
+++ b/atspi/atspi-editabletext.c
@@ -0,0 +1,258 @@
+/*
+ * 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"
+
+#if 0
+/* TODO: implement */
+/**
+ * atspi_editable_text_set_attributes:
+ * @obj: a pointer to the #AtspiEditableText object to modify.
+ * @attributes: a string indicating the attributes to apply to the range,
+ * delimited by ':'.
+ * @startOffset: a #gint indicating the start of the desired text range.
+ * @endOffset: a #gint indicating the first character past the desired range.
+ *
+ * Sets the attributes applied to a range of text from an #AtspiEditableText
+ * object, and the bounds of the range.
+ *
+ * Returns: #TRUE if the operation was successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_editable_text_set_attributes (AtspiEditableText *obj,
+ const char *attributes,
+ gint start_pos,
+ gint end_pos,
+ GError **error
+{
+ dbus_int32_t d_start_pos = start_pos, d_end_pos = end_pos;
+ dbus_bool_t retval = FALSE;
+
+ cspi_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_editable_text, "SetAttributes", error, "sii=>b", attributes, d_start_pos, d_end_pos, &retval);
+
+ return retval;
+}
+#endif
+
+/**
+ * atspi_editable_text_set_text_contents:
+ * @obj: a pointer to the #AtspiEditableText object to modify.
+ * @new_contents: a character string, encoded in UTF-8, which is to
+ * become the new text contents of the #AtspiEditableText object.
+ *
+ * Replace the entire text contents of an #AtspiEditableText object.
+ *
+ * Returns: #TRUE if the operation was successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_editable_text_set_text_contents (AtspiEditableText *obj,
+ const gchar *new_contents,
+ GError **error)
+{
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_editable_text, "SetTextContents", error, "s=>b", new_contents, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_editable_text_insert_text:
+ * @obj: a pointer to the #AtspiEditableText object to modify.
+ * @position: a #gint indicating the character offset at which to insert
+ * the new text.
+ * @text: a string representing the text to insert, in UTF-8 encoding.
+ * @length: the number of characters of text to insert. If the character
+ * count of text is less than or equal to length, the entire contents
+ * of text will be inserted.
+ *
+ * Inserts text into an #AtspiEditableText object.
+ * As with all character offsets, the specified @position may not be the
+ * same as the resulting byte offset, since the text is in a
+ * variable-width encoding.
+ *
+ * Returns: #TRUE if the operation was successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_editable_text_insert_text (AtspiEditableText *obj,
+ gint position,
+ const gchar *text,
+ gint length,
+ GError **error)
+{
+ dbus_int32_t d_position = position, d_length = length;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_editable_text, "InsertText", error, "isi=>b", d_position, text, d_length, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_editable_text_copy_text:
+ * @obj: a pointer to the #AtspiEditableText object to modify.
+ * @start_pos: a #gint indicating the starting character offset
+ * of the text to copy.
+ * @end_pos: a #gint indicating the offset of the first character
+ * past the end of the text section to be copied.
+ *
+ * Copies text from an #AtspiEditableText object into the system clipboard.
+ *
+ * see: #atspi_editable_text_paste_text
+ *
+ * Returns: #TRUE if the operation was successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_editable_text_copy_text (AtspiEditableText *obj,
+ gint start_pos,
+ gint end_pos,
+ GError **error)
+{
+ dbus_int32_t d_start_pos = start_pos, d_end_pos = end_pos;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_editable_text, "CopyText", error, "ii", d_start_pos, d_end_pos);
+
+ return TRUE;
+}
+
+/**
+ * atspi_editable_text_cut_text:
+ * @obj: a pointer to the #AtspiEditableText object to modify.
+ * @start_pos: a #gint indicating the starting character offset
+ * of the text to cut.
+ * @end_pos: a #gint indicating the offset of the first character
+ * past the end of the text section to be cut.
+ *
+ * Deletes text from an #AtspiEditableText object, copying the
+ * excised portion into the system clipboard.
+ *
+ * see: #atspi_editable_text_paste_text
+ *
+ * Returns: #TRUE if operation was successful, #FALSE otherwise.
+ **/
+gboolean
+atspi_editable_text_cut_text (AtspiEditableText *obj,
+ gint start_pos,
+ gint end_pos,
+ GError **error)
+{
+ dbus_int32_t d_start_pos = start_pos, d_end_pos = end_pos;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_editable_text, "CutText", error, "ii=>b", d_start_pos, d_end_pos, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_editable_text_delete_text:
+ * @obj: a pointer to the #AtspiEditableText object to modify.
+ * @start_pos: a #gint indicating the starting character offset
+ * of the text to delete.
+ * @end_pos: a #gint indicating the offset of the first character
+ * past the end of the text section to be deleted.
+ *
+ * Deletes text from an #AtspiEditableText object, without copying the
+ * excised portion into the system clipboard.
+ *
+ * see: #atspi_editable_text_cut_text
+ *
+ * Returns: #TRUE if the operation was successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_editable_text_delete_text (AtspiEditableText *obj,
+ gint start_pos,
+ gint end_pos,
+ GError **error)
+{
+ dbus_int32_t d_start_pos = start_pos, d_end_pos = end_pos;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_editable_text, "DeleteText", error, "ii=>b", d_start_pos, d_end_pos, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_editable_text_paste_text:
+ * @obj: a pointer to the #AtspiEditableText object to modify.
+ * @position: a #gint indicating the character offset at which to insert
+ * the new text.
+ *
+ * Inserts text from the system clipboard into an #AtspiEditableText object.
+ * As with all character offsets, the specified @position may not be the
+ * same as the resulting byte offset, since the text is in a
+ * variable-width encoding.
+ *
+ * Returns: #TRUE if the operation was successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_editable_text_paste_text (AtspiEditableText *obj,
+ gint position,
+ GError **error)
+{
+ dbus_int32_t d_position = position;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_editable_text, "PasteText", error, "i=>b", d_position, &retval);
+
+ return retval;
+}
+
+static void
+atspi_editable_text_base_init (AtspiEditableText *klass)
+{
+}
+
+GType
+atspi_editable_text_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (AtspiEditableText),
+ (GBaseInitFunc) atspi_editable_text_base_init,
+ (GBaseFinalizeFunc) NULL,
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE, "AtspiEditableText", &tinfo, 0);
+
+ }
+ return type;
+}
diff --git a/atspi/atspi-editabletext.h b/atspi/atspi-editabletext.h
new file mode 100644
index 0000000..59b2331
--- /dev/null
+++ b/atspi/atspi-editabletext.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_EDITABLE_TEXT_H_
+#define _ATSPI_EDITABLE_TEXT_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+#define ATSPI_TYPE_EDITABLE_TEXT (atspi_editable_text_get_type ())
+#define ATSPI_IS_EDITABLE_TEXT(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_EDITABLE_TEXT)
+#define ATSPI_EDITABLE_TEXT(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_EDITABLE_TEXT, AtspiEditableText)
+#define ATSPI_EDITABLE_TEXT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_EDITABLE_TEXT, AtspiEditableText))
+
+GType atspi_editable_text_get_type ();
+
+struct _AtspiEditableText
+{
+ GTypeInterface parent;
+};
+
+#if 0
+gboolean atspi_editable_text_set_attributes (AtspiEditableText *obj, const char *attributes, gint start_pos, gint end_pos, GError **error)
+#endif
+
+gboolean atspi_editable_text_set_text_contents (AtspiEditableText *obj, const gchar *new_contents, GError **error);
+
+gboolean atspi_editable_text_insert_text (AtspiEditableText *obj, gint position, const gchar *text, gint length, GError **error);
+
+gboolean atspi_editable_text_copy_text (AtspiEditableText *obj, gint start_pos, gint end_pos, GError **error);
+
+gboolean atspi_editable_text_cut_text (AtspiEditableText *obj, gint start_pos, gint end_pos, GError **error);
+
+gboolean atspi_editable_text_delete_text (AtspiEditableText *obj, gint start_pos, gint end_pos, GError **error);
+
+gboolean atspi_editable_text_paste_text (AtspiEditableText *obj, gint position, GError **error);
+
+G_END_DECLS
+
+#endif /* _ATSPI_EDITABLE_TEXT_H_ */
diff --git a/atspi/atspi-enum-types.c.template b/atspi/atspi-enum-types.c.template
new file mode 100644
index 0000000..cd92f99
--- /dev/null
+++ b/atspi/atspi-enum-types.c.template
@@ -0,0 +1,39 @@
+/*** BEGIN file-header ***/
+#include "atspi-enum-types.h"
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+/* enumerations from "@filename@" */
+#include "@filename@"
+
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType
+@enum_name@_get_type (void)
+{
+ static GType the_type = 0;
+
+ if (the_type == 0)
+ {
+ static const G@Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ { @VALUENAME@,
+ "@VALUENAME@",
+ "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL }
+ };
+ the_type = g_@type@_register_static (
+ g_intern_static_string ("@EnumName@"),
+ values);
+ }
+ return the_type;
+}
+
+/*** END value-tail ***/
diff --git a/atspi/atspi-enum-types.h.template b/atspi/atspi-enum-types.h.template
new file mode 100644
index 0000000..bd297b5
--- /dev/null
+++ b/atspi/atspi-enum-types.h.template
@@ -0,0 +1,27 @@
+/*** BEGIN file-header ***/
+#ifndef __ATSPI_ENUM_TYPES_H__
+#define __ATSPI_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+/* Enumerations from "@filename@" */
+
+/*** END file-production ***/
+
+/*** BEGIN enumeration-production ***/
+#define ATSPI_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
+GType @enum_name@_get_type (void) G_GNUC_CONST;
+
+/*** END enumeration-production ***/
+
+/*** BEGIN file-tail ***/
+G_END_DECLS
+
+#endif /* __ATSPI_ENUM_TYPES_H__ */
+/*** END file-tail ***/
+
diff --git a/atspi/atspi-event-listener-private.h b/atspi/atspi-event-listener-private.h
new file mode 100644
index 0000000..260db74
--- /dev/null
+++ b/atspi/atspi-event-listener-private.h
@@ -0,0 +1,46 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_LISTENER_PRIVATE_H_
+#define _ATSPI_EVENT_LISTENER_PRIVATE_H_
+
+#include "atspi-event-listener.h"
+
+#include "dbus/dbus.h"
+
+G_BEGIN_DECLS
+
+DBusHandlerResult _atspi_dbus_handle_Event (DBusConnection *bus, DBusMessage *message, void *data);
+
+void _atspi_send_event (AtspiEvent *e);
+
+DBusHandlerResult _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data);
+
+void
+_atspi_reregister_event_listeners ();
+
+G_END_DECLS
+
+#endif /* _ATSPI_EVENT_LISTENER_H_ */
diff --git a/atspi/atspi-event-listener.c b/atspi/atspi-event-listener.c
new file mode 100644
index 0000000..95af3a0
--- /dev/null
+++ b/atspi/atspi-event-listener.c
@@ -0,0 +1,1079 @@
+/*
+ * 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.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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"
+#include "atspi-accessible-private.h"
+#include <string.h>
+#include <ctype.h>
+
+typedef struct
+{
+ AtspiEventListenerCB callback;
+ void *user_data;
+ GDestroyNotify callback_destroyed;
+ char *event_type;
+ char *category;
+ char *name;
+ char *detail;
+ GArray *properties;
+} EventListenerEntry;
+
+G_DEFINE_TYPE (AtspiEventListener, atspi_event_listener, G_TYPE_OBJECT)
+
+void
+atspi_event_listener_init (AtspiEventListener *listener)
+{
+}
+
+void
+atspi_event_listener_class_init (AtspiEventListenerClass *klass)
+{
+}
+
+static void
+remove_datum (AtspiEvent *event, void *user_data)
+{
+ AtspiEventListenerSimpleCB cb = user_data;
+ cb (event);
+}
+
+typedef struct
+{
+ gpointer callback;
+ GDestroyNotify callback_destroyed;
+ gint ref_count;
+} CallbackInfo;
+static GHashTable *callbacks;
+
+void
+callback_ref (void *callback, GDestroyNotify callback_destroyed)
+{
+ CallbackInfo *info;
+
+ if (!callbacks)
+ {
+ callbacks = g_hash_table_new (g_direct_hash, g_direct_equal);
+ if (!callbacks)
+ return;
+ }
+
+ info = g_hash_table_lookup (callbacks, callback);
+ if (!info)
+ {
+ info = g_new (CallbackInfo, 1);
+ info->callback = callback;
+ info->callback_destroyed = callback_destroyed;
+ info->ref_count = 1;
+ g_hash_table_insert (callbacks, callback, info);
+ }
+ else
+ info->ref_count++;
+}
+
+void
+callback_unref (gpointer callback)
+{
+ CallbackInfo *info;
+
+ if (!callbacks)
+ return;
+ info = g_hash_table_lookup (callbacks, callback);
+ if (!info)
+ {
+ g_warning ("Atspi: Dereferencing invalid callback %p\n", callback);
+ return;
+ }
+ info->ref_count--;
+ if (info->ref_count == 0)
+ {
+#if 0
+ /* TODO: Figure out why this seg faults from Python */
+ if (info->callback_destroyed)
+ (*info->callback_destroyed) (info->callback);
+#endif
+ g_free (info);
+ g_hash_table_remove (callbacks, callback);
+ }
+}
+
+/**
+ * atspi_event_listener_new:
+ * @callback: (scope notified): An #AtspiEventListenerCB to be called
+ * when an event is fired.
+ * @user_data: (closure): data to pass to the callback.
+ * @callback_destroyed: A #GDestroyNotify called when the listener is freed
+ * and data associated with the callback should be freed. Can be NULL.
+ *
+ * Creates a new #AtspiEventListener associated with a specified @callback.
+ *
+ * Returns: (transfer full): A new #AtspiEventListener.
+ */
+AtspiEventListener *
+atspi_event_listener_new (AtspiEventListenerCB callback,
+ gpointer user_data,
+ GDestroyNotify callback_destroyed)
+{
+ AtspiEventListener *listener = g_object_new (ATSPI_TYPE_EVENT_LISTENER, NULL);
+ listener->callback = callback;
+ callback_ref (callback, callback_destroyed);
+ listener->user_data = user_data;
+ listener->cb_destroyed = callback_destroyed;
+ return listener;
+}
+
+/**
+ * atspi_event_listener_new_simple: (skip)
+ * @callback: (scope notified): An #AtspiEventListenerSimpleCB to be called
+ * when an event is fired.
+ * @callback_destroyed: A #GDestroyNotify called when the listener is freed
+ * and data associated with the callback should be freed. Can be NULL.
+ *
+ * Creates a new #AtspiEventListener associated with a specified @callback.
+ * Returns: (transfer full): A new #AtspiEventListener.
+ **/
+AtspiEventListener *
+atspi_event_listener_new_simple (AtspiEventListenerSimpleCB callback,
+ GDestroyNotify callback_destroyed)
+{
+ AtspiEventListener *listener = g_object_new (ATSPI_TYPE_EVENT_LISTENER, NULL);
+ listener->callback = remove_datum;
+ callback_ref (remove_datum, callback_destroyed);
+ listener->user_data = callback;
+ listener->cb_destroyed = callback_destroyed;
+ return listener;
+}
+
+static GList *event_listeners = NULL;
+
+static gchar *
+convert_name_from_dbus (const char *name, gboolean path_hack)
+{
+ gchar *ret = g_malloc (g_utf8_strlen (name, -1) * 2 + 1);
+ const char *p = name;
+ gchar *q = ret;
+
+ if (!ret)
+ return NULL;
+
+ while (*p)
+ {
+ if (isupper (*p))
+ {
+ if (q > ret)
+ *q++ = '-';
+ *q++ = tolower (*p++);
+ }
+ else if (path_hack && *p == '/')
+ {
+ *q++ = ':';
+ p++;
+ }
+ else
+ *q++ = *p++;
+ }
+ *q = '\0';
+ return ret;
+}
+
+static void
+cache_process_children_changed (AtspiEvent *event)
+{
+ AtspiAccessible *child;
+
+ if (!G_VALUE_HOLDS (&event->any_data, ATSPI_TYPE_ACCESSIBLE) ||
+ !(event->source->cached_properties & ATSPI_CACHE_CHILDREN) ||
+ atspi_state_set_contains (event->source->states, ATSPI_STATE_MANAGES_DESCENDANTS))
+ return;
+
+ child = g_value_get_object (&event->any_data);
+
+ if (!strncmp (event->type, "object:children-changed:add", 27))
+ {
+ if (g_list_find (event->source->children, child))
+ return;
+ event->source->children = g_list_insert (event->source->children,
+ g_object_ref (child),
+ event->detail1);
+ }
+ else if (g_list_find (event->source->children, child))
+ {
+ event->source->children = g_list_remove (event->source->children, child);
+ if (child == child->parent.app->root)
+ g_object_run_dispose (G_OBJECT (child->parent.app));
+ g_object_unref (child);
+ }
+}
+
+static void
+cache_process_property_change (AtspiEvent *event)
+{
+ if (!strcmp (event->type, "object:property-change:accessible-parent"))
+ {
+ if (event->source->accessible_parent)
+ g_object_unref (event->source->accessible_parent);
+ if (G_VALUE_HOLDS (&event->any_data, ATSPI_TYPE_ACCESSIBLE))
+ {
+ event->source->accessible_parent = g_value_dup_object (&event->any_data);
+ _atspi_accessible_add_cache (event->source, ATSPI_CACHE_PARENT);
+ }
+ else
+ {
+ event->source->accessible_parent = NULL;
+ event->source->cached_properties &= ~ATSPI_CACHE_PARENT;
+ }
+ }
+ else if (!strcmp (event->type, "object:property-change:accessible-name"))
+ {
+ if (event->source->name)
+ g_free (event->source->name);
+ if (G_VALUE_HOLDS_STRING (&event->any_data))
+ {
+ event->source->name = g_value_dup_string (&event->any_data);
+ _atspi_accessible_add_cache (event->source, ATSPI_CACHE_NAME);
+ }
+ else
+ {
+ event->source->name = NULL;
+ event->source->cached_properties &= ~ATSPI_CACHE_NAME;
+ }
+ }
+ else if (!strcmp (event->type, "object:property-change:accessible-description"))
+ {
+ if (event->source->description)
+ g_free (event->source->description);
+ if (G_VALUE_HOLDS_STRING (&event->any_data))
+ {
+ event->source->description = g_value_dup_string (&event->any_data);
+ _atspi_accessible_add_cache (event->source, ATSPI_CACHE_DESCRIPTION);
+ }
+ else
+ {
+ event->source->description = NULL;
+ event->source->cached_properties &= ~ATSPI_CACHE_DESCRIPTION;
+ }
+ }
+ else if (!strcmp (event->type, "object:property-change:accessible-role"))
+ {
+ if (G_VALUE_HOLDS_INT (&event->any_data))
+ {
+ event->source->role = g_value_get_int (&event->any_data);
+ _atspi_accessible_add_cache (event->source, ATSPI_CACHE_ROLE);
+ }
+ else
+ {
+ event->source->cached_properties &= ~ATSPI_CACHE_ROLE;
+ }
+ }
+}
+
+static void
+cache_process_state_changed (AtspiEvent *event)
+{
+ if (event->source->states)
+ atspi_state_set_set_by_name (event->source->states, event->type + 21,
+ event->detail1);
+}
+
+static dbus_bool_t
+demarshal_rect (DBusMessageIter *iter, AtspiRect *rect)
+{
+ dbus_int32_t x, y, width, height;
+ DBusMessageIter iter_struct;
+
+ dbus_message_iter_recurse (iter, &iter_struct);
+ if (dbus_message_iter_get_arg_type (&iter_struct) != DBUS_TYPE_INT32) return FALSE;
+ dbus_message_iter_get_basic (&iter_struct, &x);
+ dbus_message_iter_next (&iter_struct);
+ if (dbus_message_iter_get_arg_type (&iter_struct) != DBUS_TYPE_INT32) return FALSE;
+ dbus_message_iter_get_basic (&iter_struct, &y);
+ dbus_message_iter_next (&iter_struct);
+ if (dbus_message_iter_get_arg_type (&iter_struct) != DBUS_TYPE_INT32) return FALSE;
+ dbus_message_iter_get_basic (&iter_struct, &width);
+ dbus_message_iter_next (&iter_struct);
+ if (dbus_message_iter_get_arg_type (&iter_struct) != DBUS_TYPE_INT32) return FALSE;
+ dbus_message_iter_get_basic (&iter_struct, &height);
+ rect->x = x;
+ rect->y = y;
+ rect->width = width;
+ rect->height = height;
+ return TRUE;
+}
+
+static gchar *
+strdup_and_adjust_for_dbus (const char *s)
+{
+ gchar *d = g_strdup (s);
+ gchar *p;
+ int parts = 0;
+
+ if (!d)
+ return NULL;
+
+ for (p = d; *p; p++)
+ {
+ if (*p == '-')
+ {
+ memmove (p, p + 1, g_utf8_strlen (p, -1));
+ *p = toupper (*p);
+ }
+ else if (*p == ':')
+ {
+ parts++;
+ if (parts == 2)
+ break;
+ p [1] = toupper (p [1]);
+ }
+ }
+
+ d [0] = toupper (d [0]);
+ return d;
+}
+
+static gboolean
+convert_event_type_to_dbus (const char *eventType, char **categoryp, char **namep, char **detailp, GPtrArray **matchrule_array)
+{
+ gchar *tmp = strdup_and_adjust_for_dbus (eventType);
+ char *category = NULL, *name = NULL, *detail = NULL;
+ char *saveptr = NULL;
+
+ if (tmp == NULL) return FALSE;
+ category = strtok_r (tmp, ":", &saveptr);
+ if (category) category = g_strdup (category);
+ name = strtok_r (NULL, ":", &saveptr);
+ if (name)
+ {
+ name = g_strdup (name);
+ detail = strtok_r (NULL, ":", &saveptr);
+ if (detail) detail = g_strdup (detail);
+ }
+ if (matchrule_array)
+ {
+ gchar *matchrule;
+ matchrule = g_strdup_printf ("type='signal',interface='org.a11y.atspi.Event.%s'", category);
+ if (name && name [0])
+ {
+ gchar *new_str = g_strconcat (matchrule, ",member='", name, "'", NULL);
+ g_free (matchrule);
+ matchrule = new_str;
+ }
+ (*matchrule_array) = g_ptr_array_new ();
+ if (detail && detail [0])
+ {
+ gchar *new_str = g_strconcat (matchrule, ",arg0='", detail, "'", NULL);
+ g_ptr_array_add (*matchrule_array, new_str);
+ new_str = g_strconcat (matchrule, ",arg0path='", detail, "/'", NULL);
+ g_ptr_array_add (*matchrule_array, new_str);
+ g_free (matchrule);
+ }
+ else
+ g_ptr_array_add (*matchrule_array, matchrule);
+ }
+ if (categoryp) *categoryp = category;
+ else g_free (category);
+ if (namep) *namep = name;
+ else if (name) g_free (name);
+ if (detailp) *detailp = detail;
+ else if (detail) g_free (detail);
+ g_free (tmp);
+ return TRUE;
+}
+
+static void
+listener_entry_free (EventListenerEntry *e)
+{
+ gpointer callback = (e->callback == remove_datum ? (gpointer)e->user_data : (gpointer)e->callback);
+ g_free (e->event_type);
+ g_free (e->category);
+ g_free (e->name);
+ if (e->detail) g_free (e->detail);
+ callback_unref (callback);
+ g_free (e);
+}
+
+/**
+ * atspi_event_listener_register:
+ * @listener: The #AtspiEventListener to register against an event type.
+ * @event_type: a character string indicating the type of events for which
+ * notification is requested. Format is
+ * EventClass:major_type:minor_type:detail
+ * where all subfields other than EventClass are optional.
+ * EventClasses include "object", "window", "mouse",
+ * and toolkit events (e.g. "Gtk", "AWT").
+ * Examples: "focus:", "Gtk:GtkWidget:button_press_event".
+ *
+ * Adds an in-process callback function to an existing #AtspiEventListener.
+ *
+ * Legal object event types:
+ *
+ * (property change events)
+ *
+ * object:property-change
+ * object:property-change:accessible-name
+ * object:property-change:accessible-description
+ * object:property-change:accessible-parent
+ * object:property-change:accessible-value
+ * object:property-change:accessible-role
+ * object:property-change:accessible-table-caption
+ * object:property-change:accessible-table-column-description
+ * object:property-change:accessible-table-column-header
+ * object:property-change:accessible-table-row-description
+ * object:property-change:accessible-table-row-header
+ * object:property-change:accessible-table-summary
+ *
+ * (other object events)
+ *
+ * object:state-changed
+ * object:children-changed
+ * object:visible-data-changed
+ * object:selection-changed
+ * object:text-selection-changed
+ * object:text-changed
+ * object:text-caret-moved
+ * object:row-inserted
+ * object:row-reordered
+ * object:row-deleted
+ * object:column-inserted
+ * object:column-reordered
+ * object:column-deleted
+ * object:model-changed
+ * object:active-descendant-changed
+ *
+ * (window events)
+ *
+ * window:minimize
+ * window:maximize
+ * window:restore
+ * window:close
+ * window:create
+ * window:reparent
+ * window:desktop-create
+ * window:desktop-destroy
+ * window:activate
+ * window:deactivate
+ * window:raise
+ * window:lower
+ * window:move
+ * window:resize
+ * window:shade
+ * window:unshade
+ * window:restyle
+ *
+ * (other events)
+ *
+ * focus:
+ * mouse:abs
+ * mouse:rel
+ * mouse:b1p
+ * mouse:b1r
+ * mouse:b2p
+ * mouse:b2r
+ * mouse:b3p
+ * mouse:b3r
+ *
+ * NOTE: this character string may be UTF-8, but should not contain byte
+ * value 56
+ * (ascii ':'), except as a delimiter, since non-UTF-8 string
+ * delimiting functions are used internally.
+ * In general, listening to
+ * toolkit-specific events is not recommended.
+ *
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_event_listener_register (AtspiEventListener *listener,
+ const gchar *event_type,
+ GError **error)
+{
+ /* TODO: Keep track of which events have been registered, so that we
+ * deregister all of them when the event listener is destroyed */
+
+ return atspi_event_listener_register_from_callback (listener->callback,
+ listener->user_data,
+ listener->cb_destroyed,
+ event_type, error);
+}
+
+/**
+ * atspi_event_listener_register_full:
+ * @listener: The #AtspiEventListener to register against an event type.
+ * @event_type: a character string indicating the type of events for which
+ * notification is requested. See #atspi_event_listener_register
+ * for a description of the format and legal event types.
+* @properties: (element-type gchar*) (transfer none) (allow-none): a list of
+ * properties that should be sent along with the event. The
+ * properties are valued for the duration of the event callback.k
+ * TODO: Document.
+ *
+ * Adds an in-process callback function to an existing #AtspiEventListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_event_listener_register_full (AtspiEventListener *listener,
+ const gchar *event_type,
+ GArray *properties,
+ GError **error)
+{
+ /* TODO: Keep track of which events have been registered, so that we
+ * deregister all of them when the event listener is destroyed */
+
+ return atspi_event_listener_register_from_callback_full (listener->callback,
+ listener->user_data,
+ listener->cb_destroyed,
+ event_type,
+ properties,
+ error);
+}
+
+static gboolean
+notify_event_registered (EventListenerEntry *e)
+{
+
+ if (e->properties)
+ dbind_method_call_reentrant (_atspi_bus (), atspi_bus_registry,
+ atspi_path_registry,
+ atspi_interface_registry,
+ "RegisterEvent",
+ NULL, "sas", e->event_type,
+ e->properties);
+ else
+ dbind_method_call_reentrant (_atspi_bus (), atspi_bus_registry,
+ atspi_path_registry,
+ atspi_interface_registry,
+ "RegisterEvent",
+ NULL, "s", e->event_type);
+
+ return TRUE;
+}
+
+/**
+ * atspi_event_listener_register_from_callback:
+ * @callback: (scope notified): the #AtspiEventListenerCB to be registered
+ * against an event type.
+ * @user_data: (closure): User data to be passed to the callback.
+ * @callback_destroyed: A #GDestroyNotify called when the callback is destroyed.
+ * @event_type: a character string indicating the type of events for which
+ * notification is requested. See #atspi_event_listener_register
+ * for a description of the format.
+ *
+ * Registers an #AtspiEventListenerCB against an @event_type.
+ *
+ * Returns: #TRUE if successfull, otherwise #FALSE.
+ *
+ **/
+gboolean
+atspi_event_listener_register_from_callback (AtspiEventListenerCB callback,
+ void *user_data,
+ GDestroyNotify callback_destroyed,
+ const gchar *event_type,
+ GError **error)
+{
+ return atspi_event_listener_register_from_callback_full (callback,
+ user_data,
+ callback_destroyed,
+ event_type, NULL,
+ error);
+}
+
+static GArray *
+copy_event_properties (GArray *src)
+{
+ gint i;
+
+ GArray *dst = g_array_new (FALSE, FALSE, sizeof (char *));
+
+ if (!src)
+ return dst;
+ for (i = 0; i < src->len; i++)
+ {
+ gchar *dup = g_strdup (g_array_index (src, char *, i));
+ g_array_append_val (dst, dup);
+ }
+ return dst;
+}
+
+gboolean
+atspi_event_listener_register_from_callback_full (AtspiEventListenerCB callback,
+ void *user_data,
+ GDestroyNotify callback_destroyed,
+ const gchar *event_type,
+ GArray *properties,
+ GError **error)
+{
+ EventListenerEntry *e;
+ DBusError d_error;
+ GPtrArray *matchrule_array;
+ gint i;
+
+ if (!callback)
+ {
+ return FALSE;
+ }
+
+ if (!event_type)
+ {
+ g_warning ("called atspi_event_listener_register_from_callback with a NULL event_type");
+ return FALSE;
+ }
+
+ e = g_new (EventListenerEntry, 1);
+ e->event_type = g_strdup (event_type);
+ e->callback = callback;
+ e->user_data = user_data;
+ e->callback_destroyed = callback_destroyed;
+ callback_ref (callback == remove_datum ? (gpointer)user_data : (gpointer)callback,
+ callback_destroyed);
+ if (!convert_event_type_to_dbus (event_type, &e->category, &e->name, &e->detail, &matchrule_array))
+ {
+ g_free (e);
+ return FALSE;
+ }
+ e->properties = copy_event_properties (properties);
+ event_listeners = g_list_prepend (event_listeners, e);
+ for (i = 0; i < matchrule_array->len; i++)
+ {
+ char *matchrule = g_ptr_array_index (matchrule_array, i);
+ dbus_error_init (&d_error);
+ dbus_bus_add_match (_atspi_bus(), matchrule, &d_error);
+ if (dbus_error_is_set (&d_error))
+ {
+ g_warning ("Atspi: Adding match: %s", d_error.message);
+ dbus_error_free (&d_error);
+ /* TODO: Set error */
+ }
+
+ g_free (matchrule);
+ }
+ g_ptr_array_free (matchrule_array, TRUE);
+
+ notify_event_registered (e);
+ return TRUE;
+}
+
+void
+_atspi_reregister_event_listeners ()
+{
+ GList *l;
+ EventListenerEntry *e;
+
+ for (l = event_listeners; l; l = l->next)
+ {
+ e = l->data;
+ notify_event_registered (e);
+ }
+}
+
+/**
+ * atspi_event_listener_register_no_data: (skip)
+ * @callback: (scope notified): the #AtspiEventListenerSimpleCB to be
+ * registered against an event type.
+ * @callback_destroyed: A #GDestroyNotify called when the callback is destroyed.
+ * @event_type: a character string indicating the type of events for which
+ * notification is requested. Format is
+ * EventClass:major_type:minor_type:detail
+ * where all subfields other than EventClass are optional.
+ * EventClasses include "object", "window", "mouse",
+ * and toolkit events (e.g. "Gtk", "AWT").
+ * Examples: "focus:", "Gtk:GtkWidget:button_press_event".
+ *
+ * Registers an #AtspiEventListenetSimpleCB. The method is similar to
+ * #atspi_event_listener_register, but @callback takes no user_data.
+ *
+ * Returns: #TRUE if successfull, otherwise #FALSE.
+ **/
+gboolean
+atspi_event_listener_register_no_data (AtspiEventListenerSimpleCB callback,
+ GDestroyNotify callback_destroyed,
+ const gchar *event_type,
+ GError **error)
+{
+ return atspi_event_listener_register_from_callback (remove_datum, callback,
+ callback_destroyed,
+ event_type, error);
+}
+
+static gboolean
+is_superset (const gchar *super, const gchar *sub)
+{
+ if (!super || !super [0])
+ return TRUE;
+ return (strcmp (super, sub) == 0);
+}
+
+/**
+ * atspi_event_listener_deregister:
+ * @listener: The #AtspiEventListener to deregister.
+ * @event_type: a string specifying the event type for which this
+ * listener is to be deregistered.
+ *
+ * Deregisters an #AtspiEventListener from the registry, for a specific
+ * event type.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_event_listener_deregister (AtspiEventListener *listener,
+ const gchar *event_type,
+ GError **error)
+{
+ return atspi_event_listener_deregister_from_callback (listener->callback,
+ listener->user_data,
+ event_type, error);
+}
+
+/**
+ * atspi_event_listener_deregister_from_callback:
+ * @callback: (scope call): the #AtspiEventListenerCB registered against an
+ * event type.
+ * @user_data: (closure): User data that was passed in for this callback.
+ * @event_type: a string specifying the event type for which this
+ * listener is to be deregistered.
+ *
+ * Deregisters an #AtspiEventListenerCB from the registry, for a specific
+ * event type.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_event_listener_deregister_from_callback (AtspiEventListenerCB callback,
+ void *user_data,
+ const gchar *event_type,
+ GError **error)
+{
+ char *category, *name, *detail;
+ GPtrArray *matchrule_array;
+ gint i;
+ GList *l;
+
+ if (!convert_event_type_to_dbus (event_type, &category, &name, &detail, &matchrule_array))
+ {
+ return FALSE;
+ }
+ if (!callback)
+ {
+ return FALSE;
+ }
+
+ for (l = event_listeners; l;)
+ {
+ EventListenerEntry *e = l->data;
+ if (e->callback == callback &&
+ e->user_data == user_data &&
+ is_superset (category, e->category) &&
+ is_superset (name, e->name) &&
+ is_superset (detail, e->detail))
+ {
+ gboolean need_replace;
+ DBusMessage *message, *reply;
+ need_replace = (l == event_listeners);
+ l = g_list_remove (l, e);
+ if (need_replace)
+ event_listeners = l;
+ for (i = 0; i < matchrule_array->len; i++)
+ {
+ char *matchrule = g_ptr_array_index (matchrule_array, i);
+ dbus_bus_remove_match (_atspi_bus(), matchrule, NULL);
+ }
+ message = dbus_message_new_method_call (atspi_bus_registry,
+ atspi_path_registry,
+ atspi_interface_registry,
+ "DeregisterEvent");
+ if (!message)
+ return FALSE;
+ dbus_message_append_args (message, DBUS_TYPE_STRING, &event_type, DBUS_TYPE_INVALID);
+ reply = _atspi_dbus_send_with_reply_and_block (message, error);
+ if (reply)
+ dbus_message_unref (reply);
+
+ listener_entry_free (e);
+ }
+ else l = g_list_next (l);
+ }
+ g_free (category);
+ g_free (name);
+ if (detail) g_free (detail);
+ for (i = 0; i < matchrule_array->len; i++)
+ g_free (g_ptr_array_index (matchrule_array, i));
+ g_ptr_array_free (matchrule_array, TRUE);
+ return TRUE;
+}
+
+/**
+ * atspi_event_listener_deregister_no_data: (skip)
+ * @callback: (scope call): the #AtspiEventListenerSimpleCB registered against
+ * an event type.
+ * @event_type: a string specifying the event type for which this
+ * listener is to be deregistered.
+ *
+ * deregisters an #AtspiEventListenerSimpleCB from the registry, for a specific
+ * event type.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_event_listener_deregister_no_data (AtspiEventListenerSimpleCB callback,
+ const gchar *event_type,
+ GError **error)
+{
+ return atspi_event_listener_deregister_from_callback (remove_datum, callback,
+ event_type,
+ error);
+}
+
+static AtspiEvent *
+atspi_event_copy (AtspiEvent *src)
+{
+ AtspiEvent *dst = g_new0 (AtspiEvent, 1);
+ dst->type = g_strdup (src->type);
+ dst->source = g_object_ref (src->source);
+ dst->detail1 = src->detail1;
+ dst->detail2 = src->detail2;
+ g_value_init (&dst->any_data, G_VALUE_TYPE (&src->any_data));
+ g_value_copy (&src->any_data, &dst->any_data);
+ return dst;
+}
+
+static void
+atspi_event_free (AtspiEvent *event)
+{
+ g_object_unref (event->source);
+ g_free (event->type);
+ g_value_unset (&event->any_data);
+ g_free (event);
+}
+
+static gboolean
+detail_matches_listener (const char *event_detail, const char *listener_detail)
+{
+ if (!listener_detail)
+ return TRUE;
+
+ if (!event_detail)
+ return (listener_detail ? FALSE : TRUE);
+
+ return !(listener_detail [strcspn (listener_detail, ":")] == '\0'
+ ? strncmp (listener_detail, event_detail,
+ strcspn (event_detail, ":"))
+ : strcmp (listener_detail, event_detail));
+}
+
+void
+_atspi_send_event (AtspiEvent *e)
+{
+ char *category, *name, *detail;
+ GList *l;
+ GList *called_listeners = NULL;
+
+ /* Ensure that the value is set to avoid a Python exception */
+ /* TODO: Figure out how to do this without using a private field */
+ if (e->any_data.g_type == 0)
+ {
+ g_value_init (&e->any_data, G_TYPE_INT);
+ g_value_set_int (&e->any_data, 0);
+ }
+
+ if (!convert_event_type_to_dbus (e->type, &category, &name, &detail, NULL))
+ {
+ g_warning ("Atspi: Couldn't parse event: %s\n", e->type);
+ return;
+ }
+ for (l = event_listeners; l; l = g_list_next (l))
+ {
+ EventListenerEntry *entry = l->data;
+ if (!strcmp (category, entry->category) &&
+ (entry->name == NULL || !strcmp (name, entry->name)) &&
+ detail_matches_listener (detail, entry->detail))
+ {
+ GList *l2;
+ for (l2 = called_listeners; l2; l2 = l2->next)
+ {
+ EventListenerEntry *e2 = l2->data;
+ if (entry->callback == e2->callback && entry->user_data == e2->user_data)
+ break;
+ }
+ if (!l2)
+ {
+ entry->callback (atspi_event_copy (e), entry->user_data);
+ called_listeners = g_list_prepend (called_listeners, entry);
+ }
+ }
+ }
+ if (detail) g_free (detail);
+ g_free (name);
+ g_free (category);
+ g_list_free (called_listeners);
+}
+
+DBusHandlerResult
+_atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data)
+{
+ char *detail = NULL;
+ const char *category = dbus_message_get_interface (message);
+ const char *member = dbus_message_get_member (message);
+ const char *signature = dbus_message_get_signature (message);
+ gchar *name;
+ gchar *converted_type;
+ DBusMessageIter iter, iter_variant;
+ dbus_message_iter_init (message, &iter);
+ AtspiEvent e;
+ dbus_int32_t detail1, detail2;
+ char *p;
+ GHashTable *cache = NULL;
+
+ if (strcmp (signature, "siiv(so)") != 0 &&
+ strcmp (signature, "siiva{sv}") != 0)
+ {
+ g_warning ("Got invalid signature %s for signal %s from interface %s\n", signature, member, category);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ memset (&e, 0, sizeof (e));
+
+ if (!category)
+ {
+ // TODO: Error
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ category = g_utf8_strrchr (category, -1, '.');
+ if (category == NULL)
+ {
+ // TODO: Error
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ category++;
+
+ dbus_message_iter_get_basic (&iter, &detail);
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_get_basic (&iter, &detail1);
+ e.detail1 = detail1;
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_get_basic (&iter, &detail2);
+ e.detail2 = detail2;
+ dbus_message_iter_next (&iter);
+
+ converted_type = convert_name_from_dbus (category, FALSE);
+ name = convert_name_from_dbus (member, FALSE);
+ detail = convert_name_from_dbus (detail, TRUE);
+
+ if (strcasecmp (category, name) != 0)
+ {
+ p = g_strconcat (converted_type, ":", name, NULL);
+ g_free (converted_type);
+ converted_type = p;
+ }
+ else if (detail [0] == '\0')
+ {
+ p = g_strconcat (converted_type, ":", NULL);
+ g_free (converted_type);
+ converted_type = p;
+ }
+
+ if (detail[0] != '\0')
+ {
+ p = g_strconcat (converted_type, ":", detail, NULL);
+ g_free (converted_type);
+ converted_type = p;
+ }
+ e.type = converted_type;
+ e.source = _atspi_ref_accessible (dbus_message_get_sender(message), dbus_message_get_path(message));
+ if (e.source == NULL)
+ {
+ g_warning ("Got no valid source accessible for signal for signal %s from interface %s\n", member, category);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ dbus_message_iter_recurse (&iter, &iter_variant);
+ switch (dbus_message_iter_get_arg_type (&iter_variant))
+ {
+ case DBUS_TYPE_STRUCT:
+ {
+ AtspiRect rect;
+ if (demarshal_rect (&iter_variant, &rect))
+ {
+ g_value_init (&e.any_data, ATSPI_TYPE_RECT);
+ g_value_set_boxed (&e.any_data, &rect);
+ }
+ else
+ {
+ AtspiAccessible *accessible;
+ accessible = _atspi_dbus_return_accessible_from_iter (&iter_variant);
+ g_value_init (&e.any_data, ATSPI_TYPE_ACCESSIBLE);
+ g_value_set_instance (&e.any_data, accessible);
+ if (accessible)
+ g_object_unref (accessible); /* value now owns it */
+ }
+ break;
+ }
+ case DBUS_TYPE_STRING:
+ {
+ dbus_message_iter_get_basic (&iter_variant, &p);
+ g_value_init (&e.any_data, G_TYPE_STRING);
+ g_value_set_string (&e.any_data, p);
+ break;
+ }
+ default:
+ break;
+ }
+
+ dbus_message_iter_next (&iter);
+ if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY)
+ {
+ /* new form -- parse properties sent with event */
+ cache = _atspi_dbus_update_cache_from_dict (e.source, &iter);
+ }
+
+ if (!strncmp (e.type, "object:children-changed", 23))
+ {
+ cache_process_children_changed (&e);
+ }
+ else if (!strncmp (e.type, "object:property-change", 22))
+ {
+ cache_process_property_change (&e);
+ }
+ else if (!strncmp (e.type, "object:state-changed", 20))
+ {
+ cache_process_state_changed (&e);
+ }
+ else if (!strncmp (e.type, "focus", 5))
+ {
+ /* BGO#663992 - TODO: figure out the real problem */
+ e.source->cached_properties &= ~(ATSPI_CACHE_STATES);
+ }
+
+ _atspi_send_event (&e);
+
+ if (cache)
+ _atspi_accessible_unref_cache (e.source);
+
+ g_free (converted_type);
+ g_free (name);
+ g_free (detail);
+ g_object_unref (e.source);
+ g_value_unset (&e.any_data);
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+G_DEFINE_BOXED_TYPE (AtspiEvent, atspi_event, atspi_event_copy, atspi_event_free)
diff --git a/atspi/atspi-event-listener.h b/atspi/atspi-event-listener.h
new file mode 100644
index 0000000..ee52fac
--- /dev/null
+++ b/atspi/atspi-event-listener.h
@@ -0,0 +1,140 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_LISTENER_H_
+#define _ATSPI_EVENT_LISTENER_H_
+
+#include "glib-object.h"
+
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+GType atspi_event_get_type (void);
+
+/**
+ * AtspiEventListenerCB:
+ * @event: (transfer full): 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) (AtspiEvent *event,
+ void *user_data);
+
+/**
+ * AtspiEventListenerSimpleCB:
+ * @event: (transfer full): The event for which notification is sent.
+ *
+ * Like #AtspiEventlistenerCB, but with no user_data.
+ *
+ **/
+typedef void (*AtspiEventListenerSimpleCB) (const AtspiEvent *event);
+
+#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;
+ AtspiEventListenerCB callback;
+ void *user_data;
+ GDestroyNotify cb_destroyed;
+};
+
+typedef struct _AtspiEventListenerClass AtspiEventListenerClass;
+struct _AtspiEventListenerClass
+{
+ GObjectClass parent_class;
+};
+
+GType atspi_event_listener_get_type (void);
+
+AtspiEventListener *
+atspi_event_listener_new (AtspiEventListenerCB callback,
+ gpointer user_data,
+ GDestroyNotify callback_destroyed);
+
+AtspiEventListener *
+atspi_event_listener_new_simple (AtspiEventListenerSimpleCB callback,
+ GDestroyNotify callback_destroyed);
+
+gboolean
+atspi_event_listener_register (AtspiEventListener *listener,
+ const gchar *event_type,
+ GError **error);
+
+gboolean
+atspi_event_listener_register_full (AtspiEventListener *listener,
+ const gchar *event_type,
+ GArray *properties,
+ GError **error);
+
+gboolean
+atspi_event_listener_register_from_callback (AtspiEventListenerCB callback,
+ void *user_data,
+ GDestroyNotify callback_destroyed,
+ const gchar *event_type,
+ GError **error);
+
+gboolean
+atspi_event_listener_register_from_callback_full (AtspiEventListenerCB callback,
+ void *user_data,
+ GDestroyNotify callback_destroyed,
+ const gchar *event_type,
+ GArray *properties,
+ GError **error);
+
+gboolean
+atspi_event_listener_register_no_data (AtspiEventListenerSimpleCB callback,
+ GDestroyNotify callback_destroyed,
+ const gchar *event_type,
+ GError **error);
+
+gboolean
+atspi_event_listener_deregister (AtspiEventListener *listener,
+ const gchar *event_type,
+ GError **error);
+
+gboolean
+atspi_event_listener_deregister_from_callback (AtspiEventListenerCB callback,
+ void *user_data,
+ const gchar *event_type,
+ GError **error);
+
+gboolean
+atspi_event_listener_deregister_no_data (AtspiEventListenerSimpleCB callback,
+ const gchar *event_type,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* _ATSPI_EVENT_LISTENER_H_ */
diff --git a/atspi/atspi-gmain.c b/atspi/atspi-gmain.c
new file mode 100644
index 0000000..3ab985b
--- /dev/null
+++ b/atspi/atspi-gmain.c
@@ -0,0 +1,665 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-gmain.c GLib main loop integration
+ *
+ * Copyright (C) 2002, 2003 CodeFactory AB
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * This file is based on dbus-gmain.c from dbus-glib with functions renamed
+ * and unnecessary code removed.
+ */
+
+#include <config.h>
+#include <dbus/dbus.h>
+#include "glib.h"
+#include <string.h>
+
+#include <libintl.h>
+#define _(x) dgettext (GETTEXT_PACKAGE, x)
+#define N_(x) x
+
+/**
+ * DBusGMessageQueue:
+ * A GSource subclass for dispatching DBusConnection messages.
+ * We need this on top of the IO handlers, because sometimes
+ * there are messages to dispatch queued up but no IO pending.
+ */
+typedef struct
+{
+ GSource source; /**< the parent GSource */
+ DBusConnection *connection; /**< the connection to dispatch */
+} DBusGMessageQueue;
+
+static gboolean message_queue_prepare (GSource *source,
+ gint *timeout);
+static gboolean message_queue_check (GSource *source);
+static gboolean message_queue_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data);
+
+static const GSourceFuncs message_queue_funcs = {
+ message_queue_prepare,
+ message_queue_check,
+ message_queue_dispatch,
+ NULL
+};
+
+static gboolean
+message_queue_prepare (GSource *source,
+ gint *timeout)
+{
+ DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
+
+ *timeout = -1;
+
+ return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);
+}
+
+static gboolean
+message_queue_check (GSource *source)
+{
+ return FALSE;
+}
+
+static gboolean
+message_queue_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+{
+ DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
+
+ dbus_connection_ref (connection);
+
+ /* Only dispatch once - we don't want to starve other GSource */
+ dbus_connection_dispatch (connection);
+
+ dbus_connection_unref (connection);
+
+ return TRUE;
+}
+
+typedef struct
+{
+ GMainContext *context; /**< the main context */
+ GSList *ios; /**< all IOHandler */
+ GSList *timeouts; /**< all TimeoutHandler */
+ DBusConnection *connection; /**< NULL if this is really for a server not a connection */
+ GSource *message_queue_source; /**< DBusGMessageQueue */
+} ConnectionSetup;
+
+
+typedef struct
+{
+ ConnectionSetup *cs;
+ GSource *source;
+ DBusWatch *watch;
+} IOHandler;
+
+typedef struct
+{
+ ConnectionSetup *cs;
+ GSource *source;
+ DBusTimeout *timeout;
+} TimeoutHandler;
+
+dbus_int32_t _dbus_gmain_connection_slot = -1;
+static dbus_int32_t server_slot = -1;
+
+static ConnectionSetup*
+connection_setup_new (GMainContext *context,
+ DBusConnection *connection)
+{
+ ConnectionSetup *cs;
+
+ cs = g_new0 (ConnectionSetup, 1);
+
+ g_assert (context != NULL);
+
+ cs->context = context;
+ g_main_context_ref (cs->context);
+
+ if (connection)
+ {
+ cs->connection = connection;
+
+ cs->message_queue_source = g_source_new ((GSourceFuncs *) &message_queue_funcs,
+ sizeof (DBusGMessageQueue));
+ ((DBusGMessageQueue*)cs->message_queue_source)->connection = connection;
+ g_source_attach (cs->message_queue_source, cs->context);
+ }
+
+ return cs;
+}
+
+static void
+io_handler_source_finalized (gpointer data)
+{
+ IOHandler *handler;
+
+ handler = data;
+
+ if (handler->watch)
+ dbus_watch_set_data (handler->watch, NULL, NULL);
+
+ g_free (handler);
+}
+
+static void
+io_handler_destroy_source (void *data)
+{
+ IOHandler *handler;
+
+ handler = data;
+
+ if (handler->source)
+ {
+ GSource *source = handler->source;
+ handler->source = NULL;
+ handler->cs->ios = g_slist_remove (handler->cs->ios, handler);
+ g_source_destroy (source);
+ g_source_unref (source);
+ }
+}
+
+static void
+io_handler_watch_freed (void *data)
+{
+ IOHandler *handler;
+
+ handler = data;
+
+ handler->watch = NULL;
+
+ io_handler_destroy_source (handler);
+}
+
+static gboolean
+io_handler_dispatch (GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
+{
+ IOHandler *handler;
+ guint dbus_condition = 0;
+ DBusConnection *connection;
+
+ handler = data;
+
+ connection = handler->cs->connection;
+
+ if (connection)
+ dbus_connection_ref (connection);
+
+ if (condition & G_IO_IN)
+ dbus_condition |= DBUS_WATCH_READABLE;
+ if (condition & G_IO_OUT)
+ dbus_condition |= DBUS_WATCH_WRITABLE;
+ if (condition & G_IO_ERR)
+ dbus_condition |= DBUS_WATCH_ERROR;
+ if (condition & G_IO_HUP)
+ dbus_condition |= DBUS_WATCH_HANGUP;
+
+ /* Note that we don't touch the handler after this, because
+ * dbus may have disabled the watch and thus killed the
+ * handler.
+ */
+ dbus_watch_handle (handler->watch, dbus_condition);
+ handler = NULL;
+
+ if (connection)
+ dbus_connection_unref (connection);
+
+ return TRUE;
+}
+
+/* Attach the connection setup to the given watch, removing any
+ * previously-attached connection setup.
+ */
+static void
+connection_setup_add_watch (ConnectionSetup *cs,
+ DBusWatch *watch)
+{
+ guint flags;
+ GIOCondition condition;
+ GIOChannel *channel;
+ IOHandler *handler;
+
+ if (!dbus_watch_get_enabled (watch))
+ return;
+
+ flags = dbus_watch_get_flags (watch);
+
+ condition = G_IO_ERR | G_IO_HUP;
+ if (flags & DBUS_WATCH_READABLE)
+ condition |= G_IO_IN;
+ if (flags & DBUS_WATCH_WRITABLE)
+ condition |= G_IO_OUT;
+
+ handler = g_new0 (IOHandler, 1);
+ handler->cs = cs;
+ handler->watch = watch;
+
+ channel = g_io_channel_unix_new (dbus_watch_get_unix_fd (watch));
+
+ handler->source = g_io_create_watch (channel, condition);
+ g_source_set_callback (handler->source, (GSourceFunc) io_handler_dispatch, handler,
+ io_handler_source_finalized);
+ g_source_attach (handler->source, cs->context);
+
+ cs->ios = g_slist_prepend (cs->ios, handler);
+
+ dbus_watch_set_data (watch, handler, io_handler_watch_freed);
+ g_io_channel_unref (channel);
+}
+
+static void
+connection_setup_remove_watch (ConnectionSetup *cs,
+ DBusWatch *watch)
+{
+ IOHandler *handler;
+
+ handler = dbus_watch_get_data (watch);
+
+ if (handler == NULL || handler->cs != cs)
+ return;
+
+ io_handler_destroy_source (handler);
+}
+
+static void
+timeout_handler_source_finalized (gpointer data)
+{
+ TimeoutHandler *handler;
+
+ handler = data;
+
+ if (handler->timeout)
+ dbus_timeout_set_data (handler->timeout, NULL, NULL);
+
+ g_free (handler);
+}
+
+static void
+timeout_handler_destroy_source (void *data)
+{
+ TimeoutHandler *handler;
+
+ handler = data;
+
+ if (handler->source)
+ {
+ GSource *source = handler->source;
+ handler->source = NULL;
+ handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler);
+ g_source_destroy (source);
+ g_source_unref (source);
+ }
+}
+
+static void
+timeout_handler_timeout_freed (void *data)
+{
+ TimeoutHandler *handler;
+
+ handler = data;
+
+ handler->timeout = NULL;
+
+ timeout_handler_destroy_source (handler);
+}
+
+static gboolean
+timeout_handler_dispatch (gpointer data)
+{
+ TimeoutHandler *handler;
+
+ handler = data;
+
+ dbus_timeout_handle (handler->timeout);
+
+ return TRUE;
+}
+
+static void
+connection_setup_add_timeout (ConnectionSetup *cs,
+ DBusTimeout *timeout)
+{
+ TimeoutHandler *handler;
+
+ if (!dbus_timeout_get_enabled (timeout))
+ return;
+
+ handler = g_new0 (TimeoutHandler, 1);
+ handler->cs = cs;
+ handler->timeout = timeout;
+
+ handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
+ g_source_set_callback (handler->source, timeout_handler_dispatch, handler,
+ timeout_handler_source_finalized);
+ g_source_attach (handler->source, handler->cs->context);
+
+ cs->timeouts = g_slist_prepend (cs->timeouts, handler);
+
+ dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed);
+}
+
+static void
+connection_setup_remove_timeout (ConnectionSetup *cs,
+ DBusTimeout *timeout)
+{
+ TimeoutHandler *handler;
+
+ handler = dbus_timeout_get_data (timeout);
+
+ if (handler == NULL)
+ return;
+
+ timeout_handler_destroy_source (handler);
+}
+
+static void
+connection_setup_free (ConnectionSetup *cs)
+{
+ while (cs->ios)
+ io_handler_destroy_source (cs->ios->data);
+
+ while (cs->timeouts)
+ timeout_handler_destroy_source (cs->timeouts->data);
+
+ if (cs->message_queue_source)
+ {
+ GSource *source;
+
+ source = cs->message_queue_source;
+ cs->message_queue_source = NULL;
+
+ g_source_destroy (source);
+ g_source_unref (source);
+ }
+
+ g_main_context_unref (cs->context);
+ g_free (cs);
+}
+
+static dbus_bool_t
+add_watch (DBusWatch *watch,
+ gpointer data)
+{
+ ConnectionSetup *cs;
+
+ cs = data;
+
+ connection_setup_add_watch (cs, watch);
+
+ return TRUE;
+}
+
+static void
+remove_watch (DBusWatch *watch,
+ gpointer data)
+{
+ ConnectionSetup *cs;
+
+ cs = data;
+
+ connection_setup_remove_watch (cs, watch);
+}
+
+static void
+watch_toggled (DBusWatch *watch,
+ void *data)
+{
+ /* Because we just exit on OOM, enable/disable is
+ * no different from add/remove
+ */
+ if (dbus_watch_get_enabled (watch))
+ add_watch (watch, data);
+ else
+ remove_watch (watch, data);
+}
+
+static dbus_bool_t
+add_timeout (DBusTimeout *timeout,
+ void *data)
+{
+ ConnectionSetup *cs;
+
+ cs = data;
+
+ if (!dbus_timeout_get_enabled (timeout))
+ return TRUE;
+
+ connection_setup_add_timeout (cs, timeout);
+
+ return TRUE;
+}
+
+static void
+remove_timeout (DBusTimeout *timeout,
+ void *data)
+{
+ ConnectionSetup *cs;
+
+ cs = data;
+
+ connection_setup_remove_timeout (cs, timeout);
+}
+
+static void
+timeout_toggled (DBusTimeout *timeout,
+ void *data)
+{
+ /* Because we just exit on OOM, enable/disable is
+ * no different from add/remove
+ */
+ if (dbus_timeout_get_enabled (timeout))
+ add_timeout (timeout, data);
+ else
+ remove_timeout (timeout, data);
+}
+
+static void
+wakeup_main (void *data)
+{
+ ConnectionSetup *cs = data;
+
+ g_main_context_wakeup (cs->context);
+}
+
+
+/* Move to a new context */
+static ConnectionSetup*
+connection_setup_new_from_old (GMainContext *context,
+ ConnectionSetup *old)
+{
+ ConnectionSetup *cs;
+
+ g_assert (old->context != context);
+
+ cs = connection_setup_new (context, old->connection);
+
+ while (old->ios != NULL)
+ {
+ IOHandler *handler = old->ios->data;
+
+ connection_setup_add_watch (cs, handler->watch);
+ /* The old handler will be removed from old->ios as a side-effect */
+ }
+
+ while (old->timeouts != NULL)
+ {
+ TimeoutHandler *handler = old->timeouts->data;
+
+ connection_setup_add_timeout (cs, handler->timeout);
+ }
+
+ return cs;
+}
+
+/** @} */ /* End of GLib bindings internals */
+
+/**
+ * atspi_dbus_connection_setup_with_g_main: (skip)
+ * @connection: the connection
+ * @context: the #GMainContext or #NULL for default context
+ *
+ * Sets the watch and timeout functions of a #DBusConnection
+ * to integrate the connection with the GLib main loop.
+ * Pass in #NULL for the #GMainContext unless you're
+ * doing something specialized.
+ *
+ * If called twice for the same context, does nothing the second
+ * time. If called once with context A and once with context B,
+ * context B replaces context A as the context monitoring the
+ * connection.
+ */
+void
+atspi_dbus_connection_setup_with_g_main (DBusConnection *connection,
+ GMainContext *context)
+{
+ ConnectionSetup *old_setup;
+ ConnectionSetup *cs;
+
+ /* FIXME we never free the slot, so its refcount just keeps growing,
+ * which is kind of broken.
+ */
+ dbus_connection_allocate_data_slot (&_dbus_gmain_connection_slot);
+ if (_dbus_gmain_connection_slot < 0)
+ goto nomem;
+
+ if (context == NULL)
+ context = g_main_context_default ();
+
+ cs = NULL;
+
+ old_setup = dbus_connection_get_data (connection, _dbus_gmain_connection_slot);
+ if (old_setup != NULL)
+ {
+ if (old_setup->context == context)
+ return; /* nothing to do */
+
+ cs = connection_setup_new_from_old (context, old_setup);
+
+ /* Nuke the old setup */
+ dbus_connection_set_data (connection, _dbus_gmain_connection_slot, NULL, NULL);
+ old_setup = NULL;
+ }
+
+ if (cs == NULL)
+ cs = connection_setup_new (context, connection);
+
+ if (!dbus_connection_set_data (connection, _dbus_gmain_connection_slot, cs,
+ (DBusFreeFunction)connection_setup_free))
+ goto nomem;
+
+ if (!dbus_connection_set_watch_functions (connection,
+ add_watch,
+ remove_watch,
+ watch_toggled,
+ cs, NULL))
+ goto nomem;
+
+ if (!dbus_connection_set_timeout_functions (connection,
+ add_timeout,
+ remove_timeout,
+ timeout_toggled,
+ cs, NULL))
+ goto nomem;
+
+ dbus_connection_set_wakeup_main_function (connection,
+ wakeup_main,
+ cs, NULL);
+
+ return;
+
+ nomem:
+ g_error ("Not enough memory to set up DBusConnection for use with GLib");
+}
+
+/**
+ * atspi_dbus_server_setup_with_g_main: (skip)
+ * @server: the server
+ * @context: the #GMainContext or #NULL for default
+ *
+ * Sets the watch and timeout functions of a #DBusServer
+ * to integrate the server with the GLib main loop.
+ * In most cases the context argument should be #NULL.
+ *
+ * If called twice for the same context, does nothing the second
+ * time. If called once with context A and once with context B,
+ * context B replaces context A as the context monitoring the
+ * connection.
+ */
+void
+atspi_dbus_server_setup_with_g_main (DBusServer *server,
+ GMainContext *context)
+{
+ ConnectionSetup *old_setup;
+ ConnectionSetup *cs;
+
+ /* FIXME we never free the slot, so its refcount just keeps growing,
+ * which is kind of broken.
+ */
+ dbus_server_allocate_data_slot (&server_slot);
+ if (server_slot < 0)
+ goto nomem;
+
+ if (context == NULL)
+ context = g_main_context_default ();
+
+ cs = NULL;
+
+ old_setup = dbus_server_get_data (server, server_slot);
+ if (old_setup != NULL)
+ {
+ if (old_setup->context == context)
+ return; /* nothing to do */
+
+ cs = connection_setup_new_from_old (context, old_setup);
+
+ /* Nuke the old setup */
+ if (!dbus_server_set_data (server, server_slot, NULL, NULL))
+ goto nomem;
+ old_setup = NULL;
+ }
+
+ if (cs == NULL)
+ cs = connection_setup_new (context, NULL);
+
+ if (!dbus_server_set_data (server, server_slot, cs,
+ (DBusFreeFunction)connection_setup_free))
+ goto nomem;
+
+ if (!dbus_server_set_watch_functions (server,
+ add_watch,
+ remove_watch,
+ watch_toggled,
+ cs, NULL))
+ goto nomem;
+
+ if (!dbus_server_set_timeout_functions (server,
+ add_timeout,
+ remove_timeout,
+ timeout_toggled,
+ cs, NULL))
+ goto nomem;
+
+ return;
+
+ nomem:
+ g_error ("Not enough memory to set up DBusServer for use with GLib");
+}
diff --git a/atspi/atspi-gmain.h b/atspi/atspi-gmain.h
new file mode 100644
index 0000000..8e2396c
--- /dev/null
+++ b/atspi/atspi-gmain.h
@@ -0,0 +1,39 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* atspi-gmain.h atspi dbus gmain prototypes
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * This file is based on dbus-gmain.c from dbus-glib with functions renamed
+ * and unnecessary code removed.
+ */
+
+#ifndef _ATSPI_GMAIN_H
+#define _ATSPI_GMAIN_H
+
+G_BEGIN_DECLS
+
+void
+atspi_dbus_connection_setup_with_g_main (DBusConnection *connection,
+ GMainContext *context);
+
+void
+atspi_dbus_server_setup_with_g_main (DBusServer *server,
+ GMainContext *context);
+
+G_END_DECLS
+
+#endif
diff --git a/atspi/atspi-hyperlink.c b/atspi/atspi-hyperlink.c
new file mode 100644
index 0000000..36763e3
--- /dev/null
+++ b/atspi/atspi-hyperlink.c
@@ -0,0 +1,215 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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 (AtspiHyperlink, atspi_hyperlink, ATSPI_TYPE_OBJECT)
+
+static void
+atspi_hyperlink_init (AtspiHyperlink *hyperlink)
+{
+}
+
+static void
+atspi_hyperlink_class_init (AtspiHyperlinkClass *klass)
+{
+}
+
+AtspiHyperlink *
+_atspi_hyperlink_new (AtspiApplication *app, const gchar *path)
+{
+ AtspiHyperlink *hyperlink;
+
+ hyperlink = g_object_new (ATSPI_TYPE_HYPERLINK, NULL);
+ hyperlink->parent.app = g_object_ref (app);
+ hyperlink->parent.path = g_strdup (path);
+
+ return hyperlink;
+}
+
+/**
+ * atspi_hyperlink_get_n_anchors:
+ * @obj: a pointer to the #AtspiHyperlink object on which to operate.
+ *
+ * Gets the total number of anchors which an #AtspiHyperlink implementor has.
+ * Though typical hyperlinks have only one anchor, client-side image maps and
+ * other hypertext objects may potentially activate or refer to multiple
+ * URIs. For each anchor there is a corresponding URI and object.
+ *
+ * see: #atspi_hyperlink_get_uri and #atspi_hyperlink_get_object.
+ *
+ * Returns: a #gint indicating the number of anchors in this hyperlink.
+ **/
+gint
+atspi_hyperlink_get_n_anchors (AtspiHyperlink *obj, GError **error)
+{
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_get_property (obj, atspi_interface_hyperlink, "NAnchors", error, "i", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_hyperlink_get_uri:
+ * @obj: a pointer to the #AtspiHyperlink implementor on which to operate.
+ * @i: a (zero-index) integer indicating which hyperlink anchor to query.
+ *
+ * Gets the URI associated with a particular hyperlink anchor.
+ *
+ * Returns: a UTF-8 string giving the URI of the @ith hyperlink anchor.
+ **/
+gchar *
+atspi_hyperlink_get_uri (AtspiHyperlink *obj, int i, GError **error)
+{
+ dbus_int32_t d_i = i;
+ char *retval = NULL;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ _atspi_dbus_call (obj, atspi_interface_hyperlink, "GetURI", error, "i=>s", d_i, &retval);
+
+ if (!retval)
+ retval = g_strdup ("");
+
+ return retval;
+}
+
+/**
+ * atspi_hyperlink_get_object:
+ * @obj: a pointer to the #AtspiHyperlink implementor on which to operate.
+ * @i: a (zero-index) #gint indicating which hyperlink anchor to query.
+ *
+ * Gets the object associated with a particular hyperlink anchor, as an
+ * #AtspiAccessible.
+ *
+ * Returns: (transfer full): an #AtspiAccessible that represents the object
+ * associated with the @ith anchor of the specified #AtspiHyperlink.
+ **/
+AtspiAccessible*
+atspi_hyperlink_get_object (AtspiHyperlink *obj, gint i, GError **error)
+{
+ dbus_int32_t d_i = i;
+ DBusMessage *reply;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ reply = _atspi_dbus_call_partial (obj, atspi_interface_hyperlink, "GetObject", error, "i", d_i);
+
+ return _atspi_dbus_return_accessible_from_message (reply);
+}
+
+/**
+ * atspi_hyperlink_get_index_range:
+ * @obj: a pointer to the #AtspiHyperlink implementor on which to operate.
+ *
+ *
+ * Gets the starting and ending character offsets of the text range
+ * associated with an #AtspiHyperlink, in its originating #AtspiHypertext.
+ **/
+AtspiRange *
+atspi_hyperlink_get_index_range (AtspiHyperlink *obj, GError **error)
+{
+ dbus_int32_t d_start_offset, d_end_offset;
+ AtspiRange *ret = g_new (AtspiRange, 1);
+
+ ret->start_offset = ret->end_offset = -1;
+
+ if (!obj)
+ return ret;
+
+ _atspi_dbus_call (obj, atspi_interface_hyperlink, "GetIndexRange", error, "=>ii", &d_start_offset, &d_end_offset);
+
+ ret->start_offset = d_start_offset;
+ ret->end_offset = d_end_offset;
+ return ret;
+}
+
+/**
+ * atspi_hyperlink_get_start_index:
+ * @obj: a pointer to the #AtspiHyperlink implementor on which to operate.
+ *
+ *
+ * Gets the starting character offset of the text range associated with
+ * an #AtspiHyperlink, in its originating #AtspiHypertext.
+ **/
+gint
+atspi_hyperlink_get_start_index (AtspiHyperlink *obj, GError **error)
+{
+ dbus_int32_t d_start_offset = -1;
+
+ if (!obj)
+ return -1;
+
+ _atspi_dbus_get_property (obj, atspi_interface_hyperlink, "StartIndex",
+ error, "i", &d_start_offset);
+
+ return d_start_offset;
+}
+/**
+ * atspi_hyperlink_get_end_index:
+ * @obj: a pointer to the #AtspiHyperlink implementor on which to operate.
+ *
+ *
+ * Gets the ending character offset of the text range associated with
+ * an #AtspiHyperlink, in its originating #AtspiHypertext.
+ **/
+gint
+atspi_hyperlink_get_end_index (AtspiHyperlink *obj, GError **error)
+{
+ dbus_int32_t d_end_offset = -1;
+
+ if (!obj)
+ return -1;
+
+ _atspi_dbus_get_property (obj, atspi_interface_hyperlink, "EndIndex", error,
+ "i", &d_end_offset);
+
+ return d_end_offset;
+}
+
+
+/**
+ * atspi_hyperlink_is_valid:
+ * @obj: a pointer to the #AtspiHyperlink on which to operate.
+ *
+ * Tells whether an #AtspiHyperlink object is still valid with respect to its
+ * originating hypertext object.
+ *
+ * Returns: #TRUE if the specified #AtspiHyperlink is still valid with respect
+ * to its originating #AtspiHypertext object, #FALSE otherwise.
+ **/
+gboolean
+atspi_hyperlink_is_valid (AtspiHyperlink *obj, GError **error)
+{
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_hyperlink, "IsValid", error, "=>b", &retval);
+
+ return retval;
+}
diff --git a/atspi/atspi-hyperlink.h b/atspi/atspi-hyperlink.h
new file mode 100644
index 0000000..86efa7b
--- /dev/null
+++ b/atspi/atspi-hyperlink.h
@@ -0,0 +1,77 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_HYPERLINK_H_
+#define _ATSPI_HYPERLINK_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+
+#include "atspi-text.h" /* for AtspiRange */
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+#define ATSPI_TYPE_HYPERLINK (atspi_hyperlink_get_type ())
+#define ATSPI_HYPERLINK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_HYPERLINK, AtspiHyperlink))
+#define ATSPI_HYPERLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_HYPERLINK, AtspiHyperlinkClass))
+#define ATSPI_IS_HYPERLINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_HYPERLINK))
+#define ATSPI_IS_HYPERLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_HYPERLINK))
+#define ATSPI_HYPERLINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_HYPERLINK, AtspiHyperlinkClass))
+
+struct _AtspiHyperlink
+{
+ AtspiObject parent;
+};
+
+typedef struct _AtspiHyperlinkClass AtspiHyperlinkClass;
+struct _AtspiHyperlinkClass
+{
+ AtspiObjectClass parent_class;
+};
+
+GType atspi_hyperlink_get_type (void);
+
+AtspiHyperlink *
+_atspi_hyperlink_new (AtspiApplication *app, const gchar *path);
+
+gint atspi_hyperlink_get_n_anchors (AtspiHyperlink *obj, GError **error);
+
+gchar * atspi_hyperlink_get_uri (AtspiHyperlink *obj, int i, GError **error);
+
+AtspiAccessible* atspi_hyperlink_get_object (AtspiHyperlink *obj, gint i, GError **error);
+
+AtspiRange * atspi_hyperlink_get_index_range (AtspiHyperlink *obj, GError **error);
+
+gint atspi_hyperlink_get_start_index (AtspiHyperlink *obj, GError **error);
+
+gint atspi_hyperlink_get_end_index (AtspiHyperlink *obj, GError **error);
+
+gboolean atspi_hyperlink_is_valid (AtspiHyperlink *obj, GError **error);
+
+G_END_DECLS
+
+#endif /* _ATSPI_HYPERLINK_H_ */
diff --git a/atspi/atspi-hypertext.c b/atspi/atspi-hypertext.c
new file mode 100644
index 0000000..ca186ea
--- /dev/null
+++ b/atspi/atspi-hypertext.c
@@ -0,0 +1,124 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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"
+
+/**
+ * atspi_hypertext_get_n_links:
+ * @obj: a pointer to the #AtspiHypertext implementor on which to operate.
+ *
+ * Gets the total number of #AtspiHyperlink objects that an
+ * #AtspiHypertext implementor has.
+ *
+ * Returns: a #gint indicating the number of #AtspiHyperlink objects
+ * of the #AtspiHypertext implementor, or -1 if
+ * the number cannot be determined (for example, if the
+ * #AtspiHypertext object is so large that it is not
+ * all currently in the memory cache).
+ **/
+gint
+atspi_hypertext_get_n_links (AtspiHypertext *obj, GError **error)
+{
+ dbus_int32_t retval = 0;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_hypertext, "GetNLinks", error, "=>i", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_hypertext_get_link:
+ * @obj: a pointer to the #AtspiHypertext implementor on which to operate.
+ * @link_index: a (zero-index) #gint indicating which hyperlink to query.
+ *
+ * Gets the #AtspiHyperlink object at a specified index.
+ *
+ * Returns: (nullable) (transfer full): the #AtspiHyperlink object
+ * specified by @link_index.
+ **/
+AtspiHyperlink *
+atspi_hypertext_get_link (AtspiHypertext *obj, gint link_index, GError **error)
+{
+ dbus_int32_t d_link_index = link_index;
+ DBusMessage *reply;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ reply = _atspi_dbus_call_partial (obj, atspi_interface_hypertext, "GetLink", error, "i", d_link_index);
+
+ return _atspi_dbus_return_hyperlink_from_message (reply);
+}
+
+/**
+ * atspi_hypertext_get_link_index:
+ * @obj: a pointer to the #AtspiHypertext implementor on which to operate.
+ * @character_offset: a #gint specifying the character offset to query.
+ *
+ * Gets the index of the #AtspiHyperlink object at a specified
+ * character offset.
+ *
+ * Returns: the linkIndex of the #AtspiHyperlink active at
+ * character offset @character_offset, or -1 if there is
+ * no hyperlink at the specified character offset.
+ **/
+int
+atspi_hypertext_get_link_index (AtspiHypertext *obj,
+ gint character_offset,
+ GError **error)
+{
+ dbus_int32_t d_character_offset = character_offset;
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_call (obj, atspi_interface_hypertext, "GetLinkIndex", error, "i=>i", d_character_offset, &retval);
+
+ return retval;
+}
+
+static void
+atspi_hypertext_base_init (AtspiHypertext *klass)
+{
+}
+
+GType
+atspi_hypertext_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (AtspiHypertext),
+ (GBaseInitFunc) atspi_hypertext_base_init,
+ (GBaseFinalizeFunc) NULL,
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE, "AtspiHypertext", &tinfo, 0);
+
+ }
+ return type;
+}
diff --git a/atspi/atspi-hypertext.h b/atspi/atspi-hypertext.h
new file mode 100644
index 0000000..bebcf51
--- /dev/null
+++ b/atspi/atspi-hypertext.h
@@ -0,0 +1,57 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_HYPERTEXT_H_
+#define _ATSPI_HYPERTEXT_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+#define ATSPI_TYPE_HYPERTEXT (atspi_hypertext_get_type ())
+#define ATSPI_IS_HYPERTEXT(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_HYPERTEXT)
+#define ATSPI_HYPERTEXT(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_HYPERTEXT, AtspiHypertext)
+#define ATSPI_HYPERTEXT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_HYPERTEXT, AtspiHypertext))
+
+GType atspi_hypertext_get_type ();
+
+struct _AtspiHypertext
+{
+ GTypeInterface parent;
+};
+
+gint atspi_hypertext_get_n_links (AtspiHypertext *obj, GError **error);
+
+AtspiHyperlink * atspi_hypertext_get_link (AtspiHypertext *obj, gint link_index, GError **error);
+
+gint atspi_hypertext_get_link_index (AtspiHypertext *obj, gint character_offset, GError **error);
+
+G_END_DECLS
+
+#endif /* _ATSPI_HYPERTEXT_H_ */
diff --git a/atspi/atspi-image.c b/atspi/atspi-image.c
new file mode 100644
index 0000000..4f17326
--- /dev/null
+++ b/atspi/atspi-image.c
@@ -0,0 +1,177 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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"
+
+/**
+ * atspi_image_get_image_description:
+ * @obj: a pointer to the #AtspiImage implementor on which to operate.
+ *
+ * Gets the description of the image displayed in an #AtspiImage object.
+ *
+ * Returns: a UTF-8 string describing the image.
+ **/
+gchar *
+atspi_image_get_image_description (AtspiImage *obj, GError **error)
+{
+ char *retval = NULL;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ _atspi_dbus_get_property (obj, atspi_interface_image, "ImageDescription", error, "s", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_image_get_image_size:
+ * @obj: a pointer to the #AtspiImage to query.
+ *
+ * Gets the size of the image displayed in a specified #AtspiImage object.
+ *
+ * Returns: a pointer to an #AtspiPoint where x corresponds to
+ * the image's width and y corresponds to the image's height.
+ *
+ **/
+AtspiPoint *
+atspi_image_get_image_size (AtspiImage *obj, GError **error)
+{
+ dbus_int32_t d_w, d_h;
+ AtspiPoint ret;
+
+ ret.x = ret.y = -1;
+ if (!obj)
+ return atspi_point_copy (&ret);
+
+ _atspi_dbus_call (obj, atspi_interface_image, "GetImageSize", error, "=>ii", &d_w, &d_h);
+ ret.x = d_w;
+ ret.y = d_h;
+ return atspi_point_copy (&ret);
+}
+
+/**
+ * atspi_image_get_image_position:
+ * @obj: a pointer to the #AtspiImage implementor to query.
+ * @ctype: the desired coordinate system into which to return the results,
+ * (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN).
+ *
+ * Gets the minimum x and y coordinates of the image displayed in a
+ * specified #AtspiImage implementor.
+ *
+ * Returns: a pointer to an #AtspiPoint where x and y correspond to the
+ * minimum coordinates of the displayed image.
+ *
+ **/
+AtspiPoint *
+atspi_image_get_image_position (AtspiImage *obj,
+ AtspiCoordType ctype,
+ GError **error)
+{
+ dbus_int32_t d_x, d_y;
+ dbus_uint32_t d_ctype = ctype;
+ AtspiPoint ret;
+
+ ret.x = ret.y = 0;
+
+ if (!obj)
+ return atspi_point_copy (&ret);
+
+ _atspi_dbus_call (obj, atspi_interface_image, "GetImagePosition", error, "u=>ii", d_ctype, &d_x, &d_y);
+
+ ret.x = d_x;
+ ret.y = d_y;
+ return atspi_point_copy (&ret);
+}
+
+/**
+ * atspi_image_get_image_extents:
+ * @obj: a pointer to the #AtspiImage implementor to query.
+ * @ctype: the desired coordinate system into which to return the results,
+ * (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN).
+ *
+ * Gets the bounding box of the image displayed in a
+ * specified #AtspiImage implementor.
+ *
+ * Returns: a pointer to an #AtspiRect corresponding to the image's bounding box. The minimum x and y coordinates,
+ * width, and height are specified.
+ **/
+AtspiRect *
+atspi_image_get_image_extents (AtspiImage *obj,
+ AtspiCoordType ctype,
+ GError **error)
+{
+ dbus_uint32_t d_ctype = ctype;
+ AtspiRect bbox;
+
+ bbox.x = bbox.y = bbox.width = bbox.height = -1;
+ g_return_val_if_fail (obj != NULL, atspi_rect_copy (&bbox));
+
+ _atspi_dbus_call (obj, atspi_interface_image, "GetImageExtents", error, "u=>(iiii)", d_ctype, &bbox);
+
+ return atspi_rect_copy (&bbox);
+}
+
+/**
+ * atspi_image_get_image_locale:
+ * @obj: a pointer to the #AtspiImage to query.
+ *
+ * Gets the locale associated with an image and its textual representation.
+ *
+ * Returns: A POSIX LC_MESSAGES-style locale value for image description and text.
+ **/
+gchar *
+atspi_image_get_image_locale (AtspiImage *obj, GError **error)
+{
+ gchar *retval = NULL;
+
+ g_return_val_if_fail (obj != NULL, g_strdup ("C"));
+
+ _atspi_dbus_get_property (obj, atspi_interface_image, "ImageLocale", error, "s", &retval);
+
+ return retval;
+}
+
+static void
+atspi_image_base_init (AtspiImage *klass)
+{
+}
+
+GType
+atspi_image_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (AtspiImage),
+ (GBaseInitFunc) atspi_image_base_init,
+ (GBaseFinalizeFunc) NULL,
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE, "AtspiImage", &tinfo, 0);
+
+ }
+ return type;
+}
diff --git a/atspi/atspi-image.h b/atspi/atspi-image.h
new file mode 100644
index 0000000..3fa40ef
--- /dev/null
+++ b/atspi/atspi-image.h
@@ -0,0 +1,61 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_IMAGE_H_
+#define _ATSPI_IMAGE_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+#define ATSPI_TYPE_IMAGE (atspi_image_get_type ())
+#define ATSPI_IS_IMAGE(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_IMAGE)
+#define ATSPI_IMAGE(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_IMAGE, AtspiImage)
+#define ATSPI_IMAGE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_IMAGE, AtspiImage))
+
+GType atspi_image_get_type ();
+
+struct _AtspiImage
+{
+ GTypeInterface parent;
+};
+
+gchar * atspi_image_get_image_description (AtspiImage *obj, GError **error);
+
+AtspiPoint * atspi_image_get_image_size (AtspiImage *obj, GError **error);
+
+AtspiPoint * atspi_image_get_image_position (AtspiImage *obj, AtspiCoordType ctype, GError **error);
+
+AtspiRect * atspi_image_get_image_extents (AtspiImage *obj, AtspiCoordType ctype, GError **error);
+
+gchar * atspi_image_get_image_locale (AtspiImage *obj, GError **error);
+
+G_END_DECLS
+
+#endif /* _ATSPI_IMAGE_H_ */
diff --git a/atspi/atspi-matchrule-private.h b/atspi/atspi-matchrule-private.h
new file mode 100644
index 0000000..e55c2fa
--- /dev/null
+++ b/atspi/atspi-matchrule-private.h
@@ -0,0 +1,41 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_MATCH_RULE_PRIVATE_H_
+#define _ATSPI_MATCH_RULE_PRIVATE_H_
+
+#include "glib-object.h"
+
+#include "atspi-matchrule.h"
+#include "dbus/dbus.h"
+
+G_BEGIN_DECLS
+
+gboolean
+_atspi_match_rule_marshal (AtspiMatchRule *rule, DBusMessageIter *iter);
+
+G_END_DECLS
+
+#endif /* _ATSPI_MATCH_RULE_PRIVATE_H_ */
diff --git a/atspi/atspi-matchrule.c b/atspi/atspi-matchrule.c
new file mode 100644
index 0000000..e995459
--- /dev/null
+++ b/atspi/atspi-matchrule.c
@@ -0,0 +1,269 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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 (AtspiMatchRule, atspi_match_rule, G_TYPE_OBJECT)
+
+static void
+atspi_match_rule_init (AtspiMatchRule *match_rule)
+{
+}
+
+static void
+atspi_match_rule_dispose (GObject *object)
+{
+ AtspiMatchRule *rule = ATSPI_MATCH_RULE (object);
+
+ if (rule->states)
+ {
+ g_object_unref (rule->states);
+ rule->states = NULL;
+ }
+
+ if (rule->attributes)
+ {
+ g_hash_table_unref (rule->attributes);
+ rule->attributes = NULL;
+ }
+
+ G_OBJECT_CLASS (atspi_match_rule_parent_class)->dispose (object);
+}
+
+static void
+atspi_match_rule_finalize (GObject *object)
+{
+ AtspiMatchRule *rule = ATSPI_MATCH_RULE (object);
+ gint i;
+
+ if (rule->interfaces)
+ {
+ for (i = 0; i < rule->interfaces->len; i++)
+ g_free (g_array_index (rule->interfaces, gchar *, i));
+ g_array_free (rule->interfaces, TRUE);
+ }
+
+ if (rule->attributes)
+ g_hash_table_unref (rule->attributes);
+
+ G_OBJECT_CLASS (atspi_match_rule_parent_class)->finalize (object);
+}
+
+static void
+atspi_match_rule_class_init (AtspiMatchRuleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = atspi_match_rule_dispose;
+ object_class->finalize = atspi_match_rule_finalize;
+}
+
+/**
+ * atspi_match_rule_new:
+ * @states: An #AtspiStateSet specifying the states to match or NULL if none.
+ * @statematchtype: An #AtspiCollectionMatchType specifying how to interpret
+ * @states.
+ * @attributes: (element-type gchar* gchar*): A #GHashTable specifying
+ * attributes to match. To specify multiple attribute values,
+ * separate each value with a :: If an attribute value contains a :,
+ * then it can be escaped by preceding it with a \. A backslash can
+ * likewise be escaped by inserting a double backslash.
+ * @attributematchtype: An #AtspiCollectionMatchType specifying how to
+ * interpret @attributes.
+ * @interfaces: (element-type gchar*): An array of interfaces to match, or
+ * NULL if not applicable. Interface names should be specified
+ * by their DBus names (org.a11y.Atspi.Accessible,
+ * org.a11y.Atspi.Component, etc).
+ * @interfacematchtype: An #AtspiCollectionMatchType specifying how to
+ * interpret @interfaces.
+ * @roles: (element-type AtspiRole): A #GArray of roles to match, or NULL if
+ * not applicable.
+ * @rolematchtype: An #AtspiCollectionMatchType specifying how to
+ * interpret @roles.
+ * @invert: if #TRUE, the match rule should be denied (inverted); if #FALSE,
+ * it should not. For example, if the match rule defines that a match is
+ * an object of ROLE_HEADING which has STATE_FOCUSABLE and a click action,
+ * inverting it would match all objects that are not of ROLE_HEADING,
+ * focusable and clickable at the same time.
+ *
+ * Creates a new #AtspiMatchRule with specified @states, @attributes,
+ * @interfaces, and @roles.
+ *
+ * Returns: (transfer full): A new #AtspiMatchRule.
+ **/
+AtspiMatchRule *
+atspi_match_rule_new (AtspiStateSet *states,
+ AtspiCollectionMatchType statematchtype,
+ GHashTable *attributes,
+ AtspiCollectionMatchType attributematchtype,
+ GArray *roles,
+ AtspiCollectionMatchType rolematchtype,
+ GArray *interfaces,
+ AtspiCollectionMatchType interfacematchtype,
+ gboolean invert)
+{
+ AtspiMatchRule *rule = g_object_new (ATSPI_TYPE_MATCH_RULE, NULL);
+ int i;
+
+ if (states)
+ rule->states = g_object_ref (states);
+ rule->statematchtype = statematchtype;
+
+ if (attributes)
+ {
+ GHashTableIter hash_table_iter;
+ gchar *key, *value;
+ rule->attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+ g_hash_table_iter_init (&hash_table_iter, attributes);
+ while (g_hash_table_iter_next (&hash_table_iter, (gpointer *)&key,
+ (gpointer *)&value))
+ g_hash_table_insert (rule->attributes, g_strdup (key), g_strdup (value));
+ } else
+ rule->attributes = NULL;
+ rule->attributematchtype = attributematchtype;
+
+ if (interfaces)
+ {
+ rule->interfaces = g_array_new (TRUE, TRUE, sizeof (gchar *));
+ for (i = 0; i < interfaces->len; i++)
+ {
+ gchar *val = g_strdup (g_array_index (interfaces, gchar *, i));
+ rule->interfaces = g_array_append_val (rule->interfaces, val);
+ }
+ }
+ rule->interfacematchtype = interfacematchtype;
+
+ if (roles)
+ {
+ for (i = 0; i < roles->len; i++)
+ {
+ AtspiRole role = g_array_index (roles, AtspiRole, i);
+ if (role < 128)
+ rule->roles [role / 32] |= (1 << (role % 32));
+ else
+ g_warning ("Atspi: unexpected role %d\n", role);
+ }
+ }
+ else
+ rule->roles [0] = rule->roles [1] = 0;
+ rule->rolematchtype = rolematchtype;
+
+ rule->invert = invert;
+
+ return rule;
+}
+
+static void
+append_entry (gpointer key, gpointer val, gpointer data)
+{
+ DBusMessageIter *iter = data;
+ DBusMessageIter iter_entry;
+
+ if (!dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL,
+ &iter_entry))
+ return;
+ dbus_message_iter_append_basic (&iter_entry, DBUS_TYPE_STRING, &key);
+ dbus_message_iter_append_basic (&iter_entry, DBUS_TYPE_STRING, &val);
+ dbus_message_iter_close_container (iter, &iter_entry);
+}
+
+gboolean
+_atspi_match_rule_marshal (AtspiMatchRule *rule, DBusMessageIter *iter)
+{
+ DBusMessageIter iter_struct, iter_array, iter_dict;
+ dbus_int32_t states [2];
+ dbus_int32_t d_statematchtype = rule->statematchtype;
+ dbus_int32_t d_attributematchtype = rule->attributematchtype;
+ dbus_int32_t d_interfacematchtype = rule->interfacematchtype;
+ dbus_uint32_t d_rolematchtype = rule->rolematchtype;
+ dbus_bool_t d_invert = rule->invert;
+ gint i;
+ dbus_int32_t d_role;
+
+ if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
+ &iter_struct))
+ return FALSE;
+
+ /* states */
+ if (rule->states)
+ {
+ states [0] = rule->states->states & 0xffffffff;
+ states [1] = rule->states->states >> 32;
+ }
+ else
+ {
+ states [0] = states [1] = 0;
+ }
+ dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "i", &iter_array);
+ dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &states [0]);
+ dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &states [1]);
+ dbus_message_iter_close_container (&iter_struct, &iter_array);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_statematchtype);
+
+ /* attributes */
+ if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "{ss}",
+ &iter_dict))
+ return FALSE;
+ if (rule->attributes)
+ g_hash_table_foreach (rule->attributes, append_entry, &iter_dict);
+ dbus_message_iter_close_container (&iter_struct, &iter_dict);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_attributematchtype);
+
+ if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "i",
+ &iter_array))
+ return FALSE;
+ d_role = rule->roles [0];
+ dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
+ d_role = rule->roles [1];
+ dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
+ d_role = rule->roles [2];
+ dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
+ d_role = rule->roles [3];
+ dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role);
+ dbus_message_iter_close_container (&iter_struct, &iter_array);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32,
+ &d_rolematchtype);
+
+ /* interfaces */
+ if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s",
+ &iter_array))
+ return FALSE;
+ if (rule->interfaces)
+ {
+ for (i = 0; i < rule->interfaces->len; i++)
+ {
+ char *val = g_array_index (rule->interfaces, gchar *, i);
+ dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &val);
+ }
+ }
+ dbus_message_iter_close_container (&iter_struct, &iter_array);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_interfacematchtype);
+
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &d_invert);
+
+ dbus_message_iter_close_container (iter, &iter_struct);
+ return TRUE;
+}
diff --git a/atspi/atspi-matchrule.h b/atspi/atspi-matchrule.h
new file mode 100644
index 0000000..0a006d0
--- /dev/null
+++ b/atspi/atspi-matchrule.h
@@ -0,0 +1,80 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_MATCH_RULE_H_
+#define _ATSPI_MATCH_RULE_H_
+
+#include "glib-object.h"
+
+#include "atspi-stateset.h"
+#include "atspi-constants.h"
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+#define ATSPI_TYPE_MATCH_RULE (atspi_match_rule_get_type ())
+#define ATSPI_MATCH_RULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_MATCH_RULE, AtspiMatchRule))
+#define ATSPI_MATCH_RULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_MATCH_RULE, AtspiMatchRuleClass))
+#define ATSPI_IS_MATCH_RULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_MATCH_RULE))
+#define ATSPI_IS_MATCH_RULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_MATCH_RULE))
+#define ATSPI_MATCH_RULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_MATCH_RULE, AtspiMatchRuleClass))
+
+typedef struct _AtspiMatchRule AtspiMatchRule;
+struct _AtspiMatchRule
+{
+ GObject parent;
+ AtspiStateSet *states;
+ AtspiCollectionMatchType statematchtype;
+ GHashTable *attributes;
+ AtspiCollectionMatchType attributematchtype;
+ GArray *interfaces;
+ AtspiCollectionMatchType interfacematchtype;
+ gint roles [4];
+ AtspiCollectionMatchType rolematchtype;
+ gboolean invert;
+};
+
+typedef struct _AtspiMatchRuleClass AtspiMatchRuleClass;
+struct _AtspiMatchRuleClass
+{
+ GObjectClass parent_class;
+};
+
+GType atspi_match_rule_get_type ();
+
+AtspiMatchRule *
+atspi_match_rule_new (AtspiStateSet *states,
+ AtspiCollectionMatchType statematchtype,
+ GHashTable *attributes,
+ AtspiCollectionMatchType attributematchtype,
+ GArray *roles,
+ AtspiCollectionMatchType rolematchtype,
+ GArray *interfaces,
+ AtspiCollectionMatchType interfacematchtype,
+ gboolean invert);
+
+G_END_DECLS
+
+#endif /* _ATSPI_MATCH_RULE_H_ */
diff --git a/atspi/atspi-misc-private.h b/atspi/atspi-misc-private.h
new file mode 100644
index 0000000..fe5ca56
--- /dev/null
+++ b/atspi/atspi-misc-private.h
@@ -0,0 +1,171 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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 <string.h>
+
+#include "atspi.h"
+
+#include "dbus/dbus.h"
+
+#include "dbind/dbind.h"
+
+G_BEGIN_DECLS
+
+typedef struct _AtspiReference AtspiReference;
+struct _AtspiReference
+{
+ char *name;
+ char *path;
+};
+
+/* 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_collection;
+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_table_cell;
+extern const char *atspi_interface_text;
+extern const char *atspi_interface_cache;
+extern const char *atspi_interface_value;
+
+/* function prototypes */
+gint _atspi_get_iface_num (const char *iface);
+
+DBusConnection * _atspi_bus ();
+
+AtspiAccessible * _atspi_ref_accessible (const char *app, const char *path);
+
+AtspiAccessible *
+_atspi_dbus_return_accessible_from_message (DBusMessage *message);
+
+AtspiAccessible *
+_atspi_dbus_return_accessible_from_iter (DBusMessageIter *iter);
+
+AtspiHyperlink *
+_atspi_dbus_return_hyperlink_from_message (DBusMessage *message);
+
+AtspiHyperlink *
+_atspi_dbus_return_hyperlink_from_iter (DBusMessageIter *iter);
+
+dbus_bool_t _atspi_dbus_call (gpointer obj, const char *interface, const char *method, GError **error, const char *type, ...);
+
+DBusMessage *_atspi_dbus_call_partial (gpointer obj, const char *interface, const char *method, GError **error, const char *type, ...);
+
+DBusMessage *_atspi_dbus_call_partial_va (gpointer obj, const char *interface, const char *method, GError **error, const char *type, va_list args);
+
+dbus_bool_t _atspi_dbus_get_property (gpointer obj, const char *interface, const char *name, GError **error, const char *type, void *data);
+
+DBusMessage * _atspi_dbus_send_with_reply_and_block (DBusMessage *message, GError **error);
+
+GHashTable *_atspi_dbus_return_hash_from_message (DBusMessage *message);
+
+GHashTable *_atspi_dbus_hash_from_iter (DBusMessageIter *iter);
+
+GArray *_atspi_dbus_return_attribute_array_from_message (DBusMessage *message);
+
+GArray *_atspi_dbus_attribute_array_from_iter (DBusMessageIter *iter);
+
+void _atspi_dbus_set_interfaces (AtspiAccessible *accessible, DBusMessageIter *iter);
+
+void _atspi_dbus_set_state (AtspiAccessible *accessible, DBusMessageIter *iter);
+
+#define _ATSPI_DBUS_CHECK_SIG(message, type, error, ret) \
+ if (!message) \
+ return (ret); \
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) \
+ { \
+ const char *err; \
+ dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &err, DBUS_TYPE_INVALID); \
+ if (err) \
+ g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_IPC, err); \
+ dbus_message_unref (message); \
+ return ret; \
+ } \
+ if (strcmp (dbus_message_get_signature (message), type) != 0) \
+ { \
+ g_warning ("at-spi: Expected message signature %s but got %s at %s line %d", type, dbus_message_get_signature (message), __FILE__, __LINE__); \
+ dbus_message_unref (message); \
+ return (ret); \
+ }
+
+
+/**
+ * ATSPI_ERROR:
+ *
+ * Error domain for AT-SPI IPC failures. Errors in this domain will
+ * be from the #ATSPIAtspiError enumeration. See #GError for information on
+ * error domains.
+ */
+#define ATSPI_ERROR _atspi_error_quark()
+GQuark _atspi_error_quark (void);
+
+/**
+ * AtspiError:
+ * @ATSPI_APPLICATION_NO_LONGER_EXISTS: The application has quit.
+ */
+typedef enum
+{
+ ATSPI_ERROR_APPLICATION_GONE,
+ ATSPI_ERROR_IPC,
+ ATSPI_ERROR_SYNC_NOT_ALLOWED,
+} AtspiError;
+
+extern GMainLoop *atspi_main_loop;
+extern gboolean atspi_no_cache;
+
+GHashTable *_atspi_get_live_refs ();
+
+gchar *_atspi_name_compat (gchar *in);
+
+GHashTable *_atspi_dbus_update_cache_from_dict (AtspiAccessible *accessible, DBusMessageIter *iter);
+
+gboolean _atspi_get_allow_sync ();
+
+gboolean _atspi_set_allow_sync (gboolean val);
+
+void _atspi_set_error_no_sync (GError **error);
+G_END_DECLS
+
+#endif /* _ATSPI_MISC_PRIVATE_H_ */
diff --git a/atspi/atspi-misc.c b/atspi/atspi-misc.c
new file mode 100644
index 0000000..4cf7732
--- /dev/null
+++ b/atspi/atspi-misc.c
@@ -0,0 +1,1796 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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"
+#ifdef HAVE_X11
+#include "X11/Xlib.h"
+#endif
+#include "atspi-gmain.h"
+#include <stdio.h>
+#include <string.h>
+
+static void handle_get_items (DBusPendingCall *pending, void *user_data);
+
+static DBusConnection *bus = NULL;
+static GHashTable *live_refs = NULL;
+static gint method_call_timeout = 800;
+static gint app_startup_time = 15000;
+static gboolean allow_sync = TRUE;
+
+GMainLoop *atspi_main_loop;
+GMainContext *atspi_main_context;
+gboolean atspi_no_cache;
+
+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_collection = ATSPI_DBUS_INTERFACE_COLLECTION;
+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_event_object = ATSPI_DBUS_INTERFACE_EVENT_OBJECT;
+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_table_cell = ATSPI_DBUS_INTERFACE_TABLE_CELL;
+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_TABLE_CELL,
+ ATSPI_DBUS_INTERFACE_TEXT,
+ ATSPI_DBUS_INTERFACE_VALUE,
+ NULL
+};
+
+gint
+_atspi_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;
+}
+
+GHashTable *
+_atspi_get_live_refs (void)
+{
+ if (!live_refs)
+ {
+ live_refs = g_hash_table_new (g_direct_hash, g_direct_equal);
+ }
+ return live_refs;
+}
+
+/* TODO: Add an application parameter */
+DBusConnection *
+_atspi_bus ()
+{
+ if (!bus)
+ atspi_init ();
+ if (!bus)
+ g_error ("AT-SPI: Couldn't connect to accessibility bus. Is at-spi-bus-launcher running?");
+ return bus;
+}
+
+#define APP_IS_REGISTRY(app) (!strcmp (app->bus_name, atspi_bus_registry))
+
+static AtspiAccessible *desktop;
+
+static void
+cleanup ()
+{
+ GHashTable *refs;
+ GList *l;
+
+ refs = live_refs;
+ live_refs = NULL;
+ if (refs)
+ {
+ g_hash_table_destroy (refs);
+ }
+
+ if (bus)
+ {
+ dbus_connection_close (bus);
+ dbus_connection_unref (bus);
+ bus = NULL;
+ }
+
+ if (!desktop)
+ return;
+ for (l = desktop->children; l;)
+ {
+ GList *next = l->next;
+ AtspiAccessible *child = l->data;
+ g_object_run_dispose (G_OBJECT (child->parent.app));
+ g_object_run_dispose (G_OBJECT (child));
+ l = next;
+ }
+ g_object_run_dispose (G_OBJECT (desktop->parent.app));
+ g_object_unref (desktop);
+ desktop = NULL;
+}
+
+static gboolean atspi_inited = FALSE;
+
+static GHashTable *app_hash = NULL;
+
+static void
+handle_get_bus_address (DBusPendingCall *pending, void *user_data)
+{
+ AtspiApplication *app = user_data;
+ DBusMessage *reply = dbus_pending_call_steal_reply (pending);
+ DBusMessage *message;
+ const char *address;
+ DBusPendingCall *new_pending;
+
+ if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+ {
+ if (dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &address,
+ DBUS_TYPE_INVALID) && address [0])
+ {
+ DBusError error;
+ DBusConnection *bus;
+
+ dbus_error_init (&error);
+ bus = dbus_connection_open_private (address, &error);
+ if (bus)
+ {
+ if (app->bus)
+ {
+ dbus_connection_unref (app->bus);
+ }
+ app->bus = bus;
+ }
+ else
+ {
+ g_warning ("Unable to open bus connection: %s", error.message);
+ dbus_error_free (&error);
+ }
+ }
+ }
+ dbus_message_unref (reply);
+ dbus_pending_call_unref (pending);
+
+ if (!app->bus)
+ return; /* application has gone away / been disposed */
+
+ message = dbus_message_new_method_call (app->bus_name,
+ "/org/a11y/atspi/cache",
+ atspi_interface_cache, "GetItems");
+
+ dbus_connection_send_with_reply (app->bus, message, &new_pending, 2000);
+ dbus_message_unref (message);
+ if (!new_pending)
+ return;
+ dbus_pending_call_set_notify (new_pending, handle_get_items, app, NULL);
+}
+
+static AtspiApplication *
+get_application (const char *bus_name)
+{
+ AtspiApplication *app = NULL;
+ char *bus_name_dup;
+ DBusMessage *message;
+ DBusPendingCall *pending = NULL;
+
+ if (!app_hash)
+ {
+ app_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_object_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 = _atspi_application_new (bus_name);
+ app->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ app->bus = dbus_connection_ref (_atspi_bus ());
+ gettimeofday (&app->time_added, NULL);
+ app->cache = ATSPI_CACHE_UNDEFINED;
+ g_hash_table_insert (app_hash, bus_name_dup, app);
+ message = dbus_message_new_method_call (bus_name, atspi_path_root,
+ atspi_interface_application, "GetApplicationBusAddress");
+
+ dbus_connection_send_with_reply (app->bus, message, &pending, 2000);
+ dbus_message_unref (message);
+ if (!pending)
+ {
+ g_hash_table_remove (app_hash, bus_name_dup);
+ return NULL;
+ }
+ dbus_pending_call_set_notify (pending, handle_get_bus_address, app, NULL);
+ return app;
+}
+
+static AtspiAccessible *
+ref_accessible (const char *app_name, const char *path)
+{
+ AtspiApplication *app;
+ AtspiAccessible *a;
+
+ if (!strcmp (path, ATSPI_DBUS_PATH_NULL))
+ return NULL;
+
+ app = get_application (app_name);
+
+ if (!strcmp (path, "/org/a11y/atspi/accessible/root"))
+ {
+ if (!app->root)
+ {
+ app->root = _atspi_accessible_new (app, atspi_path_root);
+ app->root->accessible_parent = atspi_get_desktop (0);
+ app->root->accessible_parent->children = g_list_append (app->root->accessible_parent->children, g_object_ref (app->root));
+ }
+ return g_object_ref (app->root);
+ }
+
+ a = g_hash_table_lookup (app->hash, path);
+ if (a)
+ {
+ return g_object_ref (a);
+ }
+ a = _atspi_accessible_new (app, path);
+ if (!a)
+ return NULL;
+ g_hash_table_insert (app->hash, g_strdup (a->parent.path), g_object_ref (a));
+ return a;
+}
+
+static AtspiHyperlink *
+ref_hyperlink (const char *app_name, const char *path)
+{
+ AtspiApplication *app = get_application (app_name);
+ AtspiHyperlink *hyperlink;
+
+ if (!strcmp (path, ATSPI_DBUS_PATH_NULL))
+ return NULL;
+
+ hyperlink = g_hash_table_lookup (app->hash, path);
+ if (hyperlink)
+ {
+ return g_object_ref (hyperlink);
+ }
+ hyperlink = _atspi_hyperlink_new (app, path);
+ g_hash_table_insert (app->hash, g_strdup (hyperlink->parent.path), hyperlink);
+ /* TODO: This should be a weak ref */
+ g_object_ref (hyperlink); /* for the hash */
+ return hyperlink;
+}
+
+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;
+
+ 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_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &path);
+ app = get_application (sender);
+ a = ref_accessible (sender, path);
+ if (!a)
+ return DBUS_HANDLER_RESULT_HANDLED;
+ g_object_run_dispose (G_OBJECT (a));
+ g_hash_table_remove (app->hash, a->parent.path);
+ g_object_unref (a); /* unref our own ref */
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+handle_name_owner_changed (DBusConnection *bus, DBusMessage *message, void *user_data)
+{
+ const char *name, *new, *old;
+ static gboolean registry_lost = FALSE;
+
+ if (!dbus_message_get_args (message, NULL,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &old,
+ DBUS_TYPE_STRING, &new,
+ DBUS_TYPE_INVALID))
+ {
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ if (!strcmp (name, "org.a11y.atspi.Registry"))
+ {
+ if (registry_lost && !old[0])
+ {
+ _atspi_reregister_event_listeners ();
+ _atspi_reregister_device_listeners ();
+ registry_lost = FALSE;
+ }
+ else if (!new[0])
+ registry_lost = TRUE;
+ }
+ else if (app_hash)
+ {
+ AtspiApplication *app = g_hash_table_lookup (app_hash, old);
+ if (app)
+ g_object_run_dispose (G_OBJECT (app));
+ }
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static gboolean
+add_app_to_desktop (AtspiAccessible *a, const char *bus_name)
+{
+ AtspiAccessible *obj = ref_accessible (bus_name, atspi_path_root);
+ /* The app will be added to the desktop as a side-effect of calling
+ * ref_accessible */
+ g_object_unref (obj);
+ return (obj != NULL);
+}
+
+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_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, path);
+ dbus_message_iter_next (iter);
+}
+
+static void
+add_accessible_from_iter (DBusMessageIter *iter)
+{
+ DBusMessageIter iter_struct, iter_array;
+ const char *app_name, *path;
+ AtspiAccessible *accessible;
+ const char *name, *description;
+ dbus_uint32_t role;
+
+ dbus_message_iter_recurse (iter, &iter_struct);
+
+ /* get accessible */
+ get_reference_from_iter (&iter_struct, &app_name, &path);
+ accessible = ref_accessible (app_name, path);
+ if (!accessible)
+ return;
+
+ /* Get application: TODO */
+ dbus_message_iter_next (&iter_struct);
+
+ /* get parent */
+ get_reference_from_iter (&iter_struct, &app_name, &path);
+ if (accessible->accessible_parent)
+ g_object_unref (accessible->accessible_parent);
+ accessible->accessible_parent = ref_accessible (app_name, path);
+
+ /* Get children */
+ while (accessible->children)
+ {
+ g_object_unref (accessible->children->data);
+ accessible->children = g_list_remove (accessible->children, accessible->children->data);
+ }
+ 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);
+ accessible->children = g_list_append (accessible->children, child);
+ }
+
+ /* interfaces */
+ dbus_message_iter_next (&iter_struct);
+ _atspi_dbus_set_interfaces (accessible, &iter_struct);
+ dbus_message_iter_next (&iter_struct);
+
+ /* name */
+ if (accessible->name)
+ g_free (accessible->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 */
+ if (accessible->description)
+ g_free (accessible->description);
+ dbus_message_iter_get_basic (&iter_struct, &description);
+ accessible->description = g_strdup (description);
+ dbus_message_iter_next (&iter_struct);
+
+ _atspi_dbus_set_state (accessible, &iter_struct);
+ dbus_message_iter_next (&iter_struct);
+
+ _atspi_accessible_add_cache (accessible, ATSPI_CACHE_NAME | ATSPI_CACHE_ROLE |
+ ATSPI_CACHE_PARENT | ATSPI_CACHE_DESCRIPTION);
+ if (!atspi_state_set_contains (accessible->states,
+ ATSPI_STATE_MANAGES_DESCENDANTS))
+ _atspi_accessible_add_cache (accessible, ATSPI_CACHE_CHILDREN);
+
+ /* 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
+handle_get_items (DBusPendingCall *pending, void *user_data)
+{
+ DBusMessage *reply = dbus_pending_call_steal_reply (pending);
+ DBusMessageIter iter, iter_array;
+
+ if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ const char *sender = dbus_message_get_sender (reply);
+ const char *error = NULL;
+ dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &error,
+ DBUS_TYPE_INVALID);
+ g_warning ("AT-SPI: Error in GetItems, sender=%s, error=%s", sender, error);
+ dbus_message_unref (reply);
+ dbus_pending_call_unref (pending);
+ 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)
+ {
+ add_accessible_from_iter (&iter_array);
+ dbus_message_iter_next (&iter_array);
+ }
+ dbus_message_unref (reply);
+ dbus_pending_call_unref (pending);
+}
+
+/* TODO: Do we stil need this function? */
+static AtspiAccessible *
+ref_accessible_desktop (AtspiApplication *app)
+{
+ GError *error;
+ DBusMessage *message, *reply;
+ DBusMessageIter iter, iter_array;
+ gchar *bus_name_dup;
+
+ if (desktop)
+ {
+ g_object_ref (desktop);
+ return desktop;
+ }
+ desktop = _atspi_accessible_new (app, atspi_path_root);
+ if (!desktop)
+ {
+ return NULL;
+ }
+ g_hash_table_insert (app->hash, g_strdup (desktop->parent.path),
+ g_object_ref (desktop));
+ app->root = g_object_ref (desktop);
+ desktop->name = g_strdup ("main");
+ message = dbus_message_new_method_call (atspi_bus_registry,
+ atspi_path_root,
+ atspi_interface_accessible,
+ "GetChildren");
+ if (!message)
+ return NULL;
+ error = NULL;
+ reply = _atspi_dbus_send_with_reply_and_block (message, &error);
+ if (!reply || strcmp (dbus_message_get_signature (reply), "a(so)") != 0)
+ {
+ if (error != NULL)
+ {
+ g_warning ("Couldn't get application list: %s", error->message);
+ g_clear_error (&error);
+ }
+ if (reply)
+ dbus_message_unref (reply);
+ return NULL;
+ }
+ 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_app_to_desktop (desktop, app_name);
+ }
+ dbus_message_unref (reply);
+
+ /* Record the alternate name as an alias for org.a11y.atspi.Registry */
+ bus_name_dup = g_strdup (dbus_message_get_sender (reply));
+ if (bus_name_dup)
+ g_hash_table_insert (app_hash, bus_name_dup, app);
+
+ return g_object_ref (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))
+ {
+ if (!a->root)
+ g_object_unref (ref_accessible_desktop (a)); /* sets a->root */
+ return g_object_ref (a->root);
+ }
+ return ref_accessible (app, path);
+}
+
+AtspiAccessible *
+_atspi_dbus_return_accessible_from_message (DBusMessage *message)
+{
+ DBusMessageIter iter;
+ AtspiAccessible *retval = NULL;
+ const char *signature;
+
+ if (!message)
+ return NULL;
+
+ signature = dbus_message_get_signature (message);
+ if (!strcmp (signature, "(so)"))
+ {
+ dbus_message_iter_init (message, &iter);
+ retval = _atspi_dbus_return_accessible_from_iter (&iter);
+ }
+ else
+ {
+ g_warning ("AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange signature %s", signature);
+ }
+ dbus_message_unref (message);
+ return retval;
+}
+
+AtspiAccessible *
+_atspi_dbus_return_accessible_from_iter (DBusMessageIter *iter)
+{
+ const char *app_name, *path;
+
+ get_reference_from_iter (iter, &app_name, &path);
+ return ref_accessible (app_name, path);
+}
+
+AtspiHyperlink *
+_atspi_dbus_return_hyperlink_from_message (DBusMessage *message)
+{
+ DBusMessageIter iter;
+ AtspiHyperlink *retval = NULL;
+ const char *signature;
+
+ if (!message)
+ return NULL;
+
+ signature = dbus_message_get_signature (message);
+ if (!strcmp (signature, "(so)"))
+ {
+ dbus_message_iter_init (message, &iter);
+ retval = _atspi_dbus_return_hyperlink_from_iter (&iter);
+ }
+ else
+ {
+ g_warning ("AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange signature %s", signature);
+ }
+ dbus_message_unref (message);
+ return retval;
+}
+
+AtspiHyperlink *
+_atspi_dbus_return_hyperlink_from_iter (DBusMessageIter *iter)
+{
+ const char *app_name, *path;
+
+ get_reference_from_iter (iter, &app_name, &path);
+ return ref_hyperlink (app_name, path);
+}
+
+const char *cache_signal_type = "((so)(so)(so)a(so)assusau)";
+
+static DBusHandlerResult
+handle_add_accessible (DBusConnection *bus, DBusMessage *message, void *user_data)
+{
+ DBusMessageIter iter;
+
+ if (strcmp (dbus_message_get_signature (message), cache_signal_type) != 0)
+ {
+ g_warning ("AT-SPI: AddAccessible with unknown signature %s\n",
+ dbus_message_get_signature (message));
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ dbus_message_iter_init (message, &iter);
+ add_accessible_from_iter (&iter);
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+typedef struct
+{
+ DBusConnection *bus;
+ DBusMessage *message;
+ void *data;
+} BusDataClosure;
+
+static GSource *process_deferred_messages_source = NULL;
+
+static void
+process_deferred_message (BusDataClosure *closure)
+{
+ int type = dbus_message_get_type (closure->message);
+ const char *interface = dbus_message_get_interface (closure->message);
+
+ if (type == DBUS_MESSAGE_TYPE_SIGNAL &&
+ !strncmp (interface, "org.a11y.atspi.Event.", 21))
+ {
+ _atspi_dbus_handle_event (closure->bus, closure->message, closure->data);
+ }
+ if (dbus_message_is_method_call (closure->message, atspi_interface_device_event_listener, "NotifyEvent"))
+ {
+ _atspi_dbus_handle_DeviceEvent (closure->bus,
+ closure->message, closure->data);
+ }
+ if (dbus_message_is_signal (closure->message, atspi_interface_cache, "AddAccessible"))
+ {
+ handle_add_accessible (closure->bus, closure->message, closure->data);
+ }
+ if (dbus_message_is_signal (closure->message, atspi_interface_cache, "RemoveAccessible"))
+ {
+ handle_remove_accessible (closure->bus, closure->message, closure->data);
+ }
+ if (dbus_message_is_signal (closure->message, "org.freedesktop.DBus", "NameOwnerChanged"))
+ {
+ handle_name_owner_changed (closure->bus, closure->message, closure->data);
+ }
+}
+
+static GQueue *deferred_messages = NULL;
+
+static gboolean
+process_deferred_messages (void)
+{
+ static int in_process_deferred_messages = 0;
+ BusDataClosure *closure;
+
+ if (in_process_deferred_messages)
+ return TRUE;
+ in_process_deferred_messages = 1;
+ while ((closure = g_queue_pop_head (deferred_messages)))
+ {
+ process_deferred_message (closure);
+ dbus_message_unref (closure->message);
+ dbus_connection_unref (closure->bus);
+ g_free (closure);
+ }
+ in_process_deferred_messages = 0;
+ return FALSE;
+}
+
+static gboolean
+process_deferred_messages_callback (gpointer data)
+{
+ if (process_deferred_messages ())
+ return G_SOURCE_CONTINUE;
+
+ process_deferred_messages_source = NULL;
+ return G_SOURCE_REMOVE;
+}
+
+static DBusHandlerResult
+defer_message (DBusConnection *connection, DBusMessage *message, void *user_data)
+{
+ BusDataClosure *closure = g_new (BusDataClosure, 1);
+
+ closure->bus = dbus_connection_ref (bus);
+ closure->message = dbus_message_ref (message);
+ closure->data = user_data;
+
+ g_queue_push_tail (deferred_messages, closure);
+
+ if (process_deferred_messages_source == NULL)
+ {
+ process_deferred_messages_source = g_idle_source_new ();
+ g_source_set_callback (process_deferred_messages_source,
+ process_deferred_messages_callback, NULL, NULL);
+ g_source_attach (process_deferred_messages_source, atspi_main_context);
+ g_source_unref (process_deferred_messages_source);
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+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);
+
+ if (type == DBUS_MESSAGE_TYPE_SIGNAL &&
+ !strncmp (interface, "org.a11y.atspi.Event.", 21))
+ {
+ return defer_message (bus, message, data);
+ }
+ if (dbus_message_is_method_call (message, atspi_interface_device_event_listener, "NotifyEvent"))
+ {
+ return defer_message (bus, message, data);
+ }
+ if (dbus_message_is_signal (message, atspi_interface_cache, "AddAccessible"))
+ {
+ return defer_message (bus, message, data);
+ }
+ if (dbus_message_is_signal (message, atspi_interface_cache, "RemoveAccessible"))
+ {
+ return defer_message (bus, message, data);
+ }
+ if (dbus_message_is_signal (message, "org.freedesktop.DBus", "NameOwnerChanged"))
+ {
+ defer_message (bus, message, data);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+/*
+ * Returns a 'canonicalized' value for DISPLAY,
+ * with the screen number stripped off if present.
+ *
+ * TODO: Avoid having duplicate functions for this here and in at-spi2-atk
+ */
+static gchar *
+spi_display_name (void)
+{
+ char *canonical_display_name = NULL;
+ const gchar *display_env = g_getenv ("AT_SPI_DISPLAY");
+
+ if (!display_env)
+ {
+ display_env = g_getenv ("DISPLAY");
+ if (!display_env || !display_env[0])
+ return NULL;
+ else
+ {
+ gchar *display_p, *screen_p;
+ canonical_display_name = g_strdup (display_env);
+ display_p = g_utf8_strrchr (canonical_display_name, -1, ':');
+ screen_p = g_utf8_strrchr (canonical_display_name, -1, '.');
+ if (screen_p && display_p && (screen_p > display_p))
+ {
+ *screen_p = '\0';
+ }
+ }
+ }
+ else
+ {
+ canonical_display_name = g_strdup (display_env);
+ }
+
+ return canonical_display_name;
+}
+
+/**
+ * atspi_init:
+ *
+ * Connects to the accessibility registry and initializes the SPI.
+ *
+ * Returns: 0 on success, 1 if already initialized, or an integer error code.
+ **/
+int
+atspi_init (void)
+{
+ char *match;
+ const gchar *no_cache;
+
+ if (atspi_inited)
+ {
+ return 1;
+ }
+
+ atspi_inited = TRUE;
+
+ _atspi_get_live_refs();
+
+ bus = atspi_get_a11y_bus ();
+ if (!bus)
+ return 2;
+ dbus_bus_register (bus, NULL);
+ atspi_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_bus_add_match (bus, match, NULL);
+ g_free (match);
+ match = g_strdup_printf ("type='signal',interface='%s',member='RemoveAccessible'", atspi_interface_cache);
+ dbus_bus_add_match (bus, match, NULL);
+ g_free (match);
+ match = g_strdup_printf ("type='signal',interface='%s',member='ChildrenChanged'", atspi_interface_event_object);
+ dbus_bus_add_match (bus, match, NULL);
+ g_free (match);
+ match = g_strdup_printf ("type='signal',interface='%s',member='PropertyChange'", atspi_interface_event_object);
+ dbus_bus_add_match (bus, match, NULL);
+ g_free (match);
+ match = g_strdup_printf ("type='signal',interface='%s',member='StateChanged'", atspi_interface_event_object);
+ dbus_bus_add_match (bus, match, NULL);
+ g_free (match);
+
+ dbus_bus_add_match (bus,
+ "type='signal', interface='org.freedesktop.DBus', member='NameOwnerChanged'",
+ NULL);
+
+ no_cache = g_getenv ("ATSPI_NO_CACHE");
+ if (no_cache && g_strcmp0 (no_cache, "0") != 0)
+ atspi_no_cache = TRUE;
+
+ deferred_messages = g_queue_new ();
+
+ return 0;
+}
+
+/**
+ * atspi_is_initialized:
+ *
+ * Indicates whether AT-SPI has been initialized.
+ *
+ * Returns: %True if initialized; %False otherwise.
+ */
+gboolean
+atspi_is_initialized ()
+{
+ return atspi_inited;
+}
+
+/**
+ * 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)
+{
+ atspi_main_loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (atspi_main_loop);
+ atspi_main_loop = NULL;
+}
+
+/**
+ * atspi_event_quit:
+ *
+ * Quits the last main event loop for the AT-SPI services,
+ * See: #atspi_event_main
+ **/
+void
+atspi_event_quit (void)
+{
+ g_main_loop_quit (atspi_main_loop);
+}
+
+/**
+ * atspi_exit:
+ *
+ * Disconnects from #AtspiRegistry instances and releases
+ * any floating resources. Call only once at exit.
+ *
+ * Returns: 0 if there were no leaks, otherwise other integer values.
+ **/
+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;
+}
+
+static GSList *hung_processes;
+
+static void
+remove_hung_process (DBusPendingCall *pending, void *data)
+{
+
+ hung_processes = g_slist_remove (hung_processes, data);
+ g_free (data);
+ dbus_pending_call_unref (pending);
+}
+
+static void
+check_for_hang (DBusMessage *message, DBusError *error, DBusConnection *bus, const char *bus_name)
+{
+ if (!message && error->name &&
+ !strcmp (error->name, "org.freedesktop.DBus.Error.NoReply"))
+ {
+ GSList *l;
+ DBusMessage *message;
+ gchar *bus_name_dup;
+ DBusPendingCall *pending = NULL;
+ for (l = hung_processes; l; l = l->next)
+ if (!strcmp (l->data, bus_name))
+ return;
+ message = dbus_message_new_method_call (bus_name, "/",
+ "org.freedesktop.DBus.Peer",
+ "Ping");
+ if (!message)
+ return;
+ dbus_connection_send_with_reply (bus, message, &pending, -1);
+ dbus_message_unref (message);
+ if (!pending)
+ return;
+ bus_name_dup = g_strdup (bus_name);
+ hung_processes = g_slist_append (hung_processes, bus_name_dup);
+ dbus_pending_call_set_notify (pending, remove_hung_process, bus_name_dup, NULL);
+ }
+}
+
+static gboolean
+connection_is_hung (const char *bus_name)
+{
+ GSList *l;
+
+ for (l = hung_processes; l; l = l->next)
+ if (!strcmp (l->data, bus_name))
+ return TRUE;
+ return FALSE;
+}
+
+static gboolean
+check_app (AtspiApplication *app, GError **error)
+{
+ if (!app || !app->bus)
+ {
+ g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_APPLICATION_GONE,
+ _("The application no longer exists"));
+ return FALSE;
+ }
+
+ if (atspi_main_loop && connection_is_hung (app->bus_name))
+ {
+ g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_IPC,
+ "The process appears to be hung.");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+set_timeout (AtspiApplication *app)
+{
+ struct timeval tv;
+ int diff;
+
+ if (app && app_startup_time > 0)
+ {
+ gettimeofday (&tv, NULL);
+ diff = (tv.tv_sec - app->time_added.tv_sec) * 1000 + (tv.tv_usec - app->time_added.tv_usec) / 1000;
+ dbind_set_timeout (MAX(method_call_timeout, app_startup_time - diff));
+ }
+ else
+ dbind_set_timeout (method_call_timeout);
+}
+
+dbus_bool_t
+_atspi_dbus_call (gpointer obj, const char *interface, const char *method, GError **error, const char *type, ...)
+{
+ va_list args;
+ dbus_bool_t retval;
+ DBusError err;
+ AtspiObject *aobj = ATSPI_OBJECT (obj);
+
+ if (!check_app (aobj->app, error))
+ return FALSE;
+
+ if (!allow_sync)
+ {
+ _atspi_set_error_no_sync (error);
+ return FALSE;
+ }
+
+ va_start (args, type);
+ dbus_error_init (&err);
+ set_timeout (aobj->app);
+ retval = dbind_method_call_reentrant_va (aobj->app->bus, aobj->app->bus_name,
+ aobj->path, interface, method, &err,
+ type, args);
+ va_end (args);
+ check_for_hang (NULL, &err, aobj->app->bus, aobj->app->bus_name);
+ process_deferred_messages ();
+ if (dbus_error_is_set (&err))
+ {
+ g_set_error(error, ATSPI_ERROR, ATSPI_ERROR_IPC, "%s", err.message);
+ dbus_error_free (&err);
+ }
+ return retval;
+}
+
+DBusMessage *
+_atspi_dbus_call_partial (gpointer obj,
+ const char *interface,
+ const char *method,
+ GError **error,
+ const char *type, ...)
+{
+ va_list args;
+
+ va_start (args, type);
+ return _atspi_dbus_call_partial_va (obj, interface, method, error, type, args);
+}
+
+
+DBusMessage *
+_atspi_dbus_call_partial_va (gpointer obj,
+ const char *interface,
+ const char *method,
+ GError **error,
+ const char *type,
+ va_list args)
+{
+ AtspiObject *aobj = ATSPI_OBJECT (obj);
+ DBusError err;
+ DBusMessage *msg = NULL, *reply = NULL;
+ DBusMessageIter iter;
+ const char *p;
+
+ dbus_error_init (&err);
+
+ if (!check_app (aobj->app, error))
+ goto out;
+
+ msg = dbus_message_new_method_call (aobj->app->bus_name, aobj->path, interface, method);
+ if (!msg)
+ goto out;
+
+ p = type;
+ dbus_message_iter_init_append (msg, &iter);
+ dbind_any_marshal_va (&iter, &p, args);
+
+ set_timeout (aobj->app);
+ reply = dbind_send_and_allow_reentry (aobj->app->bus, msg, &err);
+ check_for_hang (reply, &err, aobj->app->bus, aobj->app->bus_name);
+out:
+ va_end (args);
+ if (msg)
+ dbus_message_unref (msg);
+ process_deferred_messages ();
+ if (dbus_error_is_set (&err))
+ {
+ /* TODO: Set gerror */
+ dbus_error_free (&err);
+ }
+
+ if (reply && dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ const char *err_str = NULL;
+ dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &err_str, DBUS_TYPE_INVALID);
+ if (err_str)
+ g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_IPC, err_str);
+ dbus_message_unref (reply);
+ return NULL;
+ }
+
+ return reply;
+}
+
+dbus_bool_t
+_atspi_dbus_get_property (gpointer 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;
+ AtspiObject *aobj = ATSPI_OBJECT (obj);
+ char expected_type = (type [0] == '(' ? 'r' : type [0]);
+
+ if (!aobj)
+ return FALSE;
+
+ if (!check_app (aobj->app, error))
+ return FALSE;
+
+ if (!allow_sync)
+ {
+ _atspi_set_error_no_sync (error);
+ return FALSE;
+ }
+
+ message = dbus_message_new_method_call (aobj->app->bus_name,
+ aobj->path,
+ "org.freedesktop.DBus.Properties",
+ "Get");
+ if (!message)
+ {
+ // TODO: throw exception
+ return FALSE;
+ }
+ dbus_message_append_args (message, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
+ dbus_error_init (&err);
+ set_timeout (aobj->app);
+ reply = dbind_send_and_allow_reentry (aobj->app->bus, message, &err);
+ check_for_hang (reply, &err, aobj->app->bus, aobj->app->bus_name);
+ dbus_message_unref (message);
+ process_deferred_messages ();
+ if (!reply)
+ {
+ // TODO: throw exception
+ goto done;
+ }
+
+ if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ const char *err_str = NULL;
+ dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &err_str, DBUS_TYPE_INVALID);
+ if (err_str)
+ g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_IPC, err_str);
+ goto done;
+ }
+
+ dbus_message_iter_init (reply, &iter);
+ if (dbus_message_iter_get_arg_type (&iter) != 'v')
+ {
+ g_warning ("AT-SPI: expected a variant when fetching %s from interface %s; got %s\n", name, interface, dbus_message_get_signature (reply));
+ goto done;
+ }
+ dbus_message_iter_recurse (&iter, &iter_variant);
+ if (dbus_message_iter_get_arg_type (&iter_variant) != expected_type)
+ {
+ g_warning ("atspi_dbus_get_property: Wrong type: expected %s, got %c\n", type, dbus_message_iter_get_arg_type (&iter_variant));
+ goto done;
+ }
+ if (!strcmp (type, "(so)"))
+ {
+ *((AtspiAccessible **)data) = _atspi_dbus_return_accessible_from_iter (&iter_variant);
+ }
+ else
+ {
+ dbus_message_iter_get_basic (&iter_variant, data);
+ if (type [0] == 's')
+ *(char **)data = g_strdup (*(char **)data);
+ }
+ retval = TRUE;
+done:
+ dbus_error_free (&err);
+ if (reply)
+ dbus_message_unref (reply);
+ return retval;
+}
+
+DBusMessage *
+_atspi_dbus_send_with_reply_and_block (DBusMessage *message, GError **error)
+{
+ DBusMessage *reply;
+ DBusError err;
+ AtspiApplication *app;
+ DBusConnection *bus;
+
+ app = get_application (dbus_message_get_destination (message));
+
+ if (app && !app->bus)
+ return NULL; /* will fail anyway; app has been disposed */
+
+ bus = (app ? app->bus : _atspi_bus());
+ dbus_error_init (&err);
+ set_timeout (app);
+ reply = dbind_send_and_allow_reentry (bus, message, &err);
+ process_deferred_messages ();
+ dbus_message_unref (message);
+ if (dbus_error_is_set (&err))
+ {
+ if (error)
+ g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_IPC, err.message);
+ dbus_error_free (&err);
+ }
+ return reply;
+}
+
+GHashTable *
+_atspi_dbus_return_hash_from_message (DBusMessage *message)
+{
+ DBusMessageIter iter;
+ GHashTable *ret;
+
+ if (!message)
+ return NULL;
+
+ _ATSPI_DBUS_CHECK_SIG (message, "a{ss}", NULL, NULL);
+
+ dbus_message_iter_init (message, &iter);
+ ret = _atspi_dbus_hash_from_iter (&iter);
+ dbus_message_unref (message);
+ return ret;
+}
+
+GHashTable *
+_atspi_dbus_hash_from_iter (DBusMessageIter *iter)
+{
+ GHashTable *hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+ DBusMessageIter iter_array, iter_dict;
+
+ dbus_message_iter_recurse (iter, &iter_array);
+ while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+ {
+ const char *name, *value;
+ dbus_message_iter_recurse (&iter_array, &iter_dict);
+ dbus_message_iter_get_basic (&iter_dict, &name);
+ dbus_message_iter_next (&iter_dict);
+ dbus_message_iter_get_basic (&iter_dict, &value);
+ g_hash_table_insert (hash, g_strdup (name), g_strdup (value));
+ dbus_message_iter_next (&iter_array);
+ }
+ return hash;
+}
+
+GArray *
+_atspi_dbus_return_attribute_array_from_message (DBusMessage *message)
+{
+ DBusMessageIter iter;
+ GArray *ret;
+
+ if (!message)
+ return NULL;
+
+ _ATSPI_DBUS_CHECK_SIG (message, "a{ss}", NULL, NULL);
+
+ dbus_message_iter_init (message, &iter);
+
+ ret = _atspi_dbus_attribute_array_from_iter (&iter);
+ dbus_message_unref (message);
+ return ret;
+}
+
+GArray *
+_atspi_dbus_attribute_array_from_iter (DBusMessageIter *iter)
+{
+ DBusMessageIter iter_array, iter_dict;
+ GArray *array = g_array_new (TRUE, TRUE, sizeof (gchar *));
+
+ dbus_message_iter_recurse (iter, &iter_array);
+ while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+ {
+ const char *name, *value;
+ gchar *str;
+ dbus_message_iter_recurse (&iter_array, &iter_dict);
+ dbus_message_iter_get_basic (&iter_dict, &name);
+ dbus_message_iter_next (&iter_dict);
+ dbus_message_iter_get_basic (&iter_dict, &value);
+ str = g_strdup_printf ("%s:%s", name, value);
+ array = g_array_append_val (array, str);
+ dbus_message_iter_next (&iter_array);;
+ }
+ return array;
+}
+
+void
+_atspi_dbus_set_interfaces (AtspiAccessible *accessible, DBusMessageIter *iter)
+{
+ DBusMessageIter iter_array;
+ char *iter_sig = dbus_message_iter_get_signature (iter);
+
+ accessible->interfaces = 0;
+ if (strcmp (iter_sig, "as") != 0)
+ {
+ g_warning ("_atspi_dbus_set_interfaces: Passed iterator with invalid signature %s", dbus_message_iter_get_signature (iter));
+ dbus_free (iter_sig);
+ return;
+ }
+ dbus_free (iter_sig);
+ dbus_message_iter_recurse (iter, &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 = _atspi_get_iface_num (iface);
+ if (n == -1)
+ {
+ g_warning ("AT-SPI: Unknown interface %s", iface);
+ }
+ else
+ accessible->interfaces |= (1 << n);
+ dbus_message_iter_next (&iter_array);
+ }
+ _atspi_accessible_add_cache (accessible, ATSPI_CACHE_INTERFACES);
+}
+
+void
+_atspi_dbus_set_state (AtspiAccessible *accessible, DBusMessageIter *iter)
+{
+ DBusMessageIter iter_array;
+ gint count;
+ dbus_uint32_t *states;
+
+ dbus_message_iter_recurse (iter, &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);
+ if (!accessible->states)
+ accessible->states = _atspi_state_set_new_internal (accessible, 0);
+ }
+ else
+ {
+ guint64 val = ((guint64)states [1]) << 32;
+ val += states [0];
+ if (!accessible->states)
+ accessible->states = _atspi_state_set_new_internal (accessible, val);
+ else
+ accessible->states->states = val;
+ }
+ _atspi_accessible_add_cache (accessible, ATSPI_CACHE_STATES);
+}
+
+GQuark
+_atspi_error_quark (void)
+{
+ return g_quark_from_static_string ("atspi_error");
+}
+
+/*
+ * Gets the IOR from the XDisplay.
+ */
+#ifdef HAVE_X11
+static char *
+get_accessibility_bus_address_x11 (void)
+{
+ Atom AT_SPI_BUS;
+ Atom actual_type;
+ Display *bridge_display = NULL;
+ int actual_format;
+ char *data;
+ unsigned char *data_x11 = NULL;
+ unsigned long nitems;
+ unsigned long leftover;
+ char *display_name;
+
+ display_name = spi_display_name ();
+ if (!display_name)
+ return NULL;
+
+ bridge_display = XOpenDisplay (display_name);
+ g_free (display_name);
+
+ if (!bridge_display)
+ {
+ g_warning ("Could not open X display");
+ return NULL;
+ }
+
+ AT_SPI_BUS = XInternAtom (bridge_display, "AT_SPI_BUS", False);
+ XGetWindowProperty (bridge_display,
+ XDefaultRootWindow (bridge_display),
+ AT_SPI_BUS, 0L,
+ (long) BUFSIZ, False,
+ (Atom) 31, &actual_type, &actual_format,
+ &nitems, &leftover, &data_x11);
+ XCloseDisplay (bridge_display);
+
+ data = g_strdup ((gchar *)data_x11);
+ XFree (data_x11);
+ return data;
+}
+#endif
+
+static char *
+get_accessibility_bus_address_dbus (void)
+{
+ DBusConnection *session_bus = NULL;
+ DBusMessage *message;
+ DBusMessage *reply;
+ DBusError error;
+ char *address = NULL;
+
+ session_bus = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+ if (!session_bus)
+ return NULL;
+
+ message = dbus_message_new_method_call ("org.a11y.Bus",
+ "/org/a11y/bus",
+ "org.a11y.Bus",
+ "GetAddress");
+
+ dbus_error_init (&error);
+ reply = dbus_connection_send_with_reply_and_block (session_bus,
+ message,
+ -1,
+ &error);
+ dbus_message_unref (message);
+
+ if (!reply)
+ {
+ g_warning ("Error retrieving accessibility bus address: %s: %s",
+ error.name, error.message);
+ dbus_error_free (&error);
+ return NULL;
+ }
+
+ {
+ const char *tmp_address;
+ if (!dbus_message_get_args (reply,
+ NULL,
+ DBUS_TYPE_STRING,
+ &tmp_address,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (reply);
+ return NULL;
+ }
+ address = g_strdup (tmp_address);
+ dbus_message_unref (reply);
+ }
+
+ return address;
+}
+
+static DBusConnection *a11y_bus;
+static dbus_int32_t a11y_dbus_slot = -1;
+
+static void
+a11y_bus_free (void *data)
+{
+ if (data == a11y_bus)
+ {
+ a11y_bus = NULL;
+ dbus_connection_free_data_slot (&a11y_dbus_slot);
+ }
+}
+
+/**
+ * atspi_get_a11y_bus: (skip)
+ */
+DBusConnection *
+atspi_get_a11y_bus (void)
+{
+ DBusError error;
+ char *address = NULL;
+
+ if (a11y_bus && dbus_connection_get_is_connected (a11y_bus))
+ return a11y_bus;
+
+ if (a11y_dbus_slot == -1)
+ if (!dbus_connection_allocate_data_slot (&a11y_dbus_slot))
+ g_warning ("at-spi: Unable to allocate D-Bus slot");
+
+#ifdef HAVE_X11
+ address = get_accessibility_bus_address_x11 ();
+#endif
+ if (!address)
+ address = get_accessibility_bus_address_dbus ();
+ if (!address)
+ return NULL;
+
+ dbus_error_init (&error);
+ a11y_bus = dbus_connection_open_private (address, &error);
+ g_free (address);
+
+ if (!a11y_bus)
+ {
+ g_warning ("Couldn't connect to accessibility bus: %s", error.message);
+ dbus_error_free (&error);
+ return NULL;
+ }
+ else
+ {
+ if (!dbus_bus_register (a11y_bus, &error))
+ {
+ g_warning ("Couldn't register with accessibility bus: %s", error.message);
+ dbus_error_free (&error);
+ dbus_connection_close (a11y_bus);
+ dbus_connection_unref (a11y_bus);
+ a11y_bus = NULL;
+ return NULL;
+ }
+ }
+
+ /* Simulate a weak ref on the bus */
+ dbus_connection_set_data (a11y_bus, a11y_dbus_slot, a11y_bus, a11y_bus_free);
+
+ return a11y_bus;
+}
+
+/**
+ * atspi_set_timeout:
+ * @val: The timeout value, in milliseconds, or -1 to disable the timeout.
+ * @startup_time: The amount of time, in milliseconds, to allow to pass
+ * before enforcing timeouts on an application. Can be used to prevent
+ * timeout exceptions if an application is likely to block for an extended
+ * period of time on initialization. -1 can be passed to disable this
+ * behavior.
+ *
+ * Set the timeout used for method calls. If this is not set explicitly,
+ * a default of 0.8 ms is used.
+ * Note that at-spi2-registryd currently uses a timeout of 3 seconds when
+ * sending a keyboard event notification. This means that, if an AT makes
+ * a call in response to the keyboard notification and the application
+ * being called does not respond before the timeout is reached,
+ * at-spi2-registryd will time out on the keyboard event notification and
+ * pass the key onto the application (ie, reply to indicate that the key
+ * was not consumed), so this may make it undesirable to set a timeout
+ * larger than 3 seconds.
+ *
+ * By default, the normal timeout is set to 800 ms, and the application startup
+ * timeout is set to 15 seconds.
+ */
+void
+atspi_set_timeout (gint val, gint startup_time)
+{
+ method_call_timeout = val;
+ app_startup_time = startup_time;
+}
+
+/**
+ * atspi_set_main_context:
+ * @cnx: The #GMainContext to use.
+ *
+ * Sets the main loop context that AT-SPI should assume is in use when
+ * setting an idle callback.
+ * This function should be called by application-side implementors (ie,
+ * at-spi2-atk) when it is desirable to re-enter the main loop.
+ */
+void
+atspi_set_main_context (GMainContext *cnx)
+{
+ if (atspi_main_context == cnx)
+ return;
+ if (process_deferred_messages_source != NULL)
+ {
+ g_source_destroy (process_deferred_messages_source);
+ process_deferred_messages_source = g_idle_source_new ();
+ g_source_set_callback (process_deferred_messages_source,
+ process_deferred_messages_callback, NULL, NULL);
+ g_source_attach (process_deferred_messages_source, cnx);
+ g_source_unref (process_deferred_messages_source);
+ }
+ atspi_main_context = cnx;
+ atspi_dbus_connection_setup_with_g_main (atspi_get_a11y_bus (), cnx);
+}
+
+#ifdef DEBUG_REF_COUNTS
+static void
+print_disposed (gpointer key, gpointer value, gpointer data)
+{
+ AtspiAccessible *accessible = key;
+ if (accessible->parent.app)
+ return;
+ g_print ("disposed: %s %d\n", accessible->name, accessible->role);
+}
+
+void
+debug_disposed ()
+{
+ g_hash_table_foreach (live_refs, print_disposed, NULL);
+}
+#endif
+
+gchar *
+_atspi_name_compat (gchar *name)
+{
+ gchar *p = name;
+
+ while (*p)
+ {
+ if (*p == '-')
+ *p = ' ';
+ p++;
+ }
+ return name;
+}
+
+/**
+ * atspi_role_get_name:
+ * @role: an #AtspiRole object to query.
+ *
+ * Gets a localizable string that indicates the name of an #AtspiRole.
+ * <em>DEPRECATED.</em>
+ *
+ * Returns: a localizable string name for an #AtspiRole enumerated type.
+ **/
+gchar *
+atspi_role_get_name (AtspiRole role)
+{
+ gchar *retval = NULL;
+ GTypeClass *type_class;
+ GEnumValue *value;
+
+ type_class = g_type_class_ref (ATSPI_TYPE_ROLE);
+ g_return_val_if_fail (G_IS_ENUM_CLASS (type_class), NULL);
+
+ value = g_enum_get_value (G_ENUM_CLASS (type_class), role);
+
+ if (value)
+ {
+ retval = g_strdup (value->value_nick);
+ }
+
+ g_type_class_unref (type_class);
+
+ if (retval)
+ return _atspi_name_compat (retval);
+
+ return NULL;
+}
+
+GHashTable *
+_atspi_dbus_update_cache_from_dict (AtspiAccessible *accessible, DBusMessageIter *iter)
+{
+ GHashTable *cache = _atspi_accessible_ref_cache (accessible);
+ DBusMessageIter iter_dict, iter_dict_entry, iter_struct, iter_variant;
+
+ dbus_message_iter_recurse (iter, &iter_dict);
+ while (dbus_message_iter_get_arg_type (&iter_dict) != DBUS_TYPE_INVALID)
+ {
+ const char *key;
+ GValue *val = NULL;
+ dbus_message_iter_recurse (&iter_dict, &iter_dict_entry);
+ dbus_message_iter_get_basic (&iter_dict_entry, &key);
+ dbus_message_iter_next (&iter_dict_entry);
+ dbus_message_iter_recurse (&iter_dict_entry, &iter_variant);
+ if (!strcmp (key, "interfaces"))
+ {
+ _atspi_dbus_set_interfaces (accessible, &iter_variant);
+ }
+ else if (!strcmp (key, "Attributes"))
+ {
+ char *iter_sig = dbus_message_iter_get_signature (&iter_variant);
+ val = g_new0 (GValue, 1);;
+ g_value_init (val, G_TYPE_HASH_TABLE);
+ if (strcmp (iter_sig, "a{ss}") != 0)
+ {
+ dbus_free (iter_sig);
+ break;
+ }
+ dbus_free (iter_sig);
+ g_value_take_boxed (val, _atspi_dbus_hash_from_iter (&iter_variant));
+ }
+ else if (!strcmp (key, "Component.ScreenExtents"))
+ {
+ dbus_int32_t d_int;
+ AtspiRect extents;
+ char *iter_sig = dbus_message_iter_get_signature (&iter_variant);
+ val = g_new0 (GValue, 1);;
+ g_value_init (val, ATSPI_TYPE_RECT);
+ if (strcmp (iter_sig, "(iiii)") != 0)
+ {
+ dbus_free (iter_sig);
+ break;
+ }
+ dbus_free (iter_sig);
+ dbus_message_iter_recurse (&iter_variant, &iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &d_int);
+ extents.x = d_int;
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &d_int);
+ extents.y = d_int;
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &d_int);
+ extents.width = d_int;
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &d_int);
+ extents.height = d_int;
+ g_value_set_boxed (val, &extents);
+ }
+ if (val)
+ g_hash_table_insert (cache, g_strdup (key), val);
+ dbus_message_iter_next (&iter_dict);
+ }
+
+ return cache;
+}
+
+gboolean
+_atspi_get_allow_sync ()
+{
+ return allow_sync;
+}
+
+gboolean
+_atspi_set_allow_sync (gboolean val)
+{
+ gboolean ret = allow_sync;
+
+ allow_sync = val;
+ return ret;
+}
+
+void
+_atspi_set_error_no_sync (GError **error)
+{
+ g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_SYNC_NOT_ALLOWED,
+ _("Attempted synchronous call where prohibited"));
+}
diff --git a/atspi/atspi-misc.h b/atspi/atspi-misc.h
new file mode 100644
index 0000000..f13596f
--- /dev/null
+++ b/atspi/atspi-misc.h
@@ -0,0 +1,52 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_
+
+G_BEGIN_DECLS
+
+int atspi_init (void);
+gboolean atspi_is_initialized (void);
+
+void atspi_event_main ();
+
+void atspi_event_quit ();
+
+int atspi_exit ();
+
+DBusConnection *
+atspi_get_a11y_bus ();
+
+void
+atspi_set_timeout (gint val, gint startup_time);
+
+void
+atspi_set_main_context (GMainContext *cnx);
+
+gchar * atspi_role_get_name (AtspiRole role);
+G_END_DECLS
+
+#endif /* _ATSPI_MISC_H_ */
diff --git a/atspi/atspi-object.c b/atspi/atspi-object.c
new file mode 100644
index 0000000..3545845
--- /dev/null
+++ b/atspi/atspi-object.c
@@ -0,0 +1,64 @@
+/*
+ * 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 (AtspiObject, atspi_object, G_TYPE_OBJECT)
+
+static void
+atspi_object_init (AtspiObject *obj)
+{
+}
+
+static void
+atspi_object_dispose (GObject *object)
+{
+ AtspiObject *aobj = ATSPI_OBJECT (object);
+
+ if (aobj->app)
+ {
+ g_object_unref (aobj->app);
+ aobj->app = NULL;
+ }
+
+ G_OBJECT_CLASS (atspi_object_parent_class)->dispose (object);
+}
+
+static void
+atspi_object_finalize (GObject *object)
+{
+ AtspiObject *aobj = ATSPI_OBJECT (object);
+
+ g_free (aobj->path);
+
+ G_OBJECT_CLASS (atspi_object_parent_class)->finalize (object);
+}
+
+static void
+atspi_object_class_init (AtspiObjectClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = atspi_object_dispose;
+ object_class->finalize = atspi_object_finalize;
+}
diff --git a/atspi/atspi-object.h b/atspi/atspi-object.h
new file mode 100644
index 0000000..69dd551
--- /dev/null
+++ b/atspi/atspi-object.h
@@ -0,0 +1,60 @@
+/*
+ * 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_OBJECT_H_
+#define _ATSPI_OBJECT_H_
+
+#include "glib-object.h"
+
+#include "atspi-application.h"
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+#define ATSPI_TYPE_OBJECT (atspi_object_get_type ())
+#define ATSPI_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_OBJECT, AtspiObject))
+#define ATSPI_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_OBJECT, AtspiObjectClass))
+#define ATSPI_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_OBJECT))
+#define ATSPI_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_OBJECT))
+#define ATSPI_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_OBJECT, AtspiObjectClass))
+
+typedef struct _AtspiObject AtspiObject;
+struct _AtspiObject
+{
+ GObject parent;
+ AtspiApplication *app;
+ char *path;
+};
+
+typedef struct _AtspiObjectClass AtspiObjectClass;
+struct _AtspiObjectClass
+{
+ GObjectClass parent_class;
+};
+
+GType atspi_object_get_type (void);
+
+G_END_DECLS
+
+#endif /* _ATSPI_OBJECT_H_ */
diff --git a/atspi/atspi-private.h b/atspi/atspi-private.h
new file mode 100644
index 0000000..2cf5693
--- /dev/null
+++ b/atspi/atspi-private.h
@@ -0,0 +1,43 @@
+/*
+ * 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 <config.h>
+#include "atspi-device-listener-private.h"
+#include "atspi-event-listener-private.h"
+#include "atspi-matchrule-private.h"
+#include "atspi-misc-private.h"
+
+#include "glib/gi18n.h"
+
+#include "atspi.h"
+#include "atspi-accessible-private.h"
+
+G_BEGIN_DECLS
+void _atspi_reregister_device_listeners ();
+G_END_DECLS
+
+#endif /* _ATSPI_PRIVATE_H_ */
diff --git a/atspi/atspi-registry.c b/atspi/atspi-registry.c
new file mode 100644
index 0000000..759a1aa
--- /dev/null
+++ b/atspi/atspi-registry.c
@@ -0,0 +1,545 @@
+
+/*
+ * 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"
+
+typedef struct
+{
+ AtspiDeviceListener *listener;
+ GArray *key_set;
+ AtspiKeyMaskType modmask;
+ AtspiKeyEventMask event_types;
+ gint sync_type;
+} DeviceListenerEntry;
+
+static GList *device_listeners;
+
+/**
+ * atspi_get_desktop_count:
+ *
+ * Gets the number of virtual desktops.
+ * NOTE: multiple virtual desktops are not implemented yet; as a
+ * consequence, this function always returns 1.
+ *
+ * Returns: a #gint indicating the number of active virtual desktops.
+ **/
+gint
+atspi_get_desktop_count ()
+{
+ return 1;
+}
+
+/**
+ * atspi_get_desktop:
+ * @i: a #gint indicating which of the accessible desktops is to be returned.
+ *
+ * Gets the virtual desktop indicated by index @i.
+ * NOTE: currently multiple virtual desktops are not implemented;
+ * as a consequence, any @i value different from 0 will not return a
+ * virtual desktop - instead it will return NULL.
+ *
+ * Returns: (transfer full): 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:
+ *
+ * Gets 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.
+ * NOTE: currently multiple virtual desktops are not implemented;
+ * this implementation always returns a #Garray with a single
+ * #AtspiAccessible desktop.
+ *
+ * Returns: (element-type AtspiAccessible*) (transfer full): a #GArray of
+ * desktops.
+ **/
+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;
+}
+
+static gboolean
+notify_keystroke_listener (DeviceListenerEntry *e)
+{
+ gchar *path = _atspi_device_listener_get_path (e->listener);
+ dbus_uint32_t d_modmask = e->modmask;
+ dbus_uint32_t d_event_types = e->event_types;
+ AtspiEventListenerMode listener_mode;
+ gboolean retval = FALSE;
+ DBusError d_error;
+
+ listener_mode.synchronous =
+ (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_SYNCHRONOUS)!=0);
+ listener_mode.preemptive =
+ (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_CANCONSUME)!=0);
+ listener_mode.global =
+ (dbus_bool_t) ((e->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, e->key_set,
+ d_modmask, d_event_types, &listener_mode,
+ &retval);
+ if (dbus_error_is_set (&d_error))
+ {
+ g_warning ("RegisterKeystrokeListener failed: %s", d_error.message);
+ dbus_error_free (&d_error);
+ }
+
+ g_free (path);
+
+ return retval;
+}
+
+static void
+device_listener_entry_free (DeviceListenerEntry *e)
+{
+ g_array_free (e->key_set, TRUE);
+ g_free (e);
+}
+
+static void
+unregister_listener (gpointer data, GObject *object)
+{
+ GList *l;
+ AtspiDeviceListener *listener = ATSPI_DEVICE_LISTENER (object);
+
+ for (l = device_listeners; l;)
+ {
+ DeviceListenerEntry *e = l->data;
+ if (e->listener == listener)
+ {
+ GList *next = l->next;
+ device_listener_entry_free (e);
+ device_listeners = g_list_delete_link (device_listeners, l);
+ l = next;
+ }
+ else
+ l = l->next;
+ }
+}
+
+/**
+ * atspi_register_keystroke_listener:
+ * @listener: a pointer to the #AtspiDeviceListener for which
+ * keystroke events are requested.
+ * @key_set: (element-type AtspiKeyDefinition) (allow-none): a pointer to the
+ * #AtspiKeyDefinition array indicating which keystroke events are
+ * requested, or NULL
+ * to indicate that all keycodes and keyvals for the specified
+ * modifier set are to be included.
+ * @modmask: an #AtspiKeyMaskType 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
+ * #atspi_register_keystroke_listener once for each
+ * combination.
+ * @event_types: an #AtspiKeyMaskType mask indicating which
+ * types of key events are requested (%ATSPI_KEY_PRESSED etc.).
+ * @sync_type: an #AtspiKeyListenerSyncType parameter indicating
+ * the behavior of the notification/listener transaction.
+ * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
+ *
+ * Registers 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_keystroke_listener (AtspiDeviceListener *listener,
+ GArray *key_set,
+ AtspiKeyMaskType modmask,
+ AtspiKeyEventMask event_types,
+ AtspiKeyListenerSyncType sync_type,
+ GError **error)
+{
+ DeviceListenerEntry *e;
+
+ g_return_val_if_fail (listener != NULL, FALSE);
+
+ e = g_new0 (DeviceListenerEntry, 1);
+ e->listener = listener;
+ e->modmask = modmask;
+ e->event_types = event_types;
+ e->sync_type = sync_type;
+ if (key_set)
+ {
+ gint i;
+ e->key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition),
+ key_set->len);
+ e->key_set->len = key_set->len;
+ for (i = 0; i < key_set->len; i++)
+ {
+ AtspiKeyDefinition *kd = ((AtspiKeyDefinition *) key_set->data) + i;
+ AtspiKeyDefinition *d_kd = ((AtspiKeyDefinition *) e->key_set->data) + i;
+ d_kd->keycode = kd->keycode;
+ d_kd->keysym = kd->keysym;
+ if (kd->keystring)
+ {
+ d_kd->keystring = kd->keystring;
+ }
+ else
+ {
+ d_kd->keystring = "";
+ }
+ }
+ }
+ else
+ {
+ e->key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0);
+ }
+
+ g_object_weak_ref (G_OBJECT (listener), unregister_listener, NULL);
+ device_listeners = g_list_prepend (device_listeners, e);
+ return notify_keystroke_listener (e);
+}
+
+/**
+ * atspi_deregister_keystroke_listener:
+ * @listener: a pointer to the #AtspiDeviceListener for which
+ * keystroke events are requested.
+ * @key_set: (element-type AtspiKeyDefinition) (allow-none): a pointer to the
+ * #AtspiKeyDefinition array indicating which keystroke events are
+ * requested, or %NULL
+ * to indicate that all keycodes and keyvals for the specified
+ * modifier set are to be included.
+ * @modmask: the key modifier mask for which this listener is to be
+ * 'deregistered' (of type #AtspiKeyMaskType).
+ * @event_types: an #AtspiKeyMaskType mask indicating which
+ * types of key events were requested (%ATSPI_KEY_PRESSED, etc.).
+ * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
+ *
+ * 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_keystroke_listener (AtspiDeviceListener *listener,
+ GArray *key_set,
+ AtspiKeyMaskType modmask,
+ AtspiKeyEventMask event_types,
+ GError **error)
+{
+ GArray *d_key_set;
+ gchar *path;
+ gint i;
+ dbus_uint32_t d_modmask = modmask;
+ dbus_uint32_t d_event_types = event_types;
+ DBusError d_error;
+ GList *l;
+
+ dbus_error_init (&d_error);
+ if (!listener)
+ {
+ return FALSE;
+ }
+ path = _atspi_device_listener_get_path (listener);
+
+ /* copy the keyval filter values from the C api into the DBind KeySet */
+ if (key_set)
+ {
+ d_key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), key_set->len);
+ d_key_set->len = key_set->len;
+ for (i = 0; i < key_set->len; ++i)
+ {
+ AtspiKeyDefinition *kd = ((AtspiKeyDefinition *) key_set->data) + i;
+ AtspiKeyDefinition *d_kd = ((AtspiKeyDefinition *) d_key_set->data) + i;
+ d_kd->keycode = kd->keycode;
+ d_kd->keysym = kd->keysym;
+ if (kd->keystring)
+ {
+ d_kd->keystring = kd->keystring;
+ }
+ else
+ {
+ d_kd->keystring = "";
+ }
+ }
+ }
+ else
+ {
+ d_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, d_key_set, d_modmask,
+ d_event_types);
+ if (dbus_error_is_set (&d_error))
+ {
+ g_warning ("DeregisterKeystrokeListener failed: %s", d_error.message);
+ dbus_error_free (&d_error);
+ }
+
+ unregister_listener (listener, NULL);
+ for (l = device_listeners; l;)
+ {
+ /* TODO: This code is all wrong / doesn't match what is in
+ * deviceeventcontroller.c. It would be nice to deprecate these methods
+ * in favor of methods that return an ID for the registration that can
+ * be passed to a deregister function, for instance. */
+ DeviceListenerEntry *e = l->data;
+ if (e->modmask == modmask && e->event_types == event_types)
+ {
+ GList *next = l->next;
+ device_listener_entry_free (e);
+ device_listeners = g_list_delete_link (device_listeners, l);
+ l = next;
+ }
+ else
+ l = l->next;
+ }
+ g_array_free (d_key_set, TRUE);
+ g_free (path);
+ return TRUE;
+}
+
+/**
+ * atspi_register_device_event_listener:
+ * @listener: a pointer to the #AtspiDeviceListener which requests
+ * the events.
+ * @event_types: an #AtspiDeviceEventMask mask indicating which
+ * types of key events are requested (%ATSPI_KEY_PRESSED, etc.).
+ * @filter: (allow-none): Unused parameter.
+ * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
+ *
+ * Registers 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_types,
+ void *filter, GError **error)
+{
+ gboolean retval = FALSE;
+ dbus_uint32_t d_event_types = event_types;
+ gchar *path;
+ DBusError d_error;
+
+ dbus_error_init (&d_error);
+ if (!listener)
+ {
+ return retval;
+ }
+ path = _atspi_device_listener_get_path (listener);
+
+ dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "RegisterDeviceEventListener", &d_error, "ou=>b", path, d_event_types, &retval);
+ if (dbus_error_is_set (&d_error))
+ {
+ g_warning ("RegisterDeviceEventListener failed: %s", d_error.message);
+ dbus_error_free (&d_error);
+ }
+
+ g_free (path);
+ return retval;
+}
+
+/**
+ * atspi_deregister_device_event_listener:
+ * @listener: a pointer to the #AtspiDeviceListener for which
+ * device events are requested.
+ * @filter: (allow-none): Unused parameter.
+ * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
+ *
+ * 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;
+ DBusError d_error;
+
+ dbus_error_init (&d_error);
+
+ if (!listener)
+ {
+ return FALSE;
+ }
+ path = _atspi_device_listener_get_path (listener);
+
+ 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);
+ if (dbus_error_is_set (&d_error))
+ {
+ g_warning ("DeregisterDeviceEventListener failed: %s", d_error.message);
+ dbus_error_free (&d_error);
+ }
+
+ g_free (path);
+ return TRUE;
+}
+
+/**
+ * atspi_generate_keyboard_event:
+ * @keyval: a #gint indicating the keycode or keysym of the key event
+ * being synthesized.
+ * @keystring: (allow-none): an (optional) UTF-8 string which, if
+ * @synth_type is %ATSPI_KEY_STRING, indicates a 'composed'
+ * keyboard input string 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: an #AtspiKeySynthType flag indicating whether @keyval
+ * is to be interpreted as a keysym rather than a keycode
+ * (%ATSPI_KEY_SYM) or a string (%ATSPI_KEY_STRING), or
+ * whether to synthesize %ATSPI_KEY_PRESS,
+ * %ATSPI_KEY_RELEASE, or both (%ATSPI_KEY_PRESSRELEASE).
+ * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
+ *
+ * Synthesizes 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);
+ if (dbus_error_is_set (&d_error))
+ {
+ g_warning ("GenerateKeyboardEvent failed: %s", d_error.message);
+ dbus_error_free (&d_error);
+ }
+
+ return TRUE;
+}
+
+/**
+ * atspi_generate_mouse_event:
+ * @x: a #glong indicating the screen x coordinate of the mouse event.
+ * @y: a #glong 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").
+ * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
+ *
+ * Synthesizes 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 d_x = x, d_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",
+ d_x, d_y, name);
+ if (dbus_error_is_set (&d_error))
+ {
+ g_warning ("GenerateMouseEvent failed: %s", d_error.message);
+ dbus_error_free (&d_error);
+ }
+
+ return TRUE;
+}
+
+AtspiKeyDefinition *
+atspi_key_definition_copy (AtspiKeyDefinition *src)
+{
+ AtspiKeyDefinition *dst;
+
+ dst = g_new0 (AtspiKeyDefinition, 1);
+ dst->keycode = src->keycode;
+ dst->keysym = src->keysym;
+ if (src->keystring)
+ dst->keystring = g_strdup (src->keystring);
+ dst->unused = src->unused;
+ return dst;
+}
+
+void
+atspi_key_definition_free (AtspiKeyDefinition *kd)
+{
+ if (kd->keystring)
+ g_free (kd->keystring);
+ g_free (kd);
+}
+
+void
+_atspi_reregister_device_listeners ()
+{
+ GList *l;
+ DeviceListenerEntry *e;
+
+ for (l = device_listeners; l; l = l->next)
+ {
+ e = l->data;
+ notify_keystroke_listener (e);
+ }
+}
+G_DEFINE_BOXED_TYPE (AtspiKeyDefinition, atspi_key_definition, atspi_key_definition_copy, atspi_key_definition_free)
diff --git a/atspi/atspi-registry.h b/atspi/atspi-registry.h
new file mode 100644
index 0000000..18e32a6
--- /dev/null
+++ b/atspi/atspi-registry.h
@@ -0,0 +1,76 @@
+/*
+ * 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-types.h"
+#include "atspi-device-listener.h"
+
+G_BEGIN_DECLS
+
+GType atspi_key_definition_get_type ();
+
+gint atspi_get_desktop_count ();
+
+AtspiAccessible* atspi_get_desktop (gint i);
+
+GArray *atspi_get_desktop_list ();
+
+gboolean
+atspi_register_keystroke_listener (AtspiDeviceListener *listener,
+ GArray *key_set,
+ AtspiKeyMaskType modmask,
+ AtspiKeyEventMask event_types,
+ AtspiKeyListenerSyncType sync_type,
+ GError **error);
+
+gboolean
+atspi_deregister_keystroke_listener (AtspiDeviceListener *listener,
+ GArray *key_set,
+ AtspiKeyMaskType modmask,
+ AtspiKeyEventMask event_types,
+ GError **error);
+
+gboolean
+atspi_register_device_event_listener (AtspiDeviceListener *listener,
+ AtspiDeviceEventMask event_types,
+ 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);
+
+G_END_DECLS
+
+#endif /* _ATSPI_REGISTRY_H_ */
diff --git a/atspi/atspi-relation.c b/atspi/atspi-relation.c
new file mode 100644
index 0000000..82bb668
--- /dev/null
+++ b/atspi/atspi-relation.c
@@ -0,0 +1,135 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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"
+
+/**
+ * atspi_relation_get_relation_type:
+ * @obj: a pointer to the #AtspiRelation object to query.
+ *
+ * Gets the type of relationship represented by an #AtspiRelation.
+ *
+ * Returns: an #AtspiRelationType indicating the type of relation
+ * encapsulated in this #AtspiRelation object.
+ *
+ **/
+AtspiRelationType
+atspi_relation_get_relation_type (AtspiRelation *obj)
+{
+ return obj->relation_type;
+}
+
+/**
+ * atspi_relation_get_n_targets:
+ * @obj: a pointer to the #AtspiRelation object to query.
+ *
+ * Gets the number of objects which this relationship has as its
+ * target objects (the subject is the #AtspiAccessible from which this
+ * #AtspiRelation originated).
+ *
+ * Returns: a #gint indicating how many target objects which the
+ * originating #AtspiAccessible object has the #AtspiRelation
+ * relationship with.
+ **/
+gint
+atspi_relation_get_n_targets (AtspiRelation *obj)
+{
+ return obj->targets->len;
+}
+
+/**
+ * atspi_relation_get_target:
+ * @obj: a pointer to the #AtspiRelation object to query.
+ * @i: a (zero-index) #gint indicating which (of possibly several) target is requested.
+ *
+ * Gets the @i-th target of a specified #AtspiRelation relationship.
+ *
+ * Returns: (transfer full): an #AtspiAccessible which is the @i-th object
+ * with which the originating #AtspiAccessible has relationship
+ * specified in the #AtspiRelation object.
+ *
+ **/
+AtspiAccessible *
+atspi_relation_get_target (AtspiRelation *obj, gint i)
+{
+ g_return_val_if_fail (obj, NULL);
+
+ g_return_val_if_fail (i >= 0 && i < obj->targets->len, NULL);
+ return g_object_ref (g_array_index (obj->targets, AtspiAccessible *, i));
+}
+
+AtspiRelation *
+_atspi_relation_new_from_iter (DBusMessageIter *iter)
+{
+ DBusMessageIter iter_struct, iter_array;
+ dbus_uint32_t d_type;
+ AtspiRelation *relation = g_object_new (ATSPI_TYPE_RELATION, NULL);
+
+ if (!relation)
+ return NULL;
+
+ dbus_message_iter_recurse (iter, &iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &d_type);
+ relation->relation_type = d_type;
+ dbus_message_iter_next (&iter_struct);
+
+ relation->targets = g_array_new (TRUE, TRUE, sizeof (AtspiAccessible *));
+ dbus_message_iter_recurse (&iter_struct, &iter_array);
+ while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+ {
+ AtspiAccessible *accessible;
+ accessible = _atspi_dbus_return_accessible_from_iter (&iter_array);
+ relation->targets = g_array_append_val (relation->targets, accessible);
+ /* Iter was moved already, so no need to call dbus_message_iter_next */
+ }
+ return relation;
+}
+
+G_DEFINE_TYPE (AtspiRelation, atspi_relation, G_TYPE_OBJECT)
+
+static void
+atspi_relation_init (AtspiRelation *relation)
+{
+}
+
+static void
+atspi_relation_finalize (GObject *object)
+{
+ AtspiRelation *relation = ATSPI_RELATION (object);
+ gint i;
+
+ for (i = 0; i < relation->targets->len; i++)
+ g_object_unref (g_array_index (relation->targets, AtspiAccessible *, i));
+ g_array_free (relation->targets, TRUE);
+
+ G_OBJECT_CLASS (atspi_relation_parent_class)->finalize (object);
+}
+
+static void
+atspi_relation_class_init (AtspiRelationClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = atspi_relation_finalize;
+}
diff --git a/atspi/atspi-relation.h b/atspi/atspi-relation.h
new file mode 100644
index 0000000..4eecad3
--- /dev/null
+++ b/atspi/atspi-relation.h
@@ -0,0 +1,67 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_RELATION_H_
+#define _ATSPI_RELATION_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+
+G_BEGIN_DECLS
+
+#define ATSPI_TYPE_RELATION (atspi_relation_get_type ())
+#define ATSPI_IS_RELATION(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_RELATION)
+#define ATSPI_RELATION(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_RELATION, AtspiRelation)
+#define ATSPI_RELATION_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_RELATION, AtspiRelation))
+
+GType atspi_relation_get_type ();
+
+typedef struct _AtspiRelation AtspiRelation;
+struct _AtspiRelation
+{
+ GObject parent;
+ AtspiRelationType relation_type;
+ GArray *targets;
+};
+
+typedef struct _AtspiRelationClass AtspiRelationClass;
+struct _AtspiRelationClass
+{
+ GObjectClass parent_class;
+};
+
+AtspiRelationType atspi_relation_get_relation_type (AtspiRelation *obj);
+
+gint atspi_relation_get_n_targets (AtspiRelation *obj);
+
+AtspiAccessible * atspi_relation_get_target (AtspiRelation *obj, gint i);
+
+/* private */
+AtspiRelation * _atspi_relation_new_from_iter (DBusMessageIter *iter);
+
+G_END_DECLS
+
+#endif /* _ATSPI_RELATION_H_ */
diff --git a/atspi/atspi-selection.c b/atspi/atspi-selection.c
new file mode 100644
index 0000000..7318989
--- /dev/null
+++ b/atspi/atspi-selection.c
@@ -0,0 +1,264 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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"
+
+/**
+ * atspi_selection_get_n_selected_children:
+ * @obj: a pointer to the #AtspiSelection implementor on which to operate.
+ *
+ * Gets the number of children of an #AtspiSelection implementor which are
+ * currently selected.
+ *
+ * Returns: a #gint indicating the number of #Accessible children
+ * of the #AtspiSelection implementor which are currently selected.
+ *
+ **/
+gint
+atspi_selection_get_n_selected_children (AtspiSelection *obj, GError **error)
+{
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_get_property (obj, atspi_interface_selection, "NSelectedChildren", error, "i", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_selection_get_selected_child:
+ * @obj: a pointer to the #AtspiSelection on which to operate.
+ * @selected_child_index: a #gint indicating which of the selected
+ * children is specified.
+ *
+ * Gets the i-th selected #AtspiAccessible child of an #AtspiSelection.
+ * Note that @selected_child_index refers to the index in the list
+ * of 'selected'
+ * children and generally differs from that used in
+ * #atspi_accessible_get_child_at_index or returned by
+ * #atspi_accessible_get_index_in_parent.
+ * @selected_child_index must lie between 0
+ * and #atspi_selection_get_n_selected_children - 1, inclusive.
+ *
+ * Returns: (transfer full): a pointer to a selected #AtspiAccessible child
+ * object, specified by @selected_child_index.
+ *
+ **/
+AtspiAccessible *
+atspi_selection_get_selected_child (AtspiSelection *obj,
+ gint selected_child_index, GError **error)
+{
+ dbus_int32_t d_selected_child_index = selected_child_index;
+ DBusMessage *reply;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ reply = _atspi_dbus_call_partial (obj, atspi_interface_selection,
+ "GetSelectedChild", error, "i",
+ d_selected_child_index);
+
+ return _atspi_dbus_return_accessible_from_message (reply);
+}
+
+/**
+ * atspi_selection_select_child:
+ * @obj: a pointer to the #AtspiSelection on which to operate.
+ * @child_index: a #gint indicating which child of the #Accessible
+ * is to be selected.
+ *
+ * Adds a child to the selected children list of an #AtspiSelection.
+ * For #AtspiSelection implementors that only allow
+ * single selections, this may replace the (single) current
+ * selection.
+ *
+ * Returns: #TRUE if the child was successfully selected, #FALSE otherwise.
+ **/
+gboolean
+atspi_selection_select_child (AtspiSelection *obj,
+ gint child_index,
+ GError **error)
+{
+ dbus_int32_t d_child_index = child_index;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_selection, "SelectChild", error, "i=>b", d_child_index, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_selection_deselect_selected_child:
+ * @obj: a pointer to the #AtspiSelection on which to operate.
+ * @selected_child_index: a #gint indicating which of the selected children
+ * of the #Accessible is to be selected.
+ *
+ * Removes a child from the selected children list of an #AtspiSelection.
+ * Note that @child_index is the index in the selected-children list,
+ * not the index in the parent container. @selectedChildIndex in this
+ * method, and @child_index in #atspi_selection_select_child
+ * are asymmetric.
+ *
+ * Returns: #TRUE if the child was successfully deselected, #FALSE otherwise.
+ **/
+gboolean
+atspi_selection_deselect_selected_child (AtspiSelection *obj,
+ gint selected_child_index,
+ GError **error)
+{
+ dbus_int32_t d_selected_child_index = selected_child_index;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_selection, "DeselectSelectedChild", error, "i=>b", d_selected_child_index, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_selection_deselect_child:
+ * @obj: a pointer to the #AtspiSelection on which to operate.
+ * @child_index: a #gint indicating which of the children
+ * of the #AtspiAccessible is to be de-selected.
+ *
+ * Deselects a specific child of an #AtspiSelection.
+ * Note that @child_index is the index of the child
+ * in the parent container.
+ *
+ * See #atspi_selection_deselect_selected_child
+ *
+ * Returns: #TRUE if the child was successfully deselected, #FALSE otherwise.
+ **/
+gboolean
+atspi_selection_deselect_child (AtspiSelection *obj,
+ gint child_index,
+ GError **error)
+{
+ dbus_int32_t d_child_index = child_index;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_selection, "DeselectChild", error, "i=>b", d_child_index, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_selection_is_child_selected:
+ * @obj: a pointer to the #AtspiSelection implementor on which to operate.
+ * @child_index: an index into the #AtspiSelection's list of children.
+ *
+ * Determines whether a particular child of an #AtspiSelection implementor
+ * is currently selected. Note that @child_index is the index into the
+ * standard #AtspiAccessible container's list of children.
+ *
+ * Returns: #TRUE if the specified child is currently selected,
+ * #FALSE otherwise.
+ **/
+gboolean
+atspi_selection_is_child_selected (AtspiSelection *obj,
+ gint child_index,
+ GError **error)
+{
+ dbus_int32_t d_child_index = child_index;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_selection, "IsChildSelected", error, "i=>b", d_child_index, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_selection_select_all:
+ * @obj: a pointer to the #AtspiSelection implementor on which to operate.
+ *
+ * Attempts to select all of the children of an #AtspiSelection implementor.
+ * Not all #AtspiSelection implementors support this operation.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ *
+ **/
+gboolean
+atspi_selection_select_all (AtspiSelection *obj, GError **error)
+{
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_selection, "SelectAll", error, "=>b", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_selection_clear_selection:
+ * @obj: a pointer to the #AtspiSelection implementor on which to operate.
+ *
+ * Clears the current selection, removing all selected children from the
+ * specified #AtspiSelection implementor's selection list.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ *
+ **/
+gboolean
+atspi_selection_clear_selection (AtspiSelection *obj, GError **error)
+{
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_selection, "ClearSelection", error, "=>b", &retval);
+
+ return retval;
+}
+
+static void
+atspi_selection_base_init (AtspiSelection *klass)
+{
+}
+
+GType
+atspi_selection_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (AtspiSelection),
+ (GBaseInitFunc) atspi_selection_base_init,
+ (GBaseFinalizeFunc) NULL,
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE, "AtspiSelection", &tinfo, 0);
+
+ }
+ return type;
+}
diff --git a/atspi/atspi-selection.h b/atspi/atspi-selection.h
new file mode 100644
index 0000000..8ac7e44
--- /dev/null
+++ b/atspi/atspi-selection.h
@@ -0,0 +1,69 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_SELECTION_H_
+#define _ATSPI_SELECTION_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+#define ATSPI_TYPE_SELECTION (atspi_selection_get_type ())
+#define ATSPI_IS_SELECTION(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_SELECTION)
+#define ATSPI_SELECTION(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_SELECTION, AtspiSelection)
+#define ATSPI_SELECTION_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_SELECTION, AtspiSelection))
+
+GType atspi_selection_get_type ();
+
+struct _AtspiSelection
+{
+ GTypeInterface parent;
+};
+
+gint atspi_selection_get_n_selected_children (AtspiSelection *obj, GError **error);
+
+AtspiAccessible * atspi_selection_get_selected_child (AtspiSelection *obj, gint selected_child_index, GError **error);
+
+gboolean atspi_selection_select_child (AtspiSelection *obj, gint child_index, GError **error);
+
+gboolean atspi_selection_deselect_selected_child (AtspiSelection *obj, gint selected_child_index, GError **error);
+
+gboolean atspi_selection_deselect_child (AtspiSelection *obj, gint child_index, GError **error);
+
+gboolean
+atspi_selection_is_child_selected (AtspiSelection *obj,
+ gint child_index, GError **error);
+
+gboolean atspi_selection_select_all (AtspiSelection *obj, GError **error);
+
+gboolean atspi_selection_clear_selection (AtspiSelection *obj, GError **error);
+
+G_END_DECLS
+
+#endif /* _ATSPI_SELECTION_H_ */
diff --git a/atspi/atspi-stateset.c b/atspi/atspi-stateset.c
new file mode 100644
index 0000000..d6acc85
--- /dev/null
+++ b/atspi/atspi-stateset.c
@@ -0,0 +1,279 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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"
+
+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)
+{
+}
+
+/**
+ * atspi_state_set_new:
+ * @states: (element-type AtspiStateType): An array of states with which the
+ * method initializes the state set.
+ *
+ * Generates an #AtspiStateSet with the given @states.
+ *
+ * Returns: A new #AtspiStateSet with the given states.
+ **/
+AtspiStateSet *
+atspi_state_set_new (GArray *states)
+{
+ AtspiStateSet *set = g_object_new (ATSPI_TYPE_STATE_SET, NULL);
+ gint i;
+
+ if (!set || !states)
+ return set;
+
+ for (i = 0; i < states->len; i++)
+ atspi_state_set_add (set, g_array_index (states, AtspiStateType, i));
+ return set;
+}
+
+AtspiStateSet *
+_atspi_state_set_new_internal (AtspiAccessible *accessible, gint64 states)
+{
+ AtspiStateSet *set;
+
+ set = g_object_new (ATSPI_TYPE_STATE_SET, NULL);
+ g_return_val_if_fail (set != NULL, NULL);
+
+ set->accessible = accessible;
+ set->states = states;
+ return set;
+}
+
+/**
+ * atspi_state_set_set_by_name:
+ * @set: a pointer to the #AtspiStateSet object on which to operate.
+ * @name: a string corresponding to a state name.
+ * @enabled: if #TRUE, @name should be enabled in the @set in question;
+ * otherwise, it should be disabled.
+ *
+ * Enables/disables a state in an #AtspiStateSet according to its @name.
+ **/
+void
+atspi_state_set_set_by_name (AtspiStateSet *set, const gchar *name, gboolean enabled)
+{
+ GTypeClass *type_class;
+ GEnumValue *value;
+
+ if (set->accessible &&
+ !(set->accessible->cached_properties & ATSPI_CACHE_STATES))
+ return;
+
+ type_class = g_type_class_ref (ATSPI_TYPE_STATE_TYPE);
+
+ value = g_enum_get_value_by_nick (G_ENUM_CLASS (type_class), name);
+
+ if (!value)
+ {
+ g_warning ("AT-SPI: Attempt to set unknown state '%s'", name);
+ return;
+ }
+
+ if (enabled)
+ set->states |= ((gint64)1 << value->value);
+ else
+ set->states &= ~((gint64)1 << value->value);
+
+ g_type_class_unref (type_class);
+}
+
+static void
+refresh_states (AtspiStateSet *set)
+{
+ GArray *state_array;
+ dbus_uint32_t *states;
+
+ if (!set->accessible ||
+ (set->accessible->cached_properties & ATSPI_CACHE_STATES))
+ return;
+
+ if (!_atspi_dbus_call (set->accessible, atspi_interface_accessible, "GetState", NULL, "=>au", &state_array))
+ return;
+
+ states = (dbus_uint32_t *) state_array->data;
+
+ set->states = ((gint64)states [1]) << 32;
+ set->states |= (gint64) states [0];
+ g_array_free (state_array, TRUE);
+}
+
+/**
+ * atspi_state_set_add:
+ * @set: a pointer to the #AtspiStateSet object on which to operate.
+ * @state: an #AtspiStateType to be added to the specified #AtspiStateSet.
+ *
+ * Adds a particular #AtspiState to an #AtspiStateSet (i.e. sets the
+ * given state to #TRUE in the stateset).
+ *
+ **/
+void
+atspi_state_set_add (AtspiStateSet *set, AtspiStateType state)
+{
+ g_return_if_fail (set != NULL);
+ set->states |= (((gint64)1) << state);
+}
+
+/**
+ * atspi_state_set_compare:
+ * @set: a pointer to the first #AtspiStateSet object on which to operate.
+ * @set2: a pointer to the second #AtspiStateSet object on which to operate.
+ *
+ * Determines the differences between two instances of #AtspiStateSet.
+ *
+ * @see #atspi_state_set_equals.
+ *
+ * Returns: (transfer full): an #AtspiStateSet object containing all states
+ * contained on one of the two sets but not the other.
+ *
+ **/
+AtspiStateSet *
+atspi_state_set_compare (AtspiStateSet *set,
+ AtspiStateSet *set2)
+{
+ g_return_val_if_fail (set != NULL, NULL);
+ g_return_val_if_fail (set2 != NULL, NULL);
+
+ return _atspi_state_set_new_internal (NULL, set->states ^ set2->states);
+}
+
+/**
+ * atspi_state_set_contains:
+ * @set: a pointer to the #AtspiStateSet object on which to operate.
+ * @state: an #AtspiStateType for which the specified #AtspiStateSet
+ * will be queried.
+ *
+ * Determines whether a given #AtspiStateSet includes a given state; that is,
+ * whether @state is true for the @set in question.
+ *
+ * Returns: #TRUE if @state is true/included in the given #AtspiStateSet,
+ * otherwise #FALSE.
+ *
+ **/
+gboolean
+atspi_state_set_contains (AtspiStateSet *set,
+ AtspiStateType state)
+{
+ if (!set)
+ return FALSE;
+ refresh_states (set);
+ return (set->states & ((gint64)1 << state)) ? TRUE : FALSE;
+}
+
+/**
+ * atspi_state_set_equals:
+ * @set: a pointer to the first #AtspiStateSet object on which to operate.
+ * @set2: a pointer to the second #AtspiStateSet object on which to operate.
+ *
+ * Determines whether two instances of #AtspiStateSet are equivalent (i.e.
+ * consist of the same #AtspiStates). Useful for checking multiple
+ * state variables at once.
+ *
+ * @see #atspi_state_set_compare.
+ *
+ * Returns: #TRUE if the two #AtspiStateSets are equivalent,
+ * otherwise #FALSE.
+ *
+ **/
+gboolean
+atspi_state_set_equals (AtspiStateSet *set,
+ AtspiStateSet *set2)
+{
+ if (set == set2)
+ return TRUE;
+ if (set == NULL || set2 == NULL)
+ return FALSE;
+ return (set->states == set2->states);
+}
+
+/**
+ * atspi_state_set_get_states:
+ * @set: The #AtspiStateSet to be queried.
+ *
+ * Returns the states in an #AtspiStateSet as an array.
+ *
+ * Returns: (element-type AtspiStateType) (transfer full): A #GArray of state
+ * types representing the current state.
+ **/
+GArray *
+atspi_state_set_get_states (AtspiStateSet *set)
+{
+ gint i = 0;
+ guint64 val = 1;
+ GArray *ret;
+
+ g_return_val_if_fail (set != NULL, NULL);
+ refresh_states (set);
+ ret = g_array_new (TRUE, TRUE, sizeof (AtspiStateType));
+ if (!ret)
+ return NULL;
+ for (i = 0; i < 64; i++)
+ {
+ if (set->states & val)
+ ret = g_array_append_val (ret, i);
+ val <<= 1;
+ }
+ return ret;
+}
+
+/**
+ * atspi_state_set_is_empty:
+ * @set: The #AtspiStateSet to query.
+ *
+ * Returns: #TRUE if the state set contains no states; #FALSE otherwise.
+ **/
+gboolean
+atspi_state_set_is_empty (AtspiStateSet *set)
+{
+ return (set->states == 0);
+}
+
+/**
+ * atspi_state_set_remove:
+ * @set: a pointer to the #AtspiStateSet object on which to operate.
+ * @state: an #AtspiStateType to remove from the specified @set.
+ *
+ * Removes a particular #AtspiState to an #AtspiStateSet (i.e. sets the
+ * given state to #FALSE in the stateset.)
+ *
+ **/
+void
+atspi_state_set_remove (AtspiStateSet *set, AtspiStateType state)
+{
+ g_return_if_fail (set != NULL);
+ set->states &= ~((gint64)1 << state);
+}
diff --git a/atspi/atspi-stateset.h b/atspi/atspi-stateset.h
new file mode 100644
index 0000000..f6fd32f
--- /dev/null
+++ b/atspi/atspi-stateset.h
@@ -0,0 +1,75 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_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))
+
+G_BEGIN_DECLS
+
+typedef struct _AtspiStateSet AtspiStateSet;
+struct _AtspiStateSet
+{
+ GObject parent;
+ struct _AtspiAccessible *accessible;
+ gint64 states;
+};
+
+typedef struct _AtspiStateSetClass AtspiStateSetClass;
+struct _AtspiStateSetClass
+{
+ GObjectClass parent_class;
+};
+
+GType atspi_state_set_get_type (void);
+
+AtspiStateSet * atspi_state_set_new (GArray *states);
+
+void atspi_state_set_set_by_name (AtspiStateSet *set, const gchar *name, gboolean enabled);
+
+void atspi_state_set_add (AtspiStateSet *set, AtspiStateType state);
+
+AtspiStateSet * atspi_state_set_compare (AtspiStateSet *set, AtspiStateSet *set2);
+
+gboolean atspi_state_set_contains (AtspiStateSet *set, AtspiStateType state);
+
+gboolean atspi_state_set_equals (AtspiStateSet *set, AtspiStateSet *set2);
+
+GArray * atspi_state_set_get_states (AtspiStateSet *set);
+
+gboolean atspi_state_set_is_empty (AtspiStateSet *set);
+
+void atspi_state_set_remove (AtspiStateSet *set, AtspiStateType state);
+
+AtspiStateSet * _atspi_state_set_new_internal (struct _AtspiAccessible *accessible, gint64 states);
+
+G_END_DECLS
+
+#endif /* _ATSPI_STATE_SET_H_ */
diff --git a/atspi/atspi-table-cell.c b/atspi/atspi-table-cell.c
new file mode 100644
index 0000000..9e51031
--- /dev/null
+++ b/atspi/atspi-table-cell.c
@@ -0,0 +1,306 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2013 SUSE LLC.
+ *
+ * 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 <stdlib.h> /* for malloc */
+#include "atspi-private.h"
+
+static GPtrArray *
+get_object_array_and_unref (DBusMessage *reply)
+{
+ DBusMessageIter iter, iter_array;
+ GPtrArray *array;
+
+ if (!reply)
+ return NULL;
+
+ if (strcmp (dbus_message_get_signature (reply), "(so)") != 0)
+ {
+ dbus_message_unref (reply);
+ return NULL;
+ }
+
+ array = g_ptr_array_new ();
+
+ 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)
+ {
+ AtspiAccessible *accessible = _atspi_dbus_return_accessible_from_iter (&iter_array);
+ g_ptr_array_add (array, accessible);
+ }
+ dbus_message_unref (reply);
+ return array;
+}
+
+/**
+ * atspi_table_cell_get_column_span:
+ * @obj: a GObject instance that implements AtspiTableCellIface
+ *
+ * Returns the number of columns occupied by this cell accessible.
+ *
+ * Returns: a gint representing the number of columns occupied by this cell,
+ * or 0 if the cell does not implement this method.
+ */
+gint
+atspi_table_cell_get_column_span (AtspiTableCell *obj, GError **error)
+{
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_get_property (obj, atspi_interface_table_cell, "ColumnSpan",
+ error, "i", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_cell_get_column_header_cells:
+ * @obj: a GObject instance that implements AtspiTableCellIface
+ *
+ * Returns the column headers as an array of cell accessibles.
+ *
+ * Returns: (element-type AtspiAccessible) (transfer full): a GPtrArray of
+ * AtspiAccessibles representing the column header cells.
+ */
+GPtrArray *
+atspi_table_cell_get_column_header_cells (AtspiTableCell *obj, GError **error)
+{
+ DBusMessage *reply;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ reply = _atspi_dbus_call_partial (obj, atspi_interface_table_cell, "GetColumnHeaderCells", error, "");
+
+ return get_object_array_and_unref (reply);
+}
+
+/**
+ * atspi_table_cell_get_column_index:
+ * @obj: a GObject instance that implements AtspiTableCellIface
+ *
+ * Translates this cell accessible into the corresponding column index.
+ *
+ * Returns: the column index for this cell, or -1 if unimplemented.
+ */
+gint
+atspi_table_cell_get_column_index (AtspiTableCell *obj, GError **error)
+{
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_get_property (obj, atspi_interface_table_cell, "ColumnIndex",
+ error, "i", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_cell_get_row_span:
+ * @obj: a GObject instance that implements AtspiTableCellIface
+ *
+ * Returns the number of rows occupied by this cell accessible.
+ *
+ * Returns: a gint representing the number of rows occupied by this cell,
+ * or 0 if the cell does not implement this method.
+ */
+gint
+atspi_table_cell_get_row_span (AtspiTableCell *obj, GError **error)
+{
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_get_property (obj, atspi_interface_table_cell, "RowSpan",
+ error, "i", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_cell_get_row_header_cells:
+ * @obj: a GObject instance that implements AtspiTableCellIface
+ *
+ * Returns the row headers as an array of cell accessibles.
+ *
+ * Returns: (element-type AtspiAccessible) (transfer full): a GPtrArray of
+ * AtspiAccessibles representing the row header cells.
+ */
+GPtrArray *
+atspi_table_cell_get_row_header_cells (AtspiTableCell *obj, GError **error)
+{
+ DBusMessage *reply;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ reply = _atspi_dbus_call_partial (obj, atspi_interface_table_cell, "GetRowHeaderCells", error, "");
+
+ return get_object_array_and_unref (reply);
+}
+
+/**
+ * atspi_table_cell_get_position:
+ * @obj: a GObject instance that implements AtspiTableCellIface
+ * @row: (out): the row of the given cell.
+ * @column: (out): the column of the given cell.
+ *
+ * Retrieves the tabular position of this cell.
+ *
+ * Returns: TRUE if successful, FALSE otherwise.
+ */
+gint
+atspi_table_cell_get_position (AtspiTableCell *obj,
+ gint *row,
+ gint *column,
+ GError *error)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter, iter_struct, iter_variant;
+ dbus_int32_t d_row = -1, d_column = -1;
+ char *iter_sig;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ reply = _atspi_dbus_call_partial (obj, "org.freedesktop.DBuss.Properties",
+ "Get", atspi_interface_table_cell,
+ "Position");
+
+ dbus_message_iter_init (reply, &iter);
+
+ /* TODO: Return error here */
+ if (dbus_message_iter_get_arg_type (&iter) != 'v')
+ return FALSE;
+
+ dbus_message_iter_recurse (&iter, &iter_variant);
+ iter_sig = dbus_message_iter_get_signature (&iter_variant);
+ /* TODO: Also report error here */
+ if (strcmp (iter_sig, "(ii)") != 0)
+ {
+ dbus_free (iter_sig);
+ return FALSE;
+ }
+ dbus_free (iter_sig);
+
+ dbus_message_iter_recurse (&iter_variant, &iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &d_row);
+ if (row)
+ *row = d_row;
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &d_column);
+ if (column)
+ *column = d_column;
+ dbus_message_unref (reply);
+ return TRUE;
+}
+
+/**
+ * atspi_table_cell_get_row_column_span:
+ * @obj: a GObject instance that implements AtspiTableCellIface
+ * @row: (out): the row index of the given cell.
+ * @column: (out): the column index of the given cell.
+ * @row_span: (out): the number of rows occupied by this cell.
+ * @column_span: (out): the number of columns occupied by this cell.
+ *
+ * Gets the row and column indexes and extents of this cell accessible.
+ */
+void
+atspi_table_cell_get_row_column_span (AtspiTableCell *obj,
+ gint *row,
+ gint *column,
+ gint *row_span,
+ gint *column_span,
+ GError **error)
+{
+ dbus_int32_t d_row = 0, d_column = 0, d_row_span = 0, d_column_span = 0;
+
+ if (row)
+ *row = -1;
+ if (column)
+ *column = -1;
+ if (row_span)
+ *row_span = -1;
+ if (column_span)
+ *column_span = -1;
+
+ g_return_if_fail (obj != NULL);
+
+ _atspi_dbus_call (obj, atspi_interface_table_cell, "GetRowColumnSpan",
+ error, "=>iiii", &d_row, &d_column,
+ &d_row_span, &d_column_span);
+
+ if (row)
+ *row = d_row;
+ if (column)
+ *column = d_column;
+ if (row_span)
+ *row_span = d_row_span;
+ if (column_span)
+ *column_span = d_column_span;
+}
+
+/**
+ * atspi_table_cell_get_table:
+ * @obj: a GObject instance that implements AtspiTableCellIface
+ *
+ * Returns a reference to the accessible of the containing table.
+ *
+ * Returns: (transfer full): the AtspiAccessible for the containing table.
+ */
+AtspiAccessible *
+atspi_table_cell_get_table (AtspiTableCell *obj, GError **error)
+{
+ AtspiAccessible *retval = NULL;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ _atspi_dbus_get_property (obj, atspi_interface_table_cell, "Table",
+ error, "(so)", &retval);
+
+ return retval;
+}
+
+static void
+atspi_table_cell_base_init (AtspiTableCell *klass)
+{
+}
+
+GType
+atspi_table_cell_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (AtspiTableCell),
+ (GBaseInitFunc) atspi_table_cell_base_init,
+ (GBaseFinalizeFunc) NULL,
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE, "AtspiTableCell", &tinfo, 0);
+
+ }
+ return type;
+}
diff --git a/atspi/atspi-table-cell.h b/atspi/atspi-table-cell.h
new file mode 100644
index 0000000..8174db8
--- /dev/null
+++ b/atspi/atspi-table-cell.h
@@ -0,0 +1,74 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_TABLE_CELL_H_
+#define _ATSPI_TABLE_CELL_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+#define ATSPI_TYPE_TABLE_CELL (atspi_table_cell_get_type ())
+#define ATSPI_IS_TABLE_CELL(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_TABLE_CELL)
+#define ATSPI_TABLE_CELL(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_TABLE_CELL, AtspiTableCell)
+#define ATSPI_TABLE_CELL_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_TABLE_CELL, AtspiTableCell))
+
+GType atspi_table_cell_get_type ();
+
+struct _AtspiTableCell
+{
+ GTypeInterface parent;
+};
+
+gint atspi_table_cell_get_column_span (AtspiTableCell *obj, GError **error);
+
+GPtrArray *atspi_table_cell_get_column_header_cells (AtspiTableCell *obj,
+ GError **error);
+
+gint atspi_table_cell_get_column_index (AtspiTableCell *obj, GError **error);
+
+gint atspi_table_cell_get_row_span (AtspiTableCell *obj, GError **error);
+
+GPtrArray *atspi_table_cell_get_row_header_cells (AtspiTableCell *obj,
+ GError **error);
+
+gint atspi_table_cell_get_row_index (AtspiTableCell *obj, GError **error);
+
+void atspi_table_cell_get_row_column_span (AtspiTableCell *obj,
+ gint *row,
+ gint *column,
+ gint *row_span,
+ gint *column_span,
+ GError **error);
+
+AtspiAccessible *atspi_table_cell_get_table (AtspiTableCell *obj,
+ GError **error);
+G_END_DECLS
+
+#endif /* _ATSPI_TABLE_CELL_H_ */
diff --git a/atspi/atspi-table.c b/atspi/atspi-table.c
new file mode 100644
index 0000000..b17e2f1
--- /dev/null
+++ b/atspi/atspi-table.c
@@ -0,0 +1,745 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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 <stdlib.h> /* for malloc */
+#include "atspi-private.h"
+
+/**
+ * atspi_table_get_caption:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ *
+ * Gets an accessible representation of the caption for an #AtspiTable.
+ *
+ * Returns: (transfer full): an #AtspiAccessible object that serves as
+ * the table's caption.
+ *
+ **/
+AtspiAccessible *
+atspi_table_get_caption (AtspiTable *obj, GError **error)
+{
+ AtspiAccessible *retval = NULL;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ _atspi_dbus_get_property (obj, atspi_interface_table, "Caption", error, "(so)", &retval);
+ return retval;
+}
+
+/**
+ * atspi_table_get_summary:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ *
+ * Gets an accessible object which summarizes the contents of an #AtspiTable.
+ *
+ * Returns: (transfer full): an #AtspiAccessible object that serves as the
+ * table's summary (often a reduced #AtspiTable).
+ **/
+AtspiAccessible *
+atspi_table_get_summary (AtspiTable *obj, GError **error)
+{
+ AtspiAccessible *retval;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ _atspi_dbus_get_property (obj, atspi_interface_table, "Summary", error, "(so)", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_get_n_rows:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ *
+ * Gets the number of rows in an #AtspiTable,
+ * exclusive of any rows that are programmatically hidden, but inclusive
+ * of rows that may be outside of the current scrolling window or viewport.
+ *
+ * Returns: a #gint indicating the number of rows in the table.
+ **/
+gint
+atspi_table_get_n_rows (AtspiTable *obj, GError **error)
+{
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_get_property (obj, atspi_interface_table, "NRows", error, "i", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_get_n_columns:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ *
+ * Gets the number of columns in an #AtspiTable,
+ * exclusive of any columns that are programmatically hidden, but inclusive
+ * of columns that may be outside of the current scrolling window or viewport.
+ *
+ * Returns: a #gint indicating the number of columns in the table.
+ **/
+gint
+atspi_table_get_n_columns (AtspiTable *obj, GError **error)
+{
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_get_property (obj, atspi_interface_table, "NColumns", error, "i", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_get_accessible_at:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @row: the specified table row, zero-indexed.
+ * @column: the specified table column, zero-indexed.
+ *
+ * Gets the table cell at the specified row and column indices.
+ * To get the accessible object at a particular (x, y) screen
+ * coordinate, use #atspi_component_get_accessible_at_point.
+ *
+ * Returns: (transfer full): an #AtspiAccessible object representing the
+ * specified table cell.
+ **/
+AtspiAccessible *
+atspi_table_get_accessible_at (AtspiTable *obj,
+ gint row,
+ gint column,
+ GError **error)
+{
+ dbus_int32_t d_row = row, d_column = column;
+ DBusMessage *reply;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ reply = _atspi_dbus_call_partial (obj, atspi_interface_table, "GetAccessibleAt", error, "ii", d_row, d_column);
+
+ return _atspi_dbus_return_accessible_from_message (reply);
+}
+
+/**
+ * atspi_table_get_index_at:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @row: the specified table row, zero-indexed.
+ * @column: the specified table column, zero-indexed.
+ *
+ * Gets the 1-D child index corresponding to the specified 2-D row and
+ * column indices. To get the accessible object at a particular (x, y) screen
+ * coordinate, use #atspi_component_get_accessible_at_point.
+ *
+ * @see #atspi_table_get_row_at_index, #atspi_table_get_column_at_index
+ *
+ * Returns: a #gint which serves as the index of a specified cell in the
+ * table, in a form usable by #atspi_get_child_at_index.
+ **/
+gint
+atspi_table_get_index_at (AtspiTable *obj,
+ gint row,
+ gint column,
+ GError **error)
+{
+ dbus_int32_t d_row = row, d_column = column;
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "GetIndexAt", error, "ii=>i", d_row, d_column, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_get_row_at_index:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @index: the specified child index, zero-indexed.
+ *
+ * Gets the table row index occupied by the child at a particular 1-D
+ * child index.
+ *
+ * @see #atspi_table_get_index_at, #atspi_table_get_column_at_index
+ *
+ * Returns: a #gint indicating the first row spanned by the child of a
+ * table, at the specified 1-D (zero-offset) @index.
+ **/
+gint
+atspi_table_get_row_at_index (AtspiTable *obj,
+ gint index,
+ GError **error)
+{
+ dbus_int32_t d_index = index;
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "GetRowAtIndex", error, "i=>i", d_index, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_get_column_at_index:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @index: the specified child index, zero-indexed.
+ *
+ * Gets the table column index occupied by the child at a particular 1-D
+ * child index.
+ *
+ * @see #atspi_table_get_index_at, #atspi_table_get_row_at_index
+ *
+ * Returns: a #gint indicating the first column spanned by the child of a
+ * table, at the specified 1-D (zero-offset) @index.
+ **/
+gint
+atspi_table_get_column_at_index (AtspiTable *obj,
+ gint index,
+ GError **error)
+{
+ dbus_int32_t d_index = index;
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "GetColumnAtIndex", error, "i=>i", d_index, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_get_row_description:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @row: the specified table row, zero-indexed.
+ *
+ * Gets a text description of a particular table row. This differs from
+ * #atspi_table_get_row_header, which returns an #AtspiAccessible.
+ *
+ * Returns: a UTF-8 string describing the specified table row, if available.
+ **/
+gchar *
+atspi_table_get_row_description (AtspiTable *obj,
+ gint row,
+ GError **error)
+{
+ dbus_int32_t d_row = row;
+ char *retval = NULL;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "GetRowDescription", error, "i=>s", d_row, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_get_column_description:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @column: the specified table column, zero-indexed.
+ *
+ * Gets a text description of a particular table column. This differs from
+ * #atspi_table_get_column_header, which returns an #Accessible.
+ *
+ * Returns: a UTF-8 string describing the specified table column, if available.
+ **/
+gchar *
+atspi_table_get_column_description (AtspiTable *obj,
+ gint column, GError **error)
+{
+ dbus_int32_t d_column = column;
+ char *retval = NULL;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "GetColumnDescription", error, "i=>s", d_column, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_get_row_extent_at:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @row: the specified table row, zero-indexed.
+ * @column: the specified table column, zero-indexed.
+ *
+ * Gets the number of rows spanned by the table cell at the specific row
+ * and column. (some tables can have cells which span multiple rows
+ * and/or columns).
+ *
+ * Returns: a #gint indicating the number of rows spanned by the specified cell.
+ **/
+gint
+atspi_table_get_row_extent_at (AtspiTable *obj,
+ gint row,
+ gint column,
+ GError **error)
+{
+ dbus_int32_t d_row = row, d_column = column;
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "GetRowExtentAt", error, "ii=>i", d_row, d_column, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_get_column_extent_at:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @row: the specified table row, zero-indexed.
+ * @column: the specified table column, zero-indexed.
+ *
+ * Gets the number of columns spanned by the table cell at the specific
+ * row and column (some tables can have cells which span multiple
+ * rows and/or columns).
+ *
+ * Returns: a #gint indicating the number of columns spanned by the specified cell.
+ **/
+gint
+atspi_table_get_column_extent_at (AtspiTable *obj,
+ gint row,
+ gint column,
+ GError **error)
+{
+ dbus_int32_t d_row = row, d_column = column;
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "GetColumnExtentAt", error, "ii=>i", d_row, d_column, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_get_row_header:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @row: the specified table row, zero-indexed.
+ *
+ * Gets the header associated with a table row, if available. This differs from
+ * #atspi_table_get_row_description, which returns a string.
+ *
+ * Returns: (transfer full): an #AtspiAccessible representation of the specified
+ * table row, if available.
+ **/
+AtspiAccessible *
+atspi_table_get_row_header (AtspiTable *obj,
+ gint row,
+ GError **error)
+{
+ dbus_int32_t d_row = row;
+ DBusMessage *reply;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ reply = _atspi_dbus_call_partial (obj, atspi_interface_table, "GetRowHeader", error, "i", d_row);
+
+ return _atspi_dbus_return_accessible_from_message (reply);
+}
+
+/**
+ * atspi_table_get_column_header:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @column: the specified table column, zero-indexed.
+ *
+ * Gets the header associated with a table column, if available.
+ * This differs from #atspi_table_get_column_description, which
+ * returns a string.
+ *
+ * Returns: (transfer full): an #AtspiAccessible representation of the
+ * specified table column, if available.
+ **/
+AtspiAccessible *
+atspi_table_get_column_header (AtspiTable *obj,
+ gint column,
+ GError **error)
+{
+ dbus_int32_t d_column = column;
+ DBusMessage *reply;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ reply = _atspi_dbus_call_partial (obj, atspi_interface_table, "GetColumnHeader", error, "i", d_column);
+
+ return _atspi_dbus_return_accessible_from_message (reply);
+}
+
+/**
+ * atspi_table_get_n_selected_rows:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ *
+ * Query a table to find out how many rows are currently selected.
+ * Not all tables support row selection.
+ *
+ * Returns: a #gint indicating the number of rows currently selected.
+ **/
+gint
+atspi_table_get_n_selected_rows (AtspiTable *obj, GError **error)
+{
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_get_property (obj, atspi_interface_table, "NSelectedRows", error, "i", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_get_selected_rows:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ *
+ * Queries a table for a list of indices of rows which are currently selected.
+ *
+ * Returns: (element-type gint) (transfer full): an array of #gint values,
+ * specifying which rows are currently selected.
+ **/
+GArray *
+atspi_table_get_selected_rows (AtspiTable *obj,
+ GError **error)
+{
+ GArray *rows = NULL;
+
+ g_return_val_if_fail (obj != NULL, 0);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "GetSelectedRows", error, "=>ai", &rows);
+
+ return rows;
+}
+
+/**
+ * atspi_table_get_selected_columns:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ *
+ * Queries a table for a list of indices of columns which are currently
+ * selected.
+ *
+ * Returns: (element-type gint) (transfer full): an array of #gint values,
+ * specifying which columns are currently selected.
+ **/
+GArray *
+atspi_table_get_selected_columns (AtspiTable *obj,
+ GError **error)
+{
+ GArray *columns = NULL;
+
+ g_return_val_if_fail (obj != NULL, 0);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "GetSelectedColumns", error, "=>ai", &columns);
+
+ return columns;
+}
+
+/**
+ * atspi_table_get_n_selected_columns:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ *
+ * Queries a table to find out how many columns are currently selected.
+ * Not all tables support column selection.
+ *
+ * Returns: a #gint indicating the number of columns currently selected.
+ **/
+gint
+atspi_table_get_n_selected_columns (AtspiTable *obj, GError **error)
+{
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_get_property (obj, atspi_interface_table, "NSelectedColumns", error, "i", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_is_row_selected:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @row: the zero-indexed row number of the row being queried.
+ *
+ * Determines whether a table row is selected. Not all tables support
+ * row selection.
+ *
+ * Returns: #TRUE if the specified row is currently selected, #FALSE if not.
+ **/
+gboolean
+atspi_table_is_row_selected (AtspiTable *obj,
+ gint row,
+ GError **error)
+{
+ dbus_int32_t d_row = row;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "IsRowSelected", error, "i=>b", d_row, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_is_column_selected:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @column: the zero-indexed column number of the column being queried.
+ *
+ * Determines whether specified table column is selected.
+ * Not all tables support column selection.
+ *
+ * Returns: #TRUE if the specified column is currently selected, #FALSE if not.
+ **/
+gboolean
+atspi_table_is_column_selected (AtspiTable *obj,
+ gint column,
+ GError **error)
+{
+ dbus_int32_t d_column = column;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "IsColumnSelected", error, "i=>b", d_column, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_add_row_selection:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @row: the zero-indexed row number of the row being selected.
+ *
+ * Selects the specified row, adding it to the current row selection.
+ * Not all tables support row selection.
+ *
+ * Returns: #TRUE if the specified row was successfully selected, #FALSE if not.
+ **/
+gboolean
+atspi_table_add_row_selection (AtspiTable *obj,
+ gint row,
+ GError **error)
+{
+ dbus_int32_t d_row = row;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "AddRowSelection", error, "i=>b", d_row, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_add_column_selection:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @column: the zero-indexed column number of the column being selected.
+ *
+ * Selects the specified column, adding it to the current column selection.
+ * Not all tables support column selection.
+ *
+ * Returns: #TRUE if the specified column was successfully selected, #FALSE if not.
+ **/
+gboolean
+atspi_table_add_column_selection (AtspiTable *obj,
+ gint column,
+ GError **error)
+{
+ dbus_int32_t d_column = column;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "AddColumnSelection", error, "i=>b", d_column, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_remove_row_selection:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @row: the zero-indexed number of the row being de-selected.
+ *
+ * De-selects the specified row, removing it from the current row selection.
+ * Not all tables support row selection.
+ *
+ * Returns: #TRUE if the specified row was successfully de-selected,
+ * #FALSE if not.
+ **/
+gboolean
+atspi_table_remove_row_selection (AtspiTable *obj,
+ gint row,
+ GError **error)
+{
+ dbus_int32_t d_row = row;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "RemoveRowSelection", error, "i=>b", d_row, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_remove_column_selection:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @column: the zero-indexed column number of the column being de-selected.
+ *
+ * De-selects the specified column, removing it from the current column
+ * selection.
+ * Not all tables support column selection.
+ *
+ * Returns: #TRUE if the specified column was successfully de-selected,
+ * #FALSE if not.
+ **/
+gboolean
+atspi_table_remove_column_selection (AtspiTable *obj,
+ gint column,
+ GError **error)
+{
+ dbus_int32_t d_column = column;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "RemoveColumnSelection", error, "i=>b", d_column, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_table_get_row_column_extents_at_index:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @index: the index of the #AtspiTable child whose row/column
+ * extents are requested.
+ * @row: (out): back-filled with the first table row associated with
+ * the cell with child index.
+ * @col: (out): back-filled with the first table column associated
+ * with the cell with child index.
+ * @row_extents: (out): back-filled with the number of table rows
+ * across which child i extends.
+ * @col_extents: (out): back-filled with the number of table columns
+ * across which child i extends.
+ * @is_selected: (out): a boolean which is back-filled with #TRUE
+ * if the child at index i corresponds to a selected table cell,
+ * #FALSE otherwise.
+ *
+ * Given a child index, determines the row and column indices and
+ * extents, and whether the cell is currently selected. If
+ * the child at index is not a cell (for instance, if it is
+ * a summary, caption, etc.), #FALSE is returned.
+ *
+ * Example:
+ * If the #AtspiTable child at index '6' extends across columns 5 and 6 of
+ * row 2 of an #AtspiTable instance, and is currently selected, then
+ *
+ * retval = atspi_table_get_row_column_extents_at_index (table, 6,
+ * row, col,
+ * row_extents,
+ * col_extents,
+ * is_selected);
+ *
+ * will return #TRUE, and after the call
+ * row, col, row_extents, col_extents,
+ * and is_selected will contain 2, 5, 1, 2, and
+ * #TRUE, respectively.
+ *
+ * Returns: #TRUE if the index is associated with a valid table
+ * cell, #FALSE if the index does not correspond to a cell. If
+ * #FALSE is returned, the values of the out parameters are
+ * undefined.
+ **/
+gboolean
+atspi_table_get_row_column_extents_at_index (AtspiTable *obj,
+ gint index, gint *row, gint *col,
+ gint *row_extents, gint *col_extents,
+ gboolean *is_selected, GError **error)
+{
+ dbus_int32_t d_index = index;
+ dbus_bool_t retval = FALSE;
+ dbus_int32_t d_row = 0, d_col = 0, d_row_extents = 0, d_col_extents = 0;
+ dbus_bool_t d_is_selected = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "GetRowColumnExtentsAtIndex",
+ error, "i=>biiiib", d_index, &retval, &d_row, &d_col,
+ &d_row_extents, &d_col_extents, &d_is_selected);
+
+ *row = d_row;
+ *col = d_col;
+ *row_extents = d_row_extents;;
+ *col_extents = d_col_extents;
+ *is_selected = d_is_selected;;
+
+ return retval;
+}
+
+
+/**
+ * atspi_table_is_selected:
+ * @obj: a pointer to the #AtspiTable implementor on which to operate.
+ * @row: the zero-indexed row of the cell being queried.
+ * @column: the zero-indexed column of the cell being queried.
+ *
+ * Determines whether the cell at a specific row and column is selected.
+ *
+ * Returns: #TRUE if the specified cell is currently selected, #FALSE if not.
+ **/
+gboolean
+atspi_table_is_selected (AtspiTable *obj,
+ gint row,
+ gint column,
+ GError **error)
+{
+ dbus_int32_t d_row = row, d_column = column;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_table, "IsSelected", error, "ii=>b", d_row, d_column, &retval);
+
+ return retval;
+}
+
+static void
+atspi_table_base_init (AtspiTable *klass)
+{
+}
+
+GType
+atspi_table_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (AtspiTable),
+ (GBaseInitFunc) atspi_table_base_init,
+ (GBaseFinalizeFunc) NULL,
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE, "AtspiTable", &tinfo, 0);
+
+ }
+ return type;
+}
diff --git a/atspi/atspi-table.h b/atspi/atspi-table.h
new file mode 100644
index 0000000..1295df1
--- /dev/null
+++ b/atspi/atspi-table.h
@@ -0,0 +1,105 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_TABLE_H_
+#define _ATSPI_TABLE_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+#define ATSPI_TYPE_TABLE (atspi_table_get_type ())
+#define ATSPI_IS_TABLE(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_TABLE)
+#define ATSPI_TABLE(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_TABLE, AtspiTable)
+#define ATSPI_TABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_TABLE, AtspiTable))
+
+GType atspi_table_get_type ();
+
+struct _AtspiTable
+{
+ GTypeInterface parent;
+};
+
+AtspiAccessible * atspi_table_get_caption (AtspiTable *obj, GError **error);
+
+AtspiAccessible * atspi_table_get_summary (AtspiTable *obj, GError **error);
+
+gint atspi_table_get_n_rows (AtspiTable *obj, GError **error);
+
+gint atspi_table_get_n_columns (AtspiTable *obj, GError **error);
+
+AtspiAccessible * atspi_table_get_accessible_at (AtspiTable *obj, gint row, gint column, GError **error);
+
+gint atspi_table_get_index_at (AtspiTable *obj, gint row, gint column, GError **error);
+
+gint atspi_table_get_row_at_index (AtspiTable *obj, gint index, GError **error);
+
+gint atspi_table_get_column_at_index (AtspiTable *obj, gint index, GError **error);
+
+gchar * atspi_table_get_row_description (AtspiTable *obj, gint row, GError **error);
+
+gchar * atspi_table_get_column_description (AtspiTable *obj, gint column, GError **error);
+
+gint
+atspi_table_get_row_extent_at (AtspiTable *obj, gint row, gint column, GError **error);
+
+gint
+atspi_table_get_column_extent_at (AtspiTable *obj, gint row, gint column, GError **error);
+
+AtspiAccessible * atspi_table_get_row_header (AtspiTable *obj, gint row, GError **error);
+
+AtspiAccessible * atspi_table_get_column_header (AtspiTable *obj, gint column, GError **error);
+
+gint atspi_table_get_n_selected_rows (AtspiTable *obj, GError **error);
+
+GArray *atspi_table_get_selected_rows (AtspiTable *obj, GError **error);
+
+GArray * atspi_table_get_selected_columns (AtspiTable *obj, GError **error);
+
+gint atspi_table_get_n_selected_columns (AtspiTable *obj, GError **error);
+
+gboolean atspi_table_is_row_selected (AtspiTable *obj, gint row, GError **error);
+
+gboolean atspi_table_is_column_selected (AtspiTable *obj, gint column, GError **error);
+
+gboolean atspi_table_add_row_selection (AtspiTable *obj, gint row, GError **error);
+
+gboolean atspi_table_add_column_selection (AtspiTable *obj, gint column, GError **error);
+
+gboolean atspi_table_remove_row_selection (AtspiTable *obj, gint row, GError **error);
+
+gboolean atspi_table_remove_column_selection (AtspiTable *obj, gint column, GError **error);
+
+gboolean atspi_table_get_row_column_extents_at_index (AtspiTable *obj, gint index, gint *row, gint *col, gint *row_extents, gint *col_extents, gboolean *is_selected, GError **error);
+
+gboolean atspi_table_is_selected (AtspiTable *obj, gint row, gint column, GError **error);
+
+G_END_DECLS
+
+#endif /* _ATSPI_TABLE_H_ */
diff --git a/atspi/atspi-text.c b/atspi/atspi-text.c
new file mode 100644
index 0000000..6639fd4
--- /dev/null
+++ b/atspi/atspi-text.c
@@ -0,0 +1,913 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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"
+/**
+ * atspi_range_copy:
+ * @src: a pointer to the source #AtspiRange object that will be copied.
+ *
+ * Gets a copy of an #AtspiRange object.
+ *
+ * Returns: the #AtspiRange copy of an #AtspiRange object.
+ **/
+AtspiRange *
+atspi_range_copy (AtspiRange *src)
+{
+ AtspiRange *dst = g_new (AtspiRange, 1);
+
+ dst->start_offset = src->start_offset;
+ dst->end_offset = src->end_offset;
+ return dst;
+}
+
+G_DEFINE_BOXED_TYPE (AtspiRange, atspi_range, atspi_range_copy, g_free)
+
+static AtspiTextRange *
+atspi_text_range_copy (AtspiTextRange *src)
+{
+ AtspiTextRange *dst = g_new (AtspiTextRange, 1);
+
+ dst->content = g_strdup (src->content);
+ dst->start_offset = src->start_offset;
+ dst->end_offset = src->end_offset;
+ return dst;
+}
+
+static void
+atspi_text_range_free (AtspiTextRange *range)
+{
+ g_free (range->content);
+ g_free (range);
+}
+
+G_DEFINE_BOXED_TYPE (AtspiTextRange, atspi_text_range, atspi_text_range_copy,
+ atspi_text_range_free)
+
+/**
+ * atspi_text_get_character_count:
+ * @obj: a pointer to the #AtspiText object to query.
+ *
+ * Gets the character count of an #AccessibleText object.
+ *
+ * Returns: a #gint indicating the total number of
+ * characters in the #AccessibleText object.
+ **/
+gint
+atspi_text_get_character_count (AtspiText *obj, GError **error)
+{
+ dbus_int32_t retval = 0;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_get_property (obj, atspi_interface_text, "CharacterCount", error, "i", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_text_get_text:
+ * @obj: a pointer to the #AtspiText object to query.
+ * @start_offset: a #gint indicating the start of the desired text range.
+ * @end_offset: a #gint indicating the first character past the desired range.
+ *
+ * Gets a range of text from an #AtspiText object. The number of bytes
+ * in the returned string may exceed either end_offset or start_offset, since
+ * UTF-8 is a variable-width encoding.
+ *
+ * Returns: a text string containing characters from @start_offset
+ * to @end_offset-1, inclusive, encoded as UTF-8.
+ **/
+gchar *
+atspi_text_get_text (AtspiText *obj,
+ gint start_offset,
+ gint end_offset,
+ GError **error)
+{
+ gchar *retval = NULL;
+ dbus_int32_t d_start_offset = start_offset, d_end_offset = end_offset;
+
+ g_return_val_if_fail (obj != NULL, g_strdup (""));
+
+ _atspi_dbus_call (obj, atspi_interface_text, "GetText", error, "ii=>s", d_start_offset, d_end_offset, &retval);
+
+ if (!retval)
+ retval = g_strdup ("");
+
+ return retval;
+}
+
+/**
+ * atspi_text_get_caret_offset:
+ * @obj: a pointer to the #AtspiText object to query.
+ *
+ * Gets the current offset of the text caret in an #AtspiText object.
+ *
+ * Returns: a #gint indicating the current position of the text caret.
+ **/
+gint
+atspi_text_get_caret_offset (AtspiText *obj, GError **error)
+{
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_get_property (obj, atspi_interface_text, "CaretOffset", error, "i", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_text_get_attributes: (rename-to atspi_text_get_text_attributes)
+ * @obj: a pointer to the #AtspiText object to query.
+ * @offset: a #gint indicating the offset from which the attribute
+ * search is based.
+ * @start_offset: (out): a #gint pointer indicating the start of the desired text
+ * range.
+ * @end_offset: (out): a #gint pointer indicating the first character past the desired
+ * range.
+ *
+ * Gets the attributes applied to a range of text from an #AtspiText
+ * object. The text attributes correspond to CSS attributes
+ * where possible.
+ * <em>DEPRECATED</em>
+ *
+ * Returns: (element-type gchar* gchar*) (transfer full): a #GHashTable
+ * describing the attributes at the given character offset.
+ *
+ * Deprecated: 2.10: Use atspi_text_get_text_attributes instead.
+ **/
+GHashTable *
+atspi_text_get_attributes (AtspiText *obj,
+ gint offset,
+ gint *start_offset,
+ gint *end_offset,
+ GError **error)
+{
+ return atspi_text_get_text_attributes (obj, offset, start_offset, end_offset, error);
+}
+
+/**
+ * atspi_text_get_text_attributes:
+ * @obj: a pointer to the #AtspiText object to query.
+ * @offset: a #gint indicating the offset from which the attribute
+ * search is based.
+ * @start_offset: (out): a #gint pointer indicating the start of the desired text
+ * range.
+ * @end_offset: (out): a #gint pointer indicating the first character past the desired
+ * range.
+ *
+ * Gets the attributes applied to a range of text from an #AtspiText
+ * object. The text attributes correspond to CSS attributes
+ * where possible.
+ * <em>DEPRECATED</em>
+ *
+ * Returns: (element-type gchar* gchar*) (transfer full): a #GHashTable
+ * describing the attributes at the given character offset.
+ **/
+GHashTable *
+atspi_text_get_text_attributes (AtspiText *obj,
+ gint offset,
+ gint *start_offset,
+ gint *end_offset,
+ GError **error)
+{
+ dbus_int32_t d_offset = offset;
+ dbus_int32_t d_start_offset, d_end_offset;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ GHashTable *ret = NULL;
+
+ if (obj == NULL)
+ return NULL;
+
+ reply = _atspi_dbus_call_partial (obj, atspi_interface_text, "GetAttributes", error, "i", d_offset);
+ _ATSPI_DBUS_CHECK_SIG (reply, "a{ss}ii", error, ret)
+
+ dbus_message_iter_init (reply, &iter);
+ ret = _atspi_dbus_hash_from_iter (&iter);
+ dbus_message_iter_next (&iter);
+
+ dbus_message_iter_get_basic (&iter, &d_start_offset);
+ if (start_offset)
+ *start_offset = d_start_offset;
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_get_basic (&iter, &d_end_offset);
+ if (end_offset)
+ *end_offset = d_end_offset;
+
+ dbus_message_unref (reply);
+ return ret;
+}
+
+/**
+ * atspi_text_get_attribute_run:
+ * @obj: a pointer to the #AtspiText object to query.
+ * @offset: a #gint indicating the offset from which the attribute
+ * search is based.
+ * @include_defaults: a #bool that, when set as #FALSE, indicates the call
+ * should only return those attributes which are explicitly set on the current
+ * attribute run, omitting any attributes which are inherited from the
+ * default values.
+ * @start_offset: (out): a #gint pointer indicating the start of the desired text
+ * range.
+ * @end_offset: (out): a #gint pointer indicating the first character past the desired
+ * range.
+ *
+ * Gets a set of attributes applied to a range of text from an #AtspiText object, optionally
+ * including its 'default' attributes.
+ *
+ * Returns: (element-type gchar* gchar*) (transfer full): a #GHashTable with attributes
+ * defined at the indicated offset, optionally including the 'default' ones.
+ **/
+GHashTable *
+atspi_text_get_attribute_run (AtspiText *obj,
+ gint offset,
+ gboolean include_defaults,
+ gint *start_offset,
+ gint *end_offset,
+ GError **error)
+{
+ dbus_int32_t d_offset = offset;
+ dbus_int32_t d_start_offset, d_end_offset;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ GHashTable *ret = NULL;
+
+ if (obj == NULL)
+ return NULL;
+
+ reply = _atspi_dbus_call_partial (obj, atspi_interface_text,
+ "GetAttributeRun", error, "ib", d_offset,
+ include_defaults);
+ _ATSPI_DBUS_CHECK_SIG (reply, "a{ss}ii", error, ret)
+
+ dbus_message_iter_init (reply, &iter);
+ ret = _atspi_dbus_hash_from_iter (&iter);
+ dbus_message_iter_next (&iter);
+
+ dbus_message_iter_get_basic (&iter, &d_start_offset);
+ if (start_offset)
+ *start_offset = d_start_offset;
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_get_basic (&iter, &d_end_offset);
+ if (end_offset)
+ *end_offset = d_end_offset;
+
+ dbus_message_unref (reply);
+ return ret;
+}
+
+/**
+ * atspi_text_get_attribute_value: (rename-to atspi_text_get_text_attribute_value)
+ * @obj: a pointer to the #AtspiText object to query.
+ * @offset: The character offset at which to query the attribute.
+ * @attribute_name: The attribute to query.
+ *
+ * Gets the value of a named attribute at a given offset.
+ *
+ * Returns: (nullable): the value of a given attribute at the given
+ * offset, or %NULL if not present.
+ *
+ * Deprecated: 2.10: Use atspi_text_get_text_attribute_value instead.
+ **/
+gchar *
+atspi_text_get_attribute_value (AtspiText *obj,
+ gint offset,
+ gchar *attribute_value,
+ GError **error)
+{
+ return atspi_text_get_text_attribute_value (obj, offset, attribute_value,
+ error);
+}
+
+/**
+ * atspi_text_get_text_attribute_value:
+ * @obj: a pointer to the #AtspiText object to query.
+ * @offset: The character offset at which to query the attribute.
+ * @attribute_name: The attribute to query.
+ *
+ * Gets the value of a named attribute at a given offset.
+ *
+ * Returns: (nullable): the value of a given attribute at the given offset, or %NULL if
+ * not present.
+ **/
+gchar *
+atspi_text_get_text_attribute_value (AtspiText *obj,
+ gint offset,
+ gchar *attribute_value,
+ GError **error)
+{
+ gchar *retval = NULL;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ _atspi_dbus_call (obj, atspi_interface_text, "GetAttributeValue", error, "i=>s", offset, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_text_get_default_attributes:
+ * @obj: a pointer to the #AtspiText object to query.
+ *
+ * Gets the default attributes applied to an #AtspiText
+ * object. The text attributes correspond to CSS attributes
+ * where possible. The combination of this attribute set and
+ * the attributes reported by #atspi_text_get_attributes
+ * describes the entire set of text attributes over a range.
+ *
+ * Returns: (element-type gchar* gchar*) (transfer full): a #GHashTable
+ * containing the default attributes applied to a text object,
+ * (exclusive of explicitly-set attributes), encoded as UTF-8.
+ **/
+GHashTable *
+atspi_text_get_default_attributes (AtspiText *obj, GError **error)
+{
+ DBusMessage *reply;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ reply = _atspi_dbus_call_partial (obj, atspi_interface_text, "GetDefaultAttributes", error, "");
+ return _atspi_dbus_return_hash_from_message (reply);
+}
+
+
+/**
+ * atspi_text_set_caret_offset:
+ * @obj: a pointer to the #AtspiText object on which to operate.
+ * @new_offset: the offset to which the text caret is to be moved.
+ *
+ * Moves the text caret to a given position.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ **/
+gboolean
+atspi_text_set_caret_offset (AtspiText *obj,
+ gint new_offset,
+ GError **error)
+{
+ dbus_int32_t d_new_offset = new_offset;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_text, "SetCaretOffset", error, "i=>b", d_new_offset, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_text_get_text_before_offset:
+ * @obj: a pointer to the #AtspiText object on which to operate.
+ * @offset: a #gint indicating the offset from which the delimiter
+ * search is based.
+ * @type: an #AtspiTextBoundaryType indicating whether the desired
+ * text string is a word, sentence, line, or attribute run.
+ *
+ * Gets delimited text from an #AtspiText object which precedes a given
+ * text offset.
+ *
+ * Returns: an #AtspiTextRange containing a UTF-8 string representing the
+ * delimited text, both of whose delimiting boundaries are before the
+ * current offset, or an empty string if no such text exists.
+ **/
+AtspiTextRange *
+atspi_text_get_text_before_offset (AtspiText *obj,
+ gint offset,
+ AtspiTextBoundaryType type,
+ GError **error)
+{
+ dbus_int32_t d_offset = offset;
+ dbus_uint32_t d_type = type;
+ dbus_int32_t d_start_offset = -1, d_end_offset = -1;
+ AtspiTextRange *range = g_new0 (AtspiTextRange, 1);
+
+ range->start_offset = range->end_offset = -1;
+ if (!obj)
+ return range;
+
+ _atspi_dbus_call (obj, atspi_interface_text, "GetTextBeforeOffset", error,
+ "iu=>sii", d_offset, d_type, &range->content,
+ &d_start_offset, &d_end_offset);
+
+ range->start_offset = d_start_offset;
+ range->end_offset = d_end_offset;
+ if (!range->content)
+ range->content = g_strdup ("");
+
+ return range;
+}
+
+/**
+ * atspi_text_get_string_at_offset:
+ * @obj: an #AtspiText
+ * @offset: position
+ * @granularity: An #AtspiTextGranularity
+ *
+ * Gets a portion of the text exposed through an #AtspiText according to a given @offset
+ * and a specific @granularity, along with the start and end offsets defining the
+ * boundaries of such a portion of text.
+ *
+ * If @granularity is ATSPI_TEXT_GRANULARITY_CHAR the character at the
+ * offset is returned.
+ *
+ * If @granularity is ATSPI_TEXT_GRANULARITY_WORD the returned string
+ * is from the word start at or before the offset to the word start after
+ * the offset.
+ *
+ * The returned string will contain the word at the offset if the offset
+ * is inside a word and will contain the word before the offset if the
+ * offset is not inside a word.
+ *
+ * If @granularity is ATSPI_TEXT_GRANULARITY_SENTENCE the returned string
+ * is from the sentence start at or before the offset to the sentence
+ * start after the offset.
+ *
+ * The returned string will contain the sentence at the offset if the offset
+ * is inside a sentence and will contain the sentence before the offset
+ * if the offset is not inside a sentence.
+ *
+ * If @granularity is ATSPI_TEXT_GRANULARITY_LINE the returned string
+ * is from the line start at or before the offset to the line
+ * start after the offset.
+ *
+ * If @granularity is ATSPI_TEXT_GRANULARITY_PARAGRAPH the returned string
+ * is from the start of the paragraph at or before the offset to the start
+ * of the following paragraph after the offset.
+ *
+ * Since: 2.9.90
+ *
+ * Returns: a newly allocated string containing the text at the @offset bounded
+ * by the specified @granularity. Use g_free() to free the returned string.
+ * Returns %NULL if the offset is invalid or no implementation is available.
+ **/
+AtspiTextRange *
+atspi_text_get_string_at_offset (AtspiText *obj,
+ gint offset,
+ AtspiTextGranularity granularity,
+ GError **error)
+{
+ dbus_int32_t d_offset = offset;
+ dbus_uint32_t d_granularity = granularity;
+ dbus_int32_t d_start_offset = -1, d_end_offset = -1;
+ AtspiTextRange *range = g_new0 (AtspiTextRange, 1);
+
+ range->start_offset = range->end_offset = -1;
+ if (!obj)
+ return range;
+
+ _atspi_dbus_call (obj, atspi_interface_text, "GetStringAtOffset", error,
+ "iu=>sii", d_offset, d_granularity, &range->content,
+ &d_start_offset, &d_end_offset);
+
+ range->start_offset = d_start_offset;
+ range->end_offset = d_end_offset;
+ if (!range->content)
+ range->content = g_strdup ("");
+
+ return range;
+}
+
+/**
+ * atspi_text_get_text_at_offset:
+ * @obj: a pointer to the #AtspiText object on which to operate.
+ * @offset: a #gint indicating the offset from which the delimiter
+ * search is based.
+ * @type: an #AtspiTextBoundaryType indicating whether the desired
+ * text string is a word, sentence, line, or attribute run.
+ *
+ * Gets delimited text from an #AtspiText object which includes a given
+ * text offset.
+ *
+ * Returns: an #AtspiTextRange containing a UTF-8 string representing the
+ * delimited text, whose delimiting boundaries bracket the
+ * current offset, or an empty string if no such text exists.
+ *
+ * Deprecated: 2.10: Use atspi_text_get_string_at_offset.
+ **/
+AtspiTextRange *
+atspi_text_get_text_at_offset (AtspiText *obj,
+ gint offset,
+ AtspiTextBoundaryType type,
+ GError **error)
+{
+ dbus_int32_t d_offset = offset;
+ dbus_uint32_t d_type = type;
+ dbus_int32_t d_start_offset = -1, d_end_offset = -1;
+ AtspiTextRange *range = g_new0 (AtspiTextRange, 1);
+
+ range->start_offset = range->end_offset = -1;
+ if (!obj)
+ return range;
+
+ _atspi_dbus_call (obj, atspi_interface_text, "GetTextAtOffset", error,
+ "iu=>sii", d_offset, d_type, &range->content,
+ &d_start_offset, &d_end_offset);
+
+ range->start_offset = d_start_offset;
+ range->end_offset = d_end_offset;
+ if (!range->content)
+ range->content = g_strdup ("");
+
+ return range;
+}
+
+/**
+ * atspi_text_get_text_after_offset:
+ * @obj: a pointer to the #AtspiText object on which to operate.
+ * @offset: a #gint indicating the offset from which the delimiter
+ * search is based.
+ * @type: an #AtspiTextBoundaryType indicating whether the desired
+ * text string is a word, sentence, line, or attribute run.
+ *
+ * Gets delimited text from an #AtspiText object which follows a given
+ * text offset.
+ *
+ * Returns: an #AtspiTextRange containing a UTF-8 string representing the
+ * delimited text, both of whose delimiting boundaries are after or
+ * inclusive of the current offset, or an empty string if no such
+ * text exists.
+ **/
+AtspiTextRange *
+atspi_text_get_text_after_offset (AtspiText *obj,
+ gint offset,
+ AtspiTextBoundaryType type,
+ GError **error)
+{
+ dbus_int32_t d_offset = offset;
+ dbus_uint32_t d_type = type;
+ dbus_int32_t d_start_offset = -1, d_end_offset = -1;
+ AtspiTextRange *range = g_new0 (AtspiTextRange, 1);
+
+ range->start_offset = range->end_offset = -1;
+ if (!obj)
+ return range;
+
+ _atspi_dbus_call (obj, atspi_interface_text, "GetTextAfterOffset", error,
+ "iu=>sii", d_offset, d_type, &range->content,
+ &d_start_offset, &d_end_offset);
+
+ range->start_offset = d_start_offset;
+ range->end_offset = d_end_offset;
+ if (!range->content)
+ range->content = g_strdup ("");
+
+ return range;
+}
+
+/**
+ * atspi_text_get_character_at_offset:
+ * @obj: a pointer to the #AtspiText object on which to operate.
+ * @offset: a #gint indicating the text offset where the desired
+ * character is located.
+ *
+ * Gets the character at a given offset for an #AtspiText object.
+ *
+ * Returns: a #guint representing the
+ * UCS-4 unicode code point of the given character, or
+ * 0xFFFFFFFF if the character in question cannot be represented
+ * in the UCS-4 encoding.
+ **/
+guint
+atspi_text_get_character_at_offset (AtspiText *obj,
+ gint offset,
+ GError **error)
+{
+ dbus_int32_t d_offset = offset;
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_call (obj, atspi_interface_text, "GetCharacterAtOffset", error, "i=>i", d_offset, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_text_get_character_extents:
+ * @obj: a pointer to the #AtspiText object on which to operate.
+ * @offset: a #gint indicating the offset of the text character for
+ * whom boundary information is requested.
+ * @type: an #AccessibleCoordType indicating the coordinate system to use
+ * for the returned values.
+ *
+ * Gets a bounding box containing the glyph representing
+ * the character at a particular text offset.
+ *
+ * Returns: An #AtspiRect specifying the position and size of the character.
+ *
+ **/
+AtspiRect *
+atspi_text_get_character_extents (AtspiText *obj,
+ gint offset,
+ AtspiCoordType type,
+ GError **error)
+{
+ dbus_int32_t d_offset = offset;
+ dbus_uint32_t d_type = type;
+ dbus_int32_t d_x, d_y, d_width, d_height;
+ AtspiRect ret;
+
+ ret.x = ret.y = ret.width = ret.height = -1;
+
+ if (obj == NULL)
+ return atspi_rect_copy (&ret);
+
+ _atspi_dbus_call (obj, atspi_interface_text, "GetCharacterExtents", error, "iu=>iiii", d_offset, d_type, &d_x, &d_y, &d_width, &d_height);
+
+ ret.x = d_x;
+ ret.y = d_y;
+ ret.width = d_width;
+ ret.height = d_height;
+ return atspi_rect_copy (&ret);
+}
+
+/**
+ * atspi_text_get_offset_at_point:
+ * @obj: a pointer to the #AtspiText object on which to operate.
+ * @x: the x coordinate of the point to be queried.
+ * @y: the y coordinate of the point to be queried.
+ * @type: an #AtspiCoordType indicating the coordinate system in which
+ * the values should be returned.
+ *
+ * Gets the character offset into the text at a given point.
+ *
+ * Returns: the offset (as a #gint) at the point (@x, @y)
+ * in the specified coordinate system.
+ *
+ **/
+gint
+atspi_text_get_offset_at_point (AtspiText *obj,
+ gint x,
+ gint y,
+ AtspiCoordType type,
+ GError **error)
+{
+ dbus_int32_t d_x = x, d_y = y;
+ dbus_uint32_t d_type = type;
+ dbus_int32_t retval = -1;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_call (obj, atspi_interface_text, "GetOffsetAtPoint", error, "iiu=>i", d_x, d_y, d_type, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_text_get_range_extents:
+ * @obj: a pointer to the #AtspiText object on which to operate.
+ * @start_offset: a #gint indicating the offset of the first text character for
+ * whom boundary information is requested.
+ * @end_offset: a #gint indicating the offset of the text character
+ * after the last character for whom boundary information is requested.
+ * @type: an #AtspiCoordType indicating the coordinate system to use
+ * for the returned values.
+ *
+ * Gets the bounding box for text within a range in an #AtspiText object.
+ *
+ * Returns: An #AtspiRect giving the position and size of the specified range
+ * of text.
+ *
+ **/
+AtspiRect *
+atspi_text_get_range_extents (AtspiText *obj,
+ gint start_offset,
+ gint end_offset,
+ AtspiCoordType type,
+ GError **error)
+{
+ dbus_int32_t d_start_offset = start_offset, d_end_offset = end_offset;
+ dbus_uint32_t d_type = type;
+ dbus_int32_t d_x, d_y, d_width, d_height;
+ AtspiRect ret;
+
+ ret.x = ret.y = ret.width = ret.height = -1;
+
+ if (obj == NULL)
+ return atspi_rect_copy (&ret);
+
+ _atspi_dbus_call (obj, atspi_interface_text, "GetRangeExtents", error, "iiu=>iiii", d_start_offset, d_end_offset, d_type, &d_x, &d_y, &d_width, &d_height);
+
+ ret.x = d_x;
+ ret.y = d_y;
+ ret.width = d_width;
+ ret.height = d_height;
+ return atspi_rect_copy (&ret);
+}
+
+/**
+ * atspi_text_get_bounded_ranges:
+ * @obj: a pointer to the #AtspiText object on which to operate.
+ * @x: the 'starting' x coordinate of the bounding box.
+ * @y: the 'starting' y coordinate of the bounding box.
+ * @width: the x extent of the bounding box.
+ * @height: the y extent of the bounding box.
+ * @type: an #AccessibleCoordType indicating the coordinate system to use
+ * for the returned values.
+ * @clipTypeX: an #AtspiTextClipType indicating how to treat characters that
+ * intersect the bounding box's x extents.
+ * @clipTypeY: an #AtspiTextClipType indicating how to treat characters that
+ * intersect the bounding box's y extents.
+ *
+ * Gets the ranges of text from an #AtspiText object which lie within the
+ * bounds defined by (@x, @y) and (@x+@width, @y+@height).
+ *
+ * Returns: (transfer full) (element-type AtspiTextRange*): a null-terminated list of
+ * pointers to #AtspiTextRange structs detailing the bounded text.
+ **/
+GArray *
+atspi_text_get_bounded_ranges (AtspiText *obj,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ AtspiCoordType type,
+ AtspiTextClipType clipTypeX,
+ AtspiTextClipType clipTypeY,
+ GError **error)
+{
+ dbus_int32_t d_x = x, d_y = y, d_width = width, d_height = height;
+ dbus_uint32_t d_type = type;
+ dbus_uint32_t d_clipTypeX = clipTypeX, d_clipTypeY = clipTypeY;
+ GArray *range_seq = NULL;
+
+ g_return_val_if_fail (obj != NULL, NULL);
+
+ _atspi_dbus_call (obj, atspi_interface_text, "GetBoundedRanges", error, "iiiiuuu=>a(iisv)", d_x, d_y, d_width, d_height, d_type, d_clipTypeX, d_clipTypeY, &range_seq);
+
+ return range_seq;
+}
+
+/**
+ * atspi_text_get_n_selections:
+ * @obj: a pointer to the #AtspiText object on which to operate.
+ *
+ * Gets the number of active non-contiguous selections for an
+ * #AtspiText object.
+ *
+ * Returns: a #gint indicating the current
+ * number of non-contiguous text selections active
+ * within an #AtspiText object.
+ **/
+gint
+atspi_text_get_n_selections (AtspiText *obj, GError **error)
+{
+ dbus_int32_t retval = 0;
+
+ g_return_val_if_fail (obj != NULL, -1);
+
+ _atspi_dbus_call (obj, atspi_interface_text, "GetNSelections", error, "=>i", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_text_get_selection:
+ * @obj: a pointer to the #AtspiText object on which to operate.
+ * @selection_num: a #gint indicating which selection to query.
+ *
+ * Gets the bounds of the @selection_num-th active text selection for an
+ * #AtspiText object.
+ **/
+AtspiRange *
+atspi_text_get_selection (AtspiText *obj,
+ gint selection_num,
+ GError **error)
+{
+ dbus_int32_t d_selection_num = selection_num;
+ dbus_int32_t d_start_offset, d_end_offset;
+ AtspiRange *ret = g_new (AtspiRange, 1);
+
+ ret->start_offset = ret->end_offset = -1;
+
+ if (!obj)
+ return ret;
+
+ _atspi_dbus_call (obj, atspi_interface_text, "GetSelection", error, "i=>ii", d_selection_num, &d_start_offset, &d_end_offset);
+
+ ret->start_offset = d_start_offset;
+ ret->end_offset = d_end_offset;
+ return ret;
+}
+
+/**
+ * atspi_text_add_selection:
+ * @obj: a pointer to the #AtspiText object on which to operate.
+ * @start_offset: the starting offset of the desired new selection.
+ * @end_offset: the offset of the first character after the new selection.
+ *
+ * Selects some text (adds a text selection) in an #AtspiText object.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ **/
+gboolean
+atspi_text_add_selection (AtspiText *obj,
+ gint start_offset, gint end_offset,
+ GError **error)
+{
+ dbus_int32_t d_start_offset = start_offset, d_end_offset = end_offset;
+ dbus_bool_t retval = FALSE;
+
+ _atspi_dbus_call (obj, atspi_interface_text, "AddSelection", error, "ii=>b", d_start_offset, d_end_offset, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_text_remove_selection:
+ * @obj: a pointer to the #AtspiText object on which to operate.
+ * @selection_num: a #gint indicating which text selection to remove.
+ *
+ * De-selects a text selection.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ **/
+gboolean
+atspi_text_remove_selection (AtspiText *obj,
+ gint selection_num,
+ GError **error)
+{
+ dbus_int32_t d_selection_num = selection_num;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_text, "RemoveSelection", error, "i=>b", d_selection_num, &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_text_set_selection:
+ * @obj: a pointer to the #AtspiText object on which to operate.
+ * @selection_num: a zero-offset index indicating which text selection to modify.
+ * @start_offset: a #gint indicating the new starting offset for the selection.
+ * @end_offset: a #gint indicating the desired new offset of the first character
+ * after the selection.
+ *
+ * Changes the bounds of an existing #AtspiText text selection.
+ *
+ * Returns: #TRUE if successful, #FALSE otherwise.
+ **/
+gboolean
+atspi_text_set_selection (AtspiText *obj,
+ gint selection_num,
+ gint start_offset,
+ gint end_offset,
+ GError **error)
+{
+ dbus_int32_t d_selection_num = selection_num, d_start_offset = start_offset, d_end_offset = end_offset;
+ dbus_bool_t retval = FALSE;
+
+ g_return_val_if_fail (obj != NULL, FALSE);
+
+ _atspi_dbus_call (obj, atspi_interface_text, "SetSelection", error, "iii=>b", d_selection_num, d_start_offset, d_end_offset, &retval);
+
+ return retval;
+}
+
+static void
+atspi_text_base_init (AtspiText *klass)
+{
+}
+
+GType
+atspi_text_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (AtspiText),
+ (GBaseInitFunc) atspi_text_base_init,
+ (GBaseFinalizeFunc) NULL,
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE, "AtspiText", &tinfo, 0);
+
+ }
+ return type;
+}
diff --git a/atspi/atspi-text.h b/atspi/atspi-text.h
new file mode 100644
index 0000000..8e11eb0
--- /dev/null
+++ b/atspi/atspi-text.h
@@ -0,0 +1,142 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_TEXT_H_
+#define _ATSPI_TEXT_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+typedef struct _AtspiRange AtspiRange;
+struct _AtspiRange
+{
+ gint start_offset;
+ gint end_offset;
+};
+
+/**
+ * ATSPI_TYPE_RANGE:
+ *
+ * The #GType for a boxed type holding a range within a text bock.
+ */
+#define ATSPI_TYPE_RANGE atspi_range_get_type ()
+
+GType atspi_range_get_type ();
+
+AtspiRange *
+atspi_range_copy (AtspiRange *src);
+
+typedef struct _AtspiTextRange AtspiTextRange;
+struct _AtspiTextRange
+{
+ gint start_offset;
+ gint end_offset;
+ gchar *content;
+};
+
+/**
+ * ATSPI_TYPE_TEXT_RANGE:
+ *
+ * The #GType for a boxed type holding a range within a text bock.
+ */
+#define ATSPI_TYPE_TEXT_RANGE atspi_text_range_get_type ()
+
+#define ATSPI_TYPE_TEXT (atspi_text_get_type ())
+#define ATSPI_IS_TEXT(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_TEXT)
+#define ATSPI_TEXT(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_TEXT, AtspiText)
+#define ATSPI_TEXT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_TEXT, AtspiText))
+
+GType atspi_text_get_type ();
+
+struct _AtspiText
+{
+ GTypeInterface parent;
+};
+
+
+GType atspi_text_range_get_type ();
+
+gint atspi_text_get_character_count (AtspiText *obj, GError **error);
+
+gchar * atspi_text_get_text (AtspiText *obj, gint start_offset, gint end_offset, GError **error);
+
+gint atspi_text_get_caret_offset (AtspiText *obj, GError **error);
+
+#ifndef ATSPI_DISABLE_DEPRECATED
+GHashTable *atspi_text_get_attributes (AtspiText *obj, gint offset, gint *start_offset, gint *end_offset, GError **error);
+#endif
+
+GHashTable *atspi_text_get_text_attributes (AtspiText *obj, gint offset, gint *start_offset, gint *end_offset, GError **error);
+
+GHashTable *atspi_text_get_attribute_run (AtspiText *obj, gint offset, gboolean include_defaults, gint *start_offset, gint *end_offset, GError **error);
+
+#ifndef ATSPI_DISABLE_DEPRECATED
+gchar * atspi_text_get_attribute_value (AtspiText *obj, gint offset, gchar *attribute_name, GError **error);
+#endif
+
+gchar * atspi_text_get_text_attribute_value (AtspiText *obj, gint offset, gchar *attribute_name, GError **error);
+
+GHashTable * atspi_text_get_default_attributes (AtspiText *obj, GError **error);
+
+gboolean atspi_text_set_caret_offset (AtspiText *obj, gint new_offset, GError **error);
+
+#ifndef ATSPI_DISABLE_DEPRECATED
+AtspiTextRange * atspi_text_get_text_before_offset (AtspiText *obj, gint offset, AtspiTextBoundaryType type, GError **error);
+
+AtspiTextRange * atspi_text_get_text_at_offset (AtspiText *obj, gint offset, AtspiTextBoundaryType type, GError **error);
+
+AtspiTextRange * atspi_text_get_text_after_offset (AtspiText *obj, gint offset, AtspiTextBoundaryType type, GError **error);
+#endif
+
+AtspiTextRange * atspi_text_get_string_at_offset (AtspiText *obj, gint offset, AtspiTextGranularity granularity, GError **error);
+
+guint atspi_text_get_character_at_offset (AtspiText *obj, gint offset, GError **error);
+
+AtspiRect * atspi_text_get_character_extents (AtspiText *obj, gint offset, AtspiCoordType type, GError **error);
+
+gint atspi_text_get_offset_at_point (AtspiText *obj, gint x, gint y, AtspiCoordType type, GError **error);
+
+AtspiRect * atspi_text_get_range_extents (AtspiText *obj, gint start_offset, gint end_offset, AtspiCoordType type, GError **error);
+
+GArray * atspi_text_get_bounded_ranges (AtspiText *obj, gint x, gint y, gint width, gint height, AtspiCoordType type, AtspiTextClipType clipTypeX, AtspiTextClipType clipTypeY, GError **error);
+
+gint atspi_text_get_n_selections (AtspiText *obj, GError **error);
+
+AtspiRange * atspi_text_get_selection (AtspiText *obj, gint selection_num, GError **error);
+
+gboolean atspi_text_add_selection (AtspiText *obj, gint start_offset, gint end_offset, GError **error);
+
+gboolean atspi_text_remove_selection (AtspiText *obj, gint selection_num, GError **error);
+
+gboolean atspi_text_set_selection (AtspiText *obj, gint selection_num, gint start_offset, gint end_offset, GError **error);
+
+G_END_DECLS
+
+#endif /* _ATSPI_TEXT_H_ */
diff --git a/atspi/atspi-types.h b/atspi/atspi-types.h
new file mode 100644
index 0000000..e458a8e
--- /dev/null
+++ b/atspi/atspi-types.h
@@ -0,0 +1,158 @@
+/*
+ * 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_TYPES_H_
+#define _ATSPI_TYPES_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+
+typedef struct _AtspiAccessible AtspiAccessible;
+typedef struct _AtspiAction AtspiAction;
+typedef struct _AtspiCollection AtspiCollection;
+typedef struct _AtspiComponent AtspiComponent;
+typedef struct _AtspiDocument AtspiDocument;
+typedef struct _AtspiEditableText AtspiEditableText;
+typedef struct _AtspiHyperlink AtspiHyperlink;
+typedef struct _AtspiHypertext AtspiHypertext;
+typedef struct _AtspiImage AtspiImage;
+typedef struct _AtspiSelection AtspiSelection;
+typedef struct _AtspiTable AtspiTable;
+typedef struct _AtspiTableCell AtspiTableCell;
+typedef struct _AtspiText AtspiText;
+typedef struct _AtspiValue AtspiValue;
+
+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
+{
+ gchar *type;
+ AtspiAccessible *source;
+ gint detail1;
+ gint detail2;
+ GValue any_data;
+};
+
+/**
+ * ATSPI_TYPE_DEVICE_EVENT:
+ *
+ * The #GType for a boxed type holding a #AtspiDeviceEvent.
+ */
+#define ATSPI_TYPE_DEVICE_EVENT (atspi_device_event_get_type ())
+
+/**
+ * ATSPI_TYPE_EVENT:
+ *
+ * The #GType for a boxed type holding a #AtspiEvent.
+ */
+#define ATSPI_TYPE_EVENT (atspi_event_get_type ())
+
+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:
+ * @ATSPI_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.
+ * @ATSPI_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.
+ * @ATSPI_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.
+ *
+ * Specifies the type of a key listener event.
+ * 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 << 0,
+ ATSPI_KEYLISTENER_CANCONSUME = 1 << 1,
+ ATSPI_KEYLISTENER_ALL_WINDOWS = 1 << 2
+} AtspiKeyListenerSyncType;
+#endif /* _ATSPI_TYPES_H_ */
diff --git a/atspi/atspi-value.c b/atspi/atspi-value.c
new file mode 100644
index 0000000..642533d
--- /dev/null
+++ b/atspi/atspi-value.c
@@ -0,0 +1,177 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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"
+
+/**
+ * atspi_value_get_minimum_value:
+ * @obj: a pointer to the #AtspiValue implementor on which to operate.
+ *
+ * Gets the minimum allowed value for an #AtspiValue.
+ *
+ * Returns: the minimum allowed value for this object.
+ *
+ **/
+gdouble
+atspi_value_get_minimum_value (AtspiValue *obj, GError **error)
+{
+ double retval;
+
+ g_return_val_if_fail (obj != NULL, 0.0);
+ _atspi_dbus_get_property (obj, atspi_interface_value, "MinimumValue", error, "d", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_value_get_current_value:
+ * @obj: a pointer to the #AtspiValue implementor on which to operate.
+ *
+ * Gets the current value for an #AtspiValue.
+ *
+ * Returns: the current value for this object.
+ **/
+gdouble
+atspi_value_get_current_value (AtspiValue *obj, GError **error)
+{
+ double retval;
+
+ g_return_val_if_fail (obj != NULL, 0.0);
+
+ _atspi_dbus_get_property (obj, atspi_interface_value, "CurrentValue", error, "d", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_value_get_maximum_value:
+ * @obj: a pointer to the #AtspiValue implementor on which to operate.
+ *
+ * Gets the maximum allowed value for an #AtspiValue.
+ *
+ * Returns: the maximum allowed value for this object.
+ **/
+gdouble
+atspi_value_get_maximum_value (AtspiValue *obj, GError **error)
+{
+ double retval;
+
+ g_return_val_if_fail (obj != NULL, 0.0);
+
+ _atspi_dbus_get_property (obj, atspi_interface_value, "MaximumValue", error, "d", &retval);
+
+ return retval;
+}
+
+/**
+ * atspi_value_set_current_value:
+ * @obj: a pointer to the #AtspiValue implementor on which to operate.
+ * @new_value: a #gdouble value which is the desired new value of the object.
+ *
+ * Sets the current value of an #AtspiValue.
+ *
+ * Returns: #TRUE if the value could be assigned the specified value,
+ * #FALSE otherwise.
+ **/
+gboolean
+atspi_value_set_current_value (AtspiValue *obj, gdouble new_value, GError **error)
+{
+ double d_new_value = new_value;
+ DBusMessage *message, *reply;
+ DBusMessageIter iter, iter_variant;
+ static const char *str_curval = "CurrentValue";
+ AtspiAccessible *accessible = ATSPI_ACCESSIBLE (obj);
+
+ g_return_val_if_fail (accessible != NULL, FALSE);
+
+ if (!accessible->parent.app || !accessible->parent.app->bus_name)
+{
+ g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_APPLICATION_GONE,
+ _("The application no longer exists"));
+ return FALSE;
+ }
+
+ message = dbus_message_new_method_call (accessible->parent.app->bus_name,
+ accessible->parent.path,
+ DBUS_INTERFACE_PROPERTIES, "Set");
+ if (!message)
+ return FALSE;
+ dbus_message_append_args (message, DBUS_TYPE_STRING, &atspi_interface_value,
+ DBUS_TYPE_STRING, &str_curval,
+ DBUS_TYPE_INVALID);
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "d", &iter_variant);
+ dbus_message_iter_append_basic (&iter_variant, DBUS_TYPE_DOUBLE, &d_new_value);
+ dbus_message_iter_close_container (&iter, &iter_variant);
+ reply = _atspi_dbus_send_with_reply_and_block (message, error);
+ dbus_message_unref (reply);
+
+ return TRUE;
+}
+
+/**
+ * atspi_value_get_minimum_increment:
+ * @obj: a pointer to the #AtspiValue implementor on which to operate.
+ *
+ * Gets the minimum increment by which an #AtspiValue can be adjusted.
+ *
+ * Returns: the minimum increment by which the value may be changed, or
+ * zero if the minimum increment cannot be determined.
+ *
+ **/
+gdouble
+atspi_value_get_minimum_increment (AtspiValue *obj, GError **error)
+{
+ double retval;
+
+ g_return_val_if_fail (obj != NULL, 0.0);
+
+ _atspi_dbus_get_property (obj, atspi_interface_value, "MinimumIncrement", error, "d", &retval);
+
+ return retval;
+}
+
+static void
+atspi_value_base_init (AtspiValue *klass)
+{
+}
+
+GType
+atspi_value_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (AtspiValue),
+ (GBaseInitFunc) atspi_value_base_init,
+ (GBaseFinalizeFunc) NULL,
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE, "AtspiValue", &tinfo, 0);
+
+ }
+ return type;
+}
diff --git a/atspi/atspi-value.h b/atspi/atspi-value.h
new file mode 100644
index 0000000..6a1e531
--- /dev/null
+++ b/atspi/atspi-value.h
@@ -0,0 +1,61 @@
+/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * Copyright 2002 Ximian, Inc.
+ * 2002 Sun Microsystems Inc.
+ * Copyright 2010, 2011 Novell, Inc.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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_VALUE_H_
+#define _ATSPI_VALUE_H_
+
+#include "glib-object.h"
+
+#include "atspi-constants.h"
+
+#include "atspi-types.h"
+
+G_BEGIN_DECLS
+
+#define ATSPI_TYPE_VALUE (atspi_value_get_type ())
+#define ATSPI_IS_VALUE(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_VALUE)
+#define ATSPI_VALUE(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_VALUE, AtspiValue)
+#define ATSPI_VALUE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_VALUE, AtspiValue))
+
+GType atspi_value_get_type ();
+
+struct _AtspiValue
+{
+ GTypeInterface parent;
+};
+
+gdouble atspi_value_get_minimum_value (AtspiValue *obj, GError **error);
+
+gdouble atspi_value_get_current_value (AtspiValue *obj, GError **error);
+
+gdouble atspi_value_get_maximum_value (AtspiValue *obj, GError **error);
+
+gboolean atspi_value_set_current_value (AtspiValue *obj, gdouble new_value, GError **error);
+
+gdouble atspi_value_get_minimum_increment (AtspiValue *obj, GError **error);
+
+G_END_DECLS
+
+#endif /* _ATSPI_VALUE_H_ */
diff --git a/atspi/atspi.h b/atspi/atspi.h
new file mode 100644
index 0000000..dc92de0
--- /dev/null
+++ b/atspi/atspi.h
@@ -0,0 +1,56 @@
+/*
+ * 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-types.h"
+#include "atspi-accessible.h"
+#include "atspi-action.h"
+#include "atspi-collection.h"
+#include "atspi-component.h"
+#include "atspi-device-listener.h"
+#include "atspi-document.h"
+#include "atspi-editabletext.h"
+#include "atspi-event-listener.h"
+#include "atspi-hyperlink.h"
+#include "atspi-hypertext.h"
+#include "atspi-image.h"
+#include "atspi-matchrule.h"
+#include "atspi-misc.h"
+#include "atspi-registry.h"
+#include "atspi-relation.h"
+#include "atspi-selection.h"
+#include "atspi-stateset.h"
+#include "atspi-table.h"
+#include "atspi-table-cell.h"
+#include "atspi-text.h"
+#include "atspi-value.h"
+
+#include "atspi-gmain.h"
+
+#include "atspi-enum-types.h"
+#endif