diff options
author | jk7744.park <jk7744.park@samsung.com> | 2015-10-26 15:41:08 +0900 |
---|---|---|
committer | jk7744.park <jk7744.park@samsung.com> | 2015-10-26 15:41:08 +0900 |
commit | 728e3f7e6866b63f3c3772de381d4f40d66b7487 (patch) | |
tree | 768ee2fb4e95e5119ed03100c63cfe73490dd42e /atspi | |
parent | b178bd1793db6d0385664b6e1930ab417de34cf5 (diff) | |
download | at-spi2-core-tizen_2.4.tar.gz at-spi2-core-tizen_2.4.tar.bz2 at-spi2-core-tizen_2.4.zip |
tizen 2.4 releasetizen_2.4_mobile_releasesubmit/tizen_2.4/20151028.063435accepted/tizen/2.4/mobile/20151029.035129tizen_2.4accepted/tizen_2.4_mobile
Diffstat (limited to 'atspi')
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 + * "<Control>", "<Alt>", "<Shift>", "<Mod2>", + * 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, ×tamp); + 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 |