From 11d647c36278e2430df5df0c56546e267971e74a Mon Sep 17 00:00:00 2001 From: Mike Gorse Date: Tue, 26 Oct 2010 10:15:53 -0400 Subject: [PATCH] Initial commit, not even close to being usable yet --- Makefile.am | 9 +- atspi/atspi-accessible.c | 1213 ++++++++++++++++++++++++++++++++++++++++ atspi/atspi-accessible.h | 101 ++++ atspi/atspi-constants.h | 766 +++++++++++++++++++++++++ atspi/atspi-event-types.h | 128 +++++ atspi/atspi-listener-private.h | 37 ++ atspi/atspi-listener.c | 383 +++++++++++++ atspi/atspi-listener.h | 135 +++++ atspi/atspi-misc-private.h | 114 ++++ atspi/atspi-misc.c | 828 +++++++++++++++++++++++++++ atspi/atspi-misc.h | 36 ++ atspi/atspi-private.h | 33 ++ atspi/atspi-registry.c | 364 ++++++++++++ atspi/atspi-registry.h | 66 +++ atspi/atspi-stateset.c | 28 + atspi/atspi-stateset.h | 29 + atspi/atspi.h | 36 ++ configure.ac | 6 +- dbind/Makefile.am | 22 + dbind/dbind-any.c | 670 ++++++++++++++++++++++ dbind/dbind-any.h | 31 + dbind/dbind.c | 230 ++++++++ dbind/dbind.h | 49 ++ dbind/dbtest.c | 404 +++++++++++++ xml/Makefile.am | 6 +- 25 files changed, 5720 insertions(+), 4 deletions(-) create mode 100644 atspi/atspi-accessible.c create mode 100644 atspi/atspi-accessible.h create mode 100644 atspi/atspi-constants.h create mode 100644 atspi/atspi-event-types.h create mode 100644 atspi/atspi-listener-private.h create mode 100644 atspi/atspi-listener.c create mode 100644 atspi/atspi-listener.h create mode 100644 atspi/atspi-misc-private.h create mode 100644 atspi/atspi-misc.c create mode 100644 atspi/atspi-misc.h create mode 100644 atspi/atspi-private.h create mode 100644 atspi/atspi-registry.c create mode 100644 atspi/atspi-registry.h create mode 100644 atspi/atspi-stateset.c create mode 100644 atspi/atspi-stateset.h create mode 100644 atspi/atspi.h create mode 100644 dbind/Makefile.am create mode 100644 dbind/dbind-any.c create mode 100644 dbind/dbind-any.h create mode 100644 dbind/dbind.c create mode 100644 dbind/dbind.h create mode 100644 dbind/dbtest.c diff --git a/Makefile.am b/Makefile.am index 68f7dc6..4aba3ef 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,10 @@ -SUBDIRS=registryd tools xml bus libspi +DISTCHECK_CONFIGURE_FLAGS = --enable-introspection + +-include $(INTROSPECTION_MAKEFILE) +INTROSPECTION_GIRS = +INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) +INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir) + +SUBDIRS=registryd xml bus dbind atspi ACLOCAL_AMFLAGS=-I m4 diff --git a/atspi/atspi-accessible.c b/atspi/atspi-accessible.c new file mode 100644 index 0000000..2a9d071 --- /dev/null +++ b/atspi/atspi-accessible.c @@ -0,0 +1,1213 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "atspi-private.h" + +G_DEFINE_TYPE (AtspiAccessible, atspi_accessible, G_TYPE_OBJECT) + +static void +atspi_accessible_init (AtspiAccessible *accessible) +{ +} + +static void +atspi_accessible_class_init (AtspiAccessibleClass *klass) +{ +} +/* TODO: Generate following from spec? */ +static const char *role_names [] = +{ + "invalid", + "accel-label", + "alert", + "animation", + "arrow", + "calendar", + "canvas", + "check-box", + "check-menu-item", + "color-chooser", + "column-header", + "combo-box", + "date-editor", + "desktop-icon", + "desktop-frame", + "dial", + "dialog", + "directory-pane", + "drawing-area", + "file-chooser", + "filler", + "font-chooser", + "frame", + "glass-pane", + "html-container", + "icon", + "image", + "internalframe", + "label", + "layered-pane", + "list", + "list-item", + "menu", + "menu-bar", + "menu-item", + "option-pane", + "page-tab", + "page-tab-list", + "panel", + "password-text", + "popup-menu", + "progress-bar", + "push-button", + "radio-button", + "radio-menu-item", + "root-pane", + "row-header", + "scroll-bar", + "scroll-pane", + "separator", + "slider", + "spin-button", + "split-pane", + "statusbar", + "table", + "table-cell", + "table-column-header", + "table-row-header", + "tear-off-menu-item", + "terminal", + "text", + "toggle-button", + "tool-bar", + "tool-tip", + "tree", + "tree-table", + "unknown", + "viewport", + "window", + NULL, + "header", + "fooler", + "paragraph", + "ruler", + "application", + "autocomplete", + "editbar", + "embedded", + "entry", + "chart", + "caption", + "document_frame", + "heading", + "page", + "section", + "form", + "redundant object", + "link", + "input method window" +}; + +#define MAX_ROLES (sizeof (role_names) / sizeof (char *)) + +/** + * atspi_role_get_name + * @role: an #AtspiAccessibleRole object to query. + * + * Get a localizeable string that indicates the name of an #AtspiAccessibleRole. + * DEPRECATED. + * + * Returns: a localizable string name for an #AtspiAccessibleRole enumerated type. + **/ +gchar * +atspi_role_get_name (AtspiRole role) +{ + if (role < MAX_ROLES && role_names [(int) role]) + { + return g_strdup (role_names [(int) role]); + } + else + { + return g_strdup (""); + } +} + +/** + * atspi_accessible_get_name: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Get the name of an #AtspiAccessible object. + * + * Returns: a UTF-8 string indicating the name of the #AtspiAccessible object. + * or NULL on exception + **/ +gchar * +atspi_accessible_get_name (AtspiAccessible *obj, GError **error) +{ + g_return_val_if_fail (obj != NULL, NULL); + return g_strdup (obj->name); +} + +/** + * atspi_accessible_get_description: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Get the description of an #AtspiAccessible object. + * + * Returns: a UTF-8 string describing the #AtspiAccessible object. + * or NULL on exception + **/ +gchar * +atspi_accessible_get_description (AtspiAccessible *obj, GError **error) +{ + g_return_val_if_fail (obj != NULL, NULL); + + return g_strdup (obj->description); +} + +/** + * atspi_accessible_get_parent: + * @obj: a pointer to the #AtspiAccessible object to query. + * + * Get an #AtspiAccessible object's parent container. + * + * Returns: a pointer tothe #AtspiAccessible object which contains the given + * #AtspiAccessible instance, or NULL if the @obj has no parent container. + * + **/ +AtspiAccessible * +atspi_accessible_get_parent (AtspiAccessible *obj, GError **error) +{ + g_return_val_if_fail (obj != NULL, NULL); + + return g_object_ref (obj->accessible_parent); +} + +/** + * atspi_accessible_get_child_count: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Get the number of children contained by an #AtspiAccessible object. + * + * Returns: a #long indicating the number of #AtspiAccessible children + * contained by an #AtspiAccessible object. or -1 on exception + * + **/ +gint +atspi_accessible_get_child_count (AtspiAccessible *obj, GError *error) +{ + g_return_val_if_fail (obj != NULL, -1); + + /* TODO: MANAGES_DESCENDANTS */ + return g_list_length (obj->children); +} + +/** + * atspi_accessible_get_child_at_index: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * @child_index: a #long indicating which child is specified. + * + * Get the #AtspiAccessible child of an #AtspiAccessible object at a given index. + * + * Returns: a pointer to the #AtspiAccessible child object at index + * @child_index. or NULL on exception + **/ +AtspiAccessible * +atspi_accessible_get_child_at_index (AtspiAccessible *obj, + gint child_index, + GError **error) +{ + AtspiAccessible *child; + + g_return_val_if_fail (obj != NULL, NULL); + + /* TODO: ManagesDescendants */ + child = g_list_nth_data (obj->children, child_index); + return g_object_ref (child); +} + +/** + * atspi_accessible_get_index_in_parent + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Get the index of an #AtspiAccessible object in its containing #AtspiAccessible. + * + * Returns: a #glong indicating the index of the #AtspiAccessible object + * in its parent (i.e. containing) #AtspiAccessible instance, + * or -1 if @obj has no containing parent or on exception. + **/ +gint +atspi_accessible_get_index_in_parent (AtspiAccessible *obj, GError **error) +{ + GList *l; + gint i; + + g_return_val_if_fail (obj != NULL, -1); + if (!obj->accessible_parent) return -1; + l = obj->accessible_parent->children; + while (l) + { + if (l->data == obj) return i; + l = g_list_next (l); + i++; + } + return -1; +} + +typedef struct +{ + dbus_uint32_t type; + GArray *targets; +} Accessibility_Relation; + +/** + * atspi_accessible_get_relation_set: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Get the set of #AtspiRelation objects which describe this #AtspiAccessible object's + * relationships with other #AtspiAccessible objects. + * + * Returns: an array of #AtspiAccessibleRelation pointers. or NULL on exception + * TODO:: Annotate array type + **/ +GArray * +atspi_accessible_get_relation_set (AtspiAccessible *obj, GError **error) +{ + int i; + int n_relations; + GArray *relation_set; + + g_return_val_if_fail (obj != NULL, NULL); + + if (!_atspi_dbus_call (obj, atspi_interface_accessible, "GetRelationSet", error, "=>a(uao)", &relation_set)) + return NULL; + + return relation_set; +} + +/** + * atspi_accessible_get_role: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Get the UI role of an #AtspiAccessible object. + * A UTF-8 string describing this role can be obtained via atspi_accessible_getRoleName (). + * + * Returns: the #AtspiRole of the object. + * + **/ +AtspiRole +atspi_accessible_get_role (AtspiAccessible *obj, GError **error) +{ + g_return_val_if_fail (obj != NULL, ATSPI_ROLE_INVALID); + + return obj->role; +} + +/** + * atspi_accessible_get_role_name: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Get a UTF-8 string describing the role this object plays in the UI. + * This method will return useful values for roles that fall outside the + * enumeration used in atspi_accessible_getRole (). + * + * Returns: a UTF-8 string specifying the role of this #AtspiAccessible object. + * + **/ +gchar * +atspi_accessible_get_role_name (AtspiAccessible *obj, GError **error) +{ + char *retval = NULL; + + g_return_val_if_fail (obj != NULL, g_strdup ("invalid")); + + _atspi_dbus_call (obj, atspi_interface_accessible, "GetRoleName", error, "=>s", &retval); + + return retval; +} + +/** + * atspi_accessible_get_localized_role_name: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Get a UTF-8 string describing the (localized) role this object plays in the UI. + * This method will return useful values for roles that fall outside the + * enumeration used in atspi_accessible_getRole (). + * + * Returns: a UTF-8 string specifying the role of this #AtspiAccessible object. + * + **/ +gchar * +atspi_accessible_get_localized_role_name (AtspiAccessible *obj, GError **error) +{ + char *retval = NULL; + + g_return_val_if_fail (obj != NULL, g_strdup ("invalid")); + + _atspi_dbus_call (obj, atspi_interface_accessible, "GetLocalizedRoleName", error, "=>s", &retval); + + return retval; +} + +/** + * atspi_accessible_get_state_set: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Gets the current state of an object. + * + * Returns: a pointer to an #AtspiStateSet representing the object's current state. + **/ +AtspiStateSet * +atspi_accessible_get_state_set (AtspiAccessible *obj) +{ + return obj->states; +} + +/** + * atspi_accessible_get_attributes: + * @obj: The #AtspiAccessible being queried. + * + * Get the #AttributeSet representing any assigned + * name-value pair attributes or annotations for this object. + * For typographic, textual, or textually-semantic attributes, see + * atspi_text_get_attributes instead. + * + * Returns: The name-value-pair attributes assigned to this object. + */ +GHashTable * +atspi_accessible_get_attributes (AtspiAccessible *obj, GError **error) +{ + DBusMessage *message; + GHashTable *ret; + + g_return_val_if_fail (obj != NULL, NULL); + + message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetAttributes", error, ""); + ret = _atspi_dbus_hash_from_message (message); + dbus_message_unref (message); + return ret; +} + +/** + * atspi_accessible_get_host_application: + * @obj: The #AtspiAccessible being queried. + * + * Get the containing #AtspiApplication for an object. + * + * Returns: the containing AtspiApplication instance for this object. + */ +AtspiApplication * +atspi_accessible_get_host_application (AtspiAccessible *obj, GError **error) +{ + while (obj->accessible_parent) obj = obj->accessible_parent; + g_warning ("atspi: TODO: Application interface"); + //return atspi_accessible_get_application (obj); +} + +#if 0 // TODO: interfaces */ +/* Interface query methods */ + +/** + * atspi_accessible_is_action: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements #AtspiAction. + * + * Returns: #TRUE if @obj implements the #AtspiAction interface, + * #FALSE otherwise. + **/ +gboolean +atspi_accessible_is_action (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_action); +} + +/** + * atspi_accessible_is_application: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements #AtspiApplication. + * + * Returns: #TRUE if @obj implements the #AtspiApplication interface, + * #FALSE otherwise. + **/ +gboolean +atspi_accessible_is_application (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_application); +} + +/** + * atspi_accessible_is_collection: * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements #AtspiCollection. + * Returns: #TRUE if @obj implements the #AtspiCollection interface, + * #FALSE otherwise. + **/ +gboolean +atspi_accessible_is_collection (AtspiAccessible *obj) +{ +#if 0 + g_warning ("Collections not implemented"); + return _atspi_accessible_is_a (obj, + atspi_interface_collection); +#else + return FALSE; +#endif +} + +/** + * atspi_accessible_is_component: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements #AtspiComponent. + * + * Returns: #TRUE if @obj implements the #AtspiComponent interface, + * #FALSE otherwise. + **/ +gboolean +atspi_accessible_is_component (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_component); +} + +/** + * atspi_accessible_is_document: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements #AtspiDocument. + * + * Returns: #TRUE if @obj implements the #AtspiDocument interface, + * #FALSE otherwise. + **/ +gboolean +atspi_accessible_is_document (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_document); +} + +/** + * atspi_accessible_is_editable_text: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements #AtspiEditableText. + * + * Returns: #TRUE if @obj implements the #AtspiEditableText interface, + * #FALSE otherwise. + **/ +gboolean +atspi_accessible_is_editable_text (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_editable_text); +} + +/** + * atspi_accessible_is_hypertext: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements #AtspiHypertext. + * + * Returns: #TRUE if @obj implements the #AtspiHypertext interface, + * #FALSE otherwise. + **/ +gboolean +atspi_accessible_is_hypertext (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_hypertext); +} + +/** + * atspi_accessible_is_image: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements #AtspiImage. + * + * Returns: #TRUE if @obj implements the #AtspiImage interface, + * #FALSE otherwise. +**/ +gboolean +atspi_accessible_is_image (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_image); +} + +/** + * atspi_accessible_is_selection: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements #AtspiSelection. + * + * Returns: #TRUE if @obj implements the #AtspiSelection interface, + * #FALSE otherwise. +**/ +gboolean +atspi_accessible_is_selection (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_selection); +} + +/** + * atspi_accessible_is_table: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements #AtspiTable. + * + * Returns: #TRUE if @obj implements the #AtspiTable interface, + * #FALSE otherwise. +**/ +gboolean +atspi_accessible_is_table (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_table); +} + +/** + * atspi_accessible_is_streamable_content: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements + * #AtspiStreamableContent. + * + * Returns: #TRUE if @obj implements the #AtspiStreamableContent interface, + * #FALSE otherwise. +**/ +gboolean +atspi_accessible_is_streamable_content (AtspiAccessible *obj) +{ +#if 0 + return _atspi_accessible_is_a (obj, + atspi_interface_streamable_content); +#else + g_warning ("Streamable content not implemented"); + return FALSE; +#endif +} + +/** + * atspi_accessible_is_text: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements #AtspiText. + * + * Returns: #TRUE if @obj implements the #AtspiText interface, + * #FALSE otherwise. +**/ +gboolean +atspi_accessible_is_text (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_text); +} + +/** + * atspi_accessible_is_value: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements #AtspiValue. + * + * Returns: #TRUE if @obj implements the #AtspiValue interface, + * #FALSE otherwise. +**/ +gboolean +atspi_accessible_is_value (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_value); +} + +/** + * atspi_accessible_get_application: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Get the #AtspiApplication interface for an #AtspiAccessible. + * + * Returns: a pointer to an #AtspiApplication interface instance, or + * NULL if @obj does not implement #AtspiApplication. + **/ +AtspiApplication * +atspi_accessible_get_application (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_application) ? + ATSPI_APPLICATION (accessible) : NULL); +} + +/** + * atspi_accessible_get_action: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Get the #AtspiAction interface for an #AtspiAccessible. + * + * Returns: a pointer to an #AtspiAction interface instance, or + * NULL if @obj does not implement #AtspiAction. + **/ +AtspiAction * +atspi_accessible_get_action (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_action) ? + ATSPI_APPLICATION (accessible) : NULL); +} + +/** + * atspi_accessible_get_collection: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Get the #AtspiCollection interface for an #AtspiAccessible. + * + * Returns: a pointer to an #AtspiCollection interface instance, or + * NULL if @obj does not implement #AtspiCollection. + **/ +AtspiCollection * +atspi_accessible_get_collection (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_collection) ? + ATSPI_APPLICATION (accessible) : NULL); +} + +/** + * atspi_accessible_get_component: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Get the #AtspiComponent interface for an #AtspiAccessible. + * + * Returns: a pointer to an #AtspiComponent interface instance, or + * NULL if @obj does not implement #AtspiComponent. + **/ +AtspiComponent * +atspi_accessible_get_component (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_component) ? + ATSPI_APPLICATION (accessible) : NULL); +} + +/** + * atspi_accessible_get_document: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Get the #AtspiDocument interface for an #AtspiAccessible. + * + * Returns: a pointer to an #AtspiDocument interface instance, or + * NULL if @obj does not implement #AtspiDocument. + **/ +AtspiDocument * +atspi_accessible_get_document (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_document) ? + ATSPI_APPLICATION (accessible) : NULL); +} + +/** + * atspi_accessible_get_editable_text: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Get the #AtspiEditableText interface for an #AtspiAccessible. + * + * Returns: a pointer to an #AtspiEditableText interface instance, or + * NULL if @obj does not implement #AtspiEditableText. + **/ +AtspiEditableText * +atspi_accessible_get_editable_text (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_editable_text) ? + ATSPI_APPLICATION (accessible) : NULL); +} + +/** + * atspi_accessible_get_hypertext: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Get the #AtspiHypertext interface for an #AtspiAccessible. + * + * Returns: a pointer to an #AtspiHypertext interface instance, or + * NULL if @obj does not implement #AtspiHypertext. + **/ +AtspiHypertext * +atspi_accessible_get_hypertext (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_hypertext) ? + ATSPI_APPLICATION (accessible) : NULL); +} + +/** + * atspi_accessible_get_image: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Get the #AtspiImage interface for an #AtspiAccessible. + * + * Returns: a pointer to an #AtspiImage interface instance, or + * NULL if @obj does not implement #AtspiImage. + **/ +AtspiImage * +atspi_accessible_get_image (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_image) ? + ATSPI_APPLICATION (accessible) : NULL); +} + +/** + * atspi_accessible_get_selection: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Get the #AtspiSelection interface for an #AtspiAccessible. + * + * Returns: a pointer to an #AtspiSelection interface instance, or + * NULL if @obj does not implement #AtspiSelection. + **/ +AtspiSelection * +atspi_accessible_get_selection (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_selection) ? + ATSPI_APPLICATION (accessible) : NULL); +} + +/** + * atspi_accessible_get_streamable_content: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Get the #AtspiStreamableContent interface for an #AtspiAccessible. + * + * Returns: a pointer to an #AtspiStreamableContent interface instance, or + * NULL if @obj does not implement #AtspiStreamableContent. + **/ +AtspiStreamableContent * +atspi_accessible_get_streamable_content (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_streamable_content) ? + ATSPI_APPLICATION (accessible) : NULL); +} + +/** + * atspi_accessible_get_table: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Get the #AtspiTable interface for an #AtspiAccessible. + * + * Returns: a pointer to an #AtspiTable interface instance, or + * NULL if @obj does not implement #AtspiTable. + **/ +AtspiTable * +atspi_accessible_get_table (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_table) ? + ATSPI_APPLICATION (accessible) : NULL); +} + +/** + * atspi_accessible_get_text: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Get the #AtspiTable interface for an #AtspiAccessible. + * + * Returns: a pointer to an #AtspiTable interface instance, or + * NULL if @obj does not implement #AtspiTable. + **/ +AtspiTable * +atspi_accessible_get_text (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_text) ? + ATSPI_APPLICATION (accessible) : NULL); +} + +/** + * atspi_accessible_get_value: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Get the #AtspiTable interface for an #AtspiAccessible. + * + * Returns: a pointer to an #AtspiTable interface instance, or + * NULL if @obj does not implement #AtspiTable. + **/ +AtspiTable * +atspi_accessible_get_value (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_value) ? + ATSPI_APPLICATION (accessible) : NULL); +} + +static gboolean +cspi_init_relation_type_table (AccessibleRelationType *relation_type_table) +{ + int i; + for (i = 0; i < Accessibility_RELATION_LAST_DEFINED; ++i) + { + relation_type_table [i] = SPI_RELATION_NULL; + } + relation_type_table [Accessibility_RELATION_NULL] = SPI_RELATION_NULL; + relation_type_table [Accessibility_RELATION_LABEL_FOR] = SPI_RELATION_LABEL_FOR; + relation_type_table [Accessibility_RELATION_LABELLED_BY] = SPI_RELATION_LABELED_BY; + relation_type_table [Accessibility_RELATION_CONTROLLER_FOR] = SPI_RELATION_CONTROLLER_FOR; + relation_type_table [Accessibility_RELATION_CONTROLLED_BY] = SPI_RELATION_CONTROLLED_BY; + relation_type_table [Accessibility_RELATION_MEMBER_OF] = SPI_RELATION_MEMBER_OF; + relation_type_table [Accessibility_RELATION_TOOLTIP_FOR] = SPI_RELATION_NULL; + relation_type_table [Accessibility_RELATION_NODE_CHILD_OF] = SPI_RELATION_NODE_CHILD_OF; + relation_type_table [Accessibility_RELATION_EXTENDED] = SPI_RELATION_EXTENDED; + relation_type_table [Accessibility_RELATION_FLOWS_TO] = SPI_RELATION_FLOWS_TO; + relation_type_table [Accessibility_RELATION_FLOWS_FROM] = SPI_RELATION_FLOWS_FROM; + relation_type_table [Accessibility_RELATION_SUBWINDOW_OF] = SPI_RELATION_SUBWINDOW_OF; + relation_type_table [Accessibility_RELATION_EMBEDS] = SPI_RELATION_EMBEDS; + relation_type_table [Accessibility_RELATION_EMBEDDED_BY] = SPI_RELATION_EMBEDDED_BY; + relation_type_table [Accessibility_RELATION_POPUP_FOR] = SPI_RELATION_POPUP_FOR; + relation_type_table [Accessibility_RELATION_PARENT_WINDOW_OF] = SPI_RELATION_PARENT_WINDOW_OF; + relation_type_table [Accessibility_RELATION_DESCRIBED_BY] = SPI_RELATION_DESCRIBED_BY; + relation_type_table [Accessibility_RELATION_DESCRIPTION_FOR] = SPI_RELATION_DESCRIPTION_FOR; + return TRUE; +} + +static AccessibleRelationType +cspi_relation_type_from_spi_relation_type (Accessibility_RelationType type) +{ + /* array is sized according to IDL RelationType because IDL RelationTypes are the index */ + static AccessibleRelationType cspi_relation_type_table [Accessibility_RELATION_LAST_DEFINED]; + static gboolean is_initialized = FALSE; + AccessibleRelationType cspi_type; + if (!is_initialized) + { + is_initialized = cspi_init_relation_type_table (cspi_relation_type_table); + } + if (type >= 0 && type < Accessibility_RELATION_LAST_DEFINED) + { + cspi_type = cspi_relation_type_table [type]; + } + else + { + cspi_type = SPI_RELATION_NULL; + } + return cspi_type; +} +/** + * AccessibleRelation_getRelationType: + * @obj: a pointer to the #AtspiAccessibleRelation object to query. + * + * Get the type of relationship represented by an #AtspiAccessibleRelation. + * + * Returns: an #AtspiAccessibleRelationType indicating the type of relation + * encapsulated in this #AtspiAccessibleRelation object. + * + **/ +AccessibleRelationType +AccessibleRelation_getRelationType (AccessibleRelation *obj) +{ + cspi_return_val_if_fail (obj, SPI_RELATION_NULL); + return cspi_relation_type_from_spi_relation_type (obj->type); +} + +/** + * AccessibleRelation_getNTargets: + * @obj: a pointer to the #AtspiAccessibleRelation object to query. + * + * Get the number of objects which this relationship has as its + * target objects (the subject is the #AtspiAccessible from which this + * #AtspiAccessibleRelation originated). + * + * Returns: a short integer indicating how many target objects which the + * originating #AtspiAccessible object has the #AtspiAccessibleRelation + * relationship with. + **/ +int +AccessibleRelation_getNTargets (AccessibleRelation *obj) +{ + cspi_return_val_if_fail (obj, -1); + return obj->targets->len; +} + +/** + * AccessibleRelation_getTarget: + * @obj: a pointer to the #AtspiAccessibleRelation object to query. + * @i: a (zero-index) integer indicating which (of possibly several) target is requested. + * + * Get the @i-th target of a specified #AtspiAccessibleRelation relationship. + * + * Returns: an #AtspiAccessible which is the @i-th object with which the + * originating #AtspiAccessible has relationship specified in the + * #AtspiAccessibleRelation object. + * + **/ +Accessible * +AccessibleRelation_getTarget (AccessibleRelation *obj, int i) +{ + cspi_return_val_if_fail (obj, NULL); + + if (i < 0 || i >= obj->targets->len) return NULL; + return cspi_object_add ( + g_array_index (obj->targets, Accessible *, i)); +} + +/** + * AccessibleStateSet_ref: + * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate. + * + * Increment the reference count for an #AtspiAccessibleStateSet object. + * + **/ +void +AccessibleStateSet_ref (AccessibleStateSet *obj) +{ + spi_state_set_cache_ref (obj); +} + +/** + * AccessibleStateSet_unref: + * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate. + * + * Decrement the reference count for an #AtspiAccessibleStateSet object. + * + **/ +void +AccessibleStateSet_unref (AccessibleStateSet *obj) +{ + spi_state_set_cache_unref (obj); +} + +static Accessibility_StateType +spi_state_to_dbus (AccessibleState state) +{ +#define MAP_STATE(a) \ + case SPI_STATE_##a: \ + return Accessibility_STATE_##a + + switch (state) + { + MAP_STATE (INVALID); + MAP_STATE (ACTIVE); + MAP_STATE (ARMED); + MAP_STATE (BUSY); + MAP_STATE (CHECKED); + MAP_STATE (DEFUNCT); + MAP_STATE (EDITABLE); + MAP_STATE (ENABLED); + MAP_STATE (EXPANDABLE); + MAP_STATE (EXPANDED); + MAP_STATE (FOCUSABLE); + MAP_STATE (FOCUSED); + MAP_STATE (HORIZONTAL); + MAP_STATE (ICONIFIED); + MAP_STATE (MODAL); + MAP_STATE (MULTI_LINE); + MAP_STATE (MULTISELECTABLE); + MAP_STATE (OPAQUE); + MAP_STATE (PRESSED); + MAP_STATE (RESIZABLE); + MAP_STATE (SELECTABLE); + MAP_STATE (SELECTED); + MAP_STATE (SENSITIVE); + MAP_STATE (SHOWING); + MAP_STATE (SINGLE_LINE); + MAP_STATE (STALE); + MAP_STATE (TRANSIENT); + MAP_STATE (VERTICAL); + MAP_STATE (VISIBLE); + MAP_STATE (MANAGES_DESCENDANTS); + MAP_STATE (INDETERMINATE); + MAP_STATE (TRUNCATED); + MAP_STATE (REQUIRED); + MAP_STATE (INVALID_ENTRY); + MAP_STATE (SUPPORTS_AUTOCOMPLETION); + MAP_STATE (SELECTABLE_TEXT); + MAP_STATE (IS_DEFAULT); + MAP_STATE (VISITED); + default: + return Accessibility_STATE_INVALID; + } +#undef MAP_STATE +} + +/** + * AccessibleStateSet_contains: + * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate. + * @state: an #AtspiAccessibleState for which the specified #AtspiAccessibleStateSet + * will be queried. + * + * Determine whether a given #AtspiAccessibleStateSet includes a given state; that is, + * whether @state is true for the stateset in question. + * + * Returns: #TRUE if @state is true/included in the given #AtspiAccessibleStateSet, + * otherwise #FALSE. + * + **/ +gboolean +AccessibleStateSet_contains (AccessibleStateSet *obj, + AccessibleState state) +{ + return spi_state_set_cache_contains (obj, spi_state_to_dbus (state)); +} + +/** + * AccessibleStateSet_add: + * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate. + * @state: an #AtspiAccessibleState to be added to the specified #AtspiAccessibleStateSet + * + * Add a particular #AtspiAccessibleState to an #AtspiAccessibleStateSet (i.e. set the + * given state to #TRUE in the stateset. + * + **/ +void +AccessibleStateSet_add (AccessibleStateSet *obj, + AccessibleState state) +{ + spi_state_set_cache_add (obj, spi_state_to_dbus (state)); +} + +/** + * AccessibleStateSet_remove: + * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate. + * @state: an #AtspiAccessibleState to be removed from the specified #AtspiAccessibleStateSet + * + * Remove a particular #AtspiAccessibleState to an #AtspiAccessibleStateSet (i.e. set the + * given state to #FALSE in the stateset.) + * + **/ +void +AccessibleStateSet_remove (AccessibleStateSet *obj, + AccessibleState state) +{ + spi_state_set_cache_remove (obj, spi_state_to_dbus (state)); +} + +/** + * AccessibleStateSet_equals: + * @obj: a pointer to the first #AtspiAccessibleStateSet object on which to operate. + * @obj2: a pointer to the second #AtspiAccessibleStateSet object on which to operate. + * + * Determine whether two instances of #AtspiAccessibleStateSet are equivalent (i.e. + * consist of the same #AtspiAccessibleStates). Useful for checking multiple + * state variables at once; construct the target state then compare against it. + * + * @see AccessibleStateSet_compare(). + * + * Returns: #TRUE if the two #AtspiAccessibleStateSets are equivalent, + * otherwise #FALSE. + * + **/ +gboolean +AccessibleStateSet_equals (AccessibleStateSet *obj, + AccessibleStateSet *obj2) +{ + gboolean eq; + AtkStateSet *cmp; + + if (obj == obj2) + { + return TRUE; + } + + cmp = spi_state_set_cache_xor (obj, obj2); + eq = spi_state_set_cache_is_empty (cmp); + spi_state_set_cache_unref (cmp); + + return eq; +} + +/** + * AccessibleStateSet_compare: + * @obj: a pointer to the first #AtspiAccessibleStateSet object on which to operate. + * @obj2: a pointer to the second #AtspiAccessibleStateSet object on which to operate. + * + * Determine the differences between two instances of #AtspiAccessibleStateSet. + * Not Yet Implemented. + *. + * @see AccessibleStateSet_equals(). + * + * Returns: an #AtspiAccessibleStateSet object containing all states contained on one of + * the two sets but not the other. + * + **/ +AccessibleStateSet * +AccessibleStateSet_compare (AccessibleStateSet *obj, + AccessibleStateSet *obj2) +{ + return spi_state_set_cache_xor (obj, obj2); +} + +/** + * AccessibleStateSet_isEmpty: + * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate. + * + * Determine whether a given #AtspiAccessibleStateSet is the empty set. + * + * Returns: #TRUE if the given #AtspiAccessibleStateSet contains no (true) states, + * otherwise #FALSE. + * + **/ +gboolean +AccessibleStateSet_isEmpty (AccessibleStateSet *obj) +{ + return spi_state_set_cache_is_empty (obj); +} + +gboolean +_atspi_accessible_is_a (AtspiAccessible *accessible, + const char *interface_name) +{ + int n; + + if (accessible == NULL) + { + return FALSE; + } + + n = get_iface_num (interface_name); + if (n == -1) return FALSE; + return (gbooleanean)((accessible->interfaces & (1 << n))? TRUE: FALSE); +} +#endif + +/* TODO: Move to a finalizer */ +static void +cspi_object_destroyed (AtspiAccessible *accessible) +{ + gboolean cached; + AtspiEvent e; + + /* TODO: Only fire if object not already marked defunct */ + memset (&e, 0, sizeof(e)); + e.type = "object:state-change:defunct"; + e.source = accessible; + e.detail1 = 1; + atspi_dispatch_event (&e); + + g_free (accessible->path); + + if (accessible->states) + g_object_unref (accessible->states); + g_free (accessible->description); + g_free (accessible->name); +} + +AtspiAccessible * +atspi_accessible_new () +{ + AtspiAccessible *accessible; + + accessible = g_object_new (ATSPI_TYPE_ACCESSIBLE, NULL); + g_return_val_if_fail (accessible != NULL, NULL); + + return accessible; +} diff --git a/atspi/atspi-accessible.h b/atspi/atspi-accessible.h new file mode 100644 index 0000000..56e2888 --- /dev/null +++ b/atspi/atspi-accessible.h @@ -0,0 +1,101 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSPI_ACCESSIBLE_H_ +#define _ATSPI_ACCESSIBLE_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" +#include "atspi-stateset.h" + +#define ATSPI_TYPE_ACCESSIBLE (atspi_accessible_get_type ()) +#define ATSPI_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_ACCESSIBLE, AtspiAccessible)) +#define ATSPI_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_ACCESSIBLE, AtspiAccessibleClass)) +#define ATSPI_IS_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_ACCESSIBLE)) +#define ATSPI_IS_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_ACCESSIBLE)) +#define ATSPI_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_ACCESSIBLE, AtspiAccessibleClass)) + +typedef struct _AtspiApplication AtspiApplication; +struct _AtspiApplication +{ + GHashTable *hash; + char *bus_name; + struct _AtspiAccessible *root; +}; + +typedef struct _AtspiAccessible AtspiAccessible; +struct _AtspiAccessible +{ + GObject parent; + gint ref_count; + AtspiAccessible *accessible_parent; + GList *children; + AtspiApplication *app; + char *path; + gint role : 8; + gint interfaces : 24; + char *name; + char *description; + AtspiStateSet *states; +}; + +typedef struct _AtspiAccessibleClass AtspiAccessibleClass; +struct _AtspiAccessibleClass +{ + GObjectClass parent_class; +}; + +AtspiAccessible * +atspi_accessible_new (); + +gchar * atspi_role_get_name (AtspiRole role); + +gchar * atspi_accessible_get_name (AtspiAccessible *obj, GError **error); + +gchar * atspi_accessible_get_description (AtspiAccessible *obj, GError **error); + +AtspiAccessible * atspi_accessible_get_parent (AtspiAccessible *obj, GError **error); + +gint atspi_accessible_get_child_count (AtspiAccessible *obj, GError *error); + +AtspiAccessible * atspi_accessible_get_child_at_index (AtspiAccessible *obj, gint child_index, GError **error); + +gint atspi_accessible_get_index_in_parent (AtspiAccessible *obj, GError **error); + +GArray * atspi_accessible_get_relation_set (AtspiAccessible *obj, GError **error); + +AtspiRole atspi_accessible_get_role (AtspiAccessible *obj, GError **error); + +gchar * atspi_accessible_get_role_name (AtspiAccessible *obj, GError **error); + +gchar * atspi_accessible_get_localized_role_name (AtspiAccessible *obj, GError **error); + +AtspiStateSet * atspi_accessible_get_state_set (AtspiAccessible *obj); + +GHashTable * atspi_accessible_get_attributes (AtspiAccessible *obj, GError **error); + +AtspiApplication * atspi_accessible_get_host_application (AtspiAccessible *obj, GError **error); + +#endif /* _ATSPI_ACCESSIBLE_H_ */ diff --git a/atspi/atspi-constants.h b/atspi/atspi-constants.h new file mode 100644 index 0000000..a011645 --- /dev/null +++ b/atspi/atspi-constants.h @@ -0,0 +1,766 @@ +/* TODO: Auto-generate this file again + + + + !\mainpage AT-SPI Interfaces and Subinterfaces + + This is the main documentation page for the + Assistive Technology Service Provider Interface (AT-SPI). + + \section apps Applications and Interface Components + Namespace Accessibility includes service APIs implemented by + participating applications and their user interface components:\n\n + Accessibility::Accessible\n + Accessibility::Application\n + Accessibility::Desktop\n + Accessibility::Collecgtion\n + Accessibility::Component\n + Accessibility::Hypertext\n + Accessibility::Image\n + Accessibility::Selection\n + Accessibility::Table\n + Accessibility::Text\n + Accessibility::EditableText\n + Accessibility::Value + + \section types Enumerated Types + Accessibility defines a number of key enumerated types, including:\n\n + Accessibility::RelationType\n + Accessibility::Role\n + Accessibility::StateType\n + Accessibility::Event\n + Accessibility::EventDetails \n + + \section Registry + Accessibility also includes Accessibility::Registry, + which is the service used by assistive technologies and related + AT-SPI clients to register interest in certain classes of events, + enumerate the currently available desktop and application list, + and to synthesize certain kinds of device events. + + \section listeners Event Listener Interfaces + Accessibility::EventListener\n + Accessibility::DeviceEventListener + + \section helpers Helper Interfaces + + The following interfaces may be implemented by assistive technologies + themselves, in order to export their services in a consistent manner or + in order to interoperate with other applications or desktop services.\n + + Accessibility::LoginHelper : Implemented by adaptive technologies which + need to participate in user-authentication or login activities, and which + therefore may need negotiation with authentication agents or processes.\n + + Accessibility::Selector [NEW]: Implemented by user agents or assistive + technologies which export lists of choices from which the end-user is + expected to make selections. Useful for various types of remote + activation or intercommunication between multiple ATs. + + */ + +#ifndef _ATSPI_CONSTANTS_H_ +#define _ATSPI_CONSTANTS_H_ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * +ATSPI_LOCALE_TYPE: + * @ATSPI_LOCALE_TYPE_MESSAGES: + * @ATSPI_LOCALE_TYPE_COLLATE: + * @ATSPI_LOCALE_TYPE_CTYPE: + * @ATSPI_LOCALE_TYPE_MONETARY: + * @ATSPI_LOCALE_TYPE_NUMERIC: + * @ATSPI_LOCALE_TYPE_TIME: + * + * + * + * Bitfield/set of flags generated from the AT-SPI specification. + */ +typedef enum { + ATSPI_LOCALE_TYPE_MESSAGES, + ATSPI_LOCALE_TYPE_COLLATE, + ATSPI_LOCALE_TYPE_CTYPE, + ATSPI_LOCALE_TYPE_MONETARY, + ATSPI_LOCALE_TYPE_NUMERIC, + ATSPI_LOCALE_TYPE_TIME, +} AtspiLocaleType; + +/** + * NUM_ATSPI_LOCALE_TYPES: + * + * 1 higher than the highest valid value of #AtspiLocaleType. + */ +#define NUM_ATSPI_LOCALE_TYPES (5+1) + +/** + * +ATSPI_COORD_TYPE: + * @ATSPI_COORD_TYPE_SCREEN: + * @ATSPI_COORD_TYPE_WINDOW: + * + * + * + * Bitfield/set of flags generated from the AT-SPI specification. + */ +typedef enum { + ATSPI_COORD_TYPE_SCREEN, + ATSPI_COORD_TYPE_WINDOW, +} AtspiCoordType; + +/** + * NUM_ATSPI_COORD_TYPES: + * + * 1 higher than the highest valid value of #AtspiCoordType. + */ +#define NUM_ATSPI_COORD_TYPES (1+1) + +/** + * +ATSPI_Collection_SortOrder: + * @ATSPI_Collection_SORT_ORDER_INVALID: + * @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: + * + * Bitfield/set of flags generated from the AT-SPI specification. + */ +typedef enum { + ATSPI_Collection_SORT_ORDER_INVALID, + ATSPI_Collection_SORT_ORDER_CANONICAL, + ATSPI_Collection_SORT_ORDER_FLOW, + ATSPI_Collection_SORT_ORDER_TAB, + ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL, + ATSPI_Collection_SORT_ORDER_REVERSE_FLOW, + ATSPI_Collection_SORT_ORDER_REVERSE_TAB, + ATSPI_Collection_SORT_ORDER_LAST_DEFINED, +} AtspiCollectionSortOrder; + +/** + * NUM_ATSPI_SORTORDERS: + * + * 1 higher than the highest valid value of #AtspiCollectionSortOrder. + */ +#define NUM_ATSPI_SORTORDERS (7+1) + +/** + * +ATSPI_Collection_MatchType: + * @ATSPI_Collection_MATCH_INVALID: + * @ATSPI_Collection_MATCH_ALL: + * @ATSPI_Collection_MATCH_ANY: + * @ATSPI_Collection_MATCH_NONE: + * @ATSPI_Collection_MATCH_EMPTY: + * @ATSPI_Collection_MATCH_LAST_DEFINED: + * + * Bitfield/set of flags generated from the AT-SPI specification. + */ +typedef enum { + ATSPI_Collection_MATCH_INVALID, + ATSPI_Collection_MATCH_ALL, + ATSPI_Collection_MATCH_ANY, + ATSPI_Collection_MATCH_NONE, + ATSPI_Collection_MATCH_EMPTY, + ATSPI_Collection_MATCH_LAST_DEFINED, +} AtspiCollectionMatchType; + +/** + * NUM_ATSPI_MATCHTYPES: + * + * 1 higher than the highest valid value of #AtspiCollection_MatchType. + */ +#define NUM_ATSPI_MATCHTYPES (5+1) + +/** + * +ATSPI_Collection_TreeTraversalType: + * @ATSPI_Collection_TREE_RESTRICT_CHILDREN: + * @ATSPI_Collection_TREE_RESTRICT_SIBLING: + * @ATSPI_Collection_TREE_INORDER: + * @ATSPI_Collection_TREE_LAST_DEFINED: + * + * Bitfield/set of flags generated from the AT-SPI specification. + */ +typedef enum { + ATSPI_Collection_TREE_RESTRICT_CHILDREN, + ATSPI_Collection_TREE_RESTRICT_SIBLING, + ATSPI_Collection_TREE_INORDER, + ATSPI_Collection_TREE_LAST_DEFINED, +} AtspiCollectionTreeTraversalType; + +/** + * NUM_ATSPI_TREETRAVERSALTYPES: + * + * 1 higher than the highest valid value of #AtspiCollection_TreeTraversalType. + */ +#define NUM_ATSPI_TREETRAVERSALTYPES (3+1) + +/** + * +ATSPI_ComponentLayer: + * @ATSPI_LAYER_INVALID: + * @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: + * + * + * + * Bitfield/set of flags generated from the AT-SPI specification. + */ +typedef enum { + ATSPI_LAYER_INVALID, + ATSPI_LAYER_BACKGROUND, + ATSPI_LAYER_CANVAS, + ATSPI_LAYER_WIDGET, + ATSPI_LAYER_MDI, + ATSPI_LAYER_POPUP, + ATSPI_LAYER_OVERLAY, + ATSPI_LAYER_WINDOW, + ATSPI_LAYER_LAST_DEFINED, +} AtspiComponentLayer; + +/** + * NUM_ATSPI_COMPONENTLAYERS: + * + * 1 higher than the highest valid value of #AtspiComponentLayer. + */ +#define NUM_ATSPI_COMPONENTLAYERS (8+1) + +/** + * +ATSPI_TEXT_BOUNDARY_TYPE: + * @ATSPI_TEXT_BOUNDARY_CHAR: + * @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: + * + * + * + * Bitfield/set of flags generated from the AT-SPI specification. + */ +typedef enum { + ATSPI_TEXT_BOUNDARY_CHAR, + ATSPI_TEXT_BOUNDARY_WORD_START, + ATSPI_TEXT_BOUNDARY_WORD_END, + ATSPI_TEXT_BOUNDARY_SENTENCE_START, + ATSPI_TEXT_BOUNDARY_SENTENCE_END, + ATSPI_TEXT_BOUNDARY_LINE_START, + ATSPI_TEXT_BOUNDARY_LINE_END, +} AtspiTextBoundaryType; + +/** + * NUM_ATSPI_TEXT_BOUNDARY_TYPES: + * + * 1 higher than the highest valid value of #AtspiTextBOundaryType. + */ +#define NUM_ATSPI_TEXT_BOUNDARY_TYPES (6+1) + +/** + * +ATSPI_TEXT_CLIP_TYPE: + * @ATSPI_TEXT_CLIP_NONE: + * @ATSPI_TEXT_CLIP_MIN: + * @ATSPI_TEXT_CLIP_MAX: + * @ATSPI_TEXT_CLIP_BOTH: + * + * + * + * Bitfield/set of flags generated from the AT-SPI specification. + */ +typedef enum { + ATSPI_TEXT_CLIP_NONE, + ATSPI_TEXT_CLIP_MIN, + ATSPI_TEXT_CLIP_MAX, + ATSPI_TEXT_CLIP_BOTH, +} AtspiTextClipType; + +/** + * NUM_ATSPI_TEXT_CLIP_TYPES: + * + * 1 higher than the highest valid value of #AtspiTextClipType. + */ +#define NUM_ATSPI_TEXT_CLIP_TYPES (3+1) + +/** + * +ATSPI_StateType: + * @ATSPI_STATE_INVALID: + * @ATSPI_STATE_ACTIVE: + * @ATSPI_STATE_ARMED: + * @ATSPI_STATE_BUSY: + * @ATSPI_STATE_CHECKED: + * @ATSPI_STATE_COLLAPSED: + * @ATSPI_STATE_DEFUNCT: + * @ATSPI_STATE_EDITABLE: + * @ATSPI_STATE_ENABLED: + * @ATSPI_STATE_EXPANDABLE: + * @ATSPI_STATE_EXPANDED: + * @ATSPI_STATE_FOCUSABLE: + * @ATSPI_STATE_FOCUSED: + * @ATSPI_STATE_HAS_TOOLTIP: + * @ATSPI_STATE_HORIZONTAL: + * @ATSPI_STATE_ICONIFIED: + * @ATSPI_STATE_MODAL: + * @ATSPI_STATE_MULTI_LINE: + * @ATSPI_STATE_MULTISELECTABLE: + * @ATSPI_STATE_OPAQUE: + * @ATSPI_STATE_PRESSED: + * @ATSPI_STATE_RESIZABLE: + * @ATSPI_STATE_SELECTABLE: + * @ATSPI_STATE_SELECTED: + * @ATSPI_STATE_SENSITIVE: + * @ATSPI_STATE_SHOWING: + * @ATSPI_STATE_SINGLE_LINE: + * @ATSPI_STATE_STALE: + * @ATSPI_STATE_TRANSIENT: + * @ATSPI_STATE_VERTICAL: + * @ATSPI_STATE_VISIBLE: + * @ATSPI_STATE_MANAGES_DESCENDANTS: + * @ATSPI_STATE_INDETERMINATE: + * @ATSPI_STATE_REQUIRED: + * @ATSPI_STATE_TRUNCATED: + * @ATSPI_STATE_ANIMATED: + * @ATSPI_STATE_INVALID_ENTRY: + * @ATSPI_STATE_SUPPORTS_AUTOCOMPLETION: + * @ATSPI_STATE_SELECTABLE_TEXT: + * @ATSPI_STATE_IS_DEFAULT: + * @ATSPI_STATE_VISITED: + * @ATSPI_STATE_LAST_DEFINED: + * + * Bitfield/set of flags generated from the AT-SPI specification. + */ +typedef enum { + ATSPI_STATE_INVALID, + ATSPI_STATE_ACTIVE, + ATSPI_STATE_ARMED, + ATSPI_STATE_BUSY, + ATSPI_STATE_CHECKED, + ATSPI_STATE_COLLAPSED, + ATSPI_STATE_DEFUNCT, + ATSPI_STATE_EDITABLE, + ATSPI_STATE_ENABLED, + ATSPI_STATE_EXPANDABLE, + ATSPI_STATE_EXPANDED, + ATSPI_STATE_FOCUSABLE, + ATSPI_STATE_FOCUSED, + ATSPI_STATE_HAS_TOOLTIP, + ATSPI_STATE_HORIZONTAL, + ATSPI_STATE_ICONIFIED, + ATSPI_STATE_MODAL, + ATSPI_STATE_MULTI_LINE, + ATSPI_STATE_MULTISELECTABLE, + ATSPI_STATE_OPAQUE, + ATSPI_STATE_PRESSED, + ATSPI_STATE_RESIZABLE, + ATSPI_STATE_SELECTABLE, + ATSPI_STATE_SELECTED, + ATSPI_STATE_SENSITIVE, + ATSPI_STATE_SHOWING, + ATSPI_STATE_SINGLE_LINE, + ATSPI_STATE_STALE, + ATSPI_STATE_TRANSIENT, + ATSPI_STATE_VERTICAL, + ATSPI_STATE_VISIBLE, + ATSPI_STATE_MANAGES_DESCENDANTS, + ATSPI_STATE_INDETERMINATE, + ATSPI_STATE_REQUIRED, + ATSPI_STATE_TRUNCATED, + ATSPI_STATE_ANIMATED, + ATSPI_STATE_INVALID_ENTRY, + ATSPI_STATE_SUPPORTS_AUTOCOMPLETION, + ATSPI_STATE_SELECTABLE_TEXT, + ATSPI_STATE_IS_DEFAULT, + ATSPI_STATE_VISITED, + ATSPI_STATE_LAST_DEFINED, +} AtspiStateType; + +/** + * NUM_ATSPI_STATETYPES: + * + * 1 higher than the highest valid value of #AtspiStateType. + */ +#define NUM_ATSPI_STATETYPES (41+1) + +/** + * +ATSPI_KeyEventType: + * @ATSPI_KEY_PRESSED: + * @ATSPI_KEY_RELEASED: + * + * + * + * Bitfield/set of flags generated from the AT-SPI specification. + */ +typedef enum { + ATSPI_KEY_PRESSED, + ATSPI_KEY_RELEASED, +} AtspiKeyEventType; + +/** + * NUM_ATSPI_KEYEVENTTYPES: + * + * 1 higher than the highest valid value of #AtspiKeyEventType. + */ +#define NUM_ATSPI_KEYEVENTTYPES (1+1) + +/** + * +ATSPI_EventType: + * @ATSPI_KEY_PRESSED_EVENT: + * @ATSPI_KEY_RELEASED_EVENT: + * @ATSPI_BUTTON_PRESSED_EVENT: + * @ATSPI_BUTTON_RELEASED_EVENT: + * + * + * + * Bitfield/set of flags generated from the AT-SPI specification. + */ +typedef enum { + ATSPI_KEY_PRESSED_EVENT, + ATSPI_KEY_RELEASED_EVENT, + ATSPI_BUTTON_PRESSED_EVENT, + ATSPI_BUTTON_RELEASED_EVENT, +} AtspiEventType; + +/** + * NUM_ATSPI_EVENTTYPES: + * + * 1 higher than the highest valid value of #AtspiEventType. + */ +#define NUM_ATSPI_EVENTTYPES (3+1) + +/** + * +AtspiKeySynthType: + * @ATSPI_KEY_PRESS: + * @ATSPI_KEY_RELEASE: + * @ATSPI_KEY_PRESSRELEASE: + * @ATSPI_KEY_SYM: + * @ATSPI_KEY_STRING: + * + * + * + * Bitfield/set of flags generated from the AT-SPI specification. + */ +typedef enum { + ATSPI_KEY_PRESS, + ATSPI_KEY_RELEASE, + ATSPI_KEY_PRESSRELEASE, + ATSPI_KEY_SYM, + ATSPI_KEY_STRING, +} AtspiKeySynthType; + +/** + * NUM_ATSPI_KEYSYNTHTYPES: + * + * 1 higher than the highest valid value of #AtspiKeySynthType. + */ +#define NUM_ATSPI_KEYSYNTHTYPES (4+1) + +/** + * +ATSPI_ModifierType: + * @ATSPI_MODIFIER_SHIFT: + * @ATSPI_MODIFIER_SHIFTLOCK: + * @ATSPI_MODIFIER_CONTROL: + * @ATSPI_MODIFIER_ALT: + * @ATSPI_MODIFIER_META: + * @ATSPI_MODIFIER_META2: + * @ATSPI_MODIFIER_META3: + * @ATSPI_MODIFIER_NUMLOCK: + * + * Bitfield/set of flags generated from the AT-SPI specification. + */ +typedef enum { + ATSPI_MODIFIER_SHIFT, + ATSPI_MODIFIER_SHIFTLOCK, + ATSPI_MODIFIER_CONTROL, + ATSPI_MODIFIER_ALT, + ATSPI_MODIFIER_META, + ATSPI_MODIFIER_META2, + ATSPI_MODIFIER_META3, + ATSPI_MODIFIER_NUMLOCK, +} AtspimodifierType; + +/** + * NUM_ATSPI_MODIFIERTYPES: + * + * 1 higher than the highest valid value of #AtspiModifierType. + */ +#define NUM_ATSPI_MODIFIERTYPES (7+1) + +/** + * +ATSPI_RelationType: + * @ATSPI_RELATION_NULL: + * @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: + * + * + * + * Bitfield/set of flags generated from the AT-SPI specification. + */ +typedef enum { + ATSPI_RELATION_NULL, + ATSPI_RELATION_LABEL_FOR, + ATSPI_RELATION_LABELLED_BY, + ATSPI_RELATION_CONTROLLER_FOR, + ATSPI_RELATION_CONTROLLED_BY, + ATSPI_RELATION_MEMBER_OF, + ATSPI_RELATION_TOOLTIP_FOR, + ATSPI_RELATION_NODE_CHILD_OF, + ATSPI_RELATION_NODE_PARENT_OF, + ATSPI_RELATION_EXTENDED, + ATSPI_RELATION_FLOWS_TO, + ATSPI_RELATION_FLOWS_FROM, + ATSPI_RELATION_SUBWINDOW_OF, + ATSPI_RELATION_EMBEDS, + ATSPI_RELATION_EMBEDDED_BY, + ATSPI_RELATION_POPUP_FOR, + ATSPI_RELATION_PARENT_WINDOW_OF, + ATSPI_RELATION_DESCRIPTION_FOR, + ATSPI_RELATION_DESCRIBED_BY, + ATSPI_RELATION_LAST_DEFINED, +} AtspiRelationType; + +/** + * NUM_ATSPI_RELATIONTYPES: + * + * 1 higher than the highest valid value of #AtspiRelationType. + */ +#define NUM_ATSPI_RELATIONTYPES (19+1) + +/** + * +ATSPI_Role: + * @ATSPI_ROLE_INVALID: + * @ATSPI_ROLE_ACCELERATOR_LABEL: + * @ATSPI_ROLE_ALERT: + * @ATSPI_ROLE_ANIMATION: + * @ATSPI_ROLE_ARROW: + * @ATSPI_ROLE_CALENDAR: + * @ATSPI_ROLE_CANVAS: + * @ATSPI_ROLE_CHECK_BOX: + * @ATSPI_ROLE_CHECK_MENU_ITEM: + * @ATSPI_ROLE_COLOR_CHOOSER: + * @ATSPI_ROLE_COLUMN_HEADER: + * @ATSPI_ROLE_COMBO_BOX: + * @ATSPI_ROLE_DATE_EDITOR: + * @ATSPI_ROLE_DESKTOP_ICON: + * @ATSPI_ROLE_DESKTOP_FRAME: + * @ATSPI_ROLE_DIAL: + * @ATSPI_ROLE_DIALOG: + * @ATSPI_ROLE_DIRECTORY_PANE: + * @ATSPI_ROLE_DRAWING_AREA: + * @ATSPI_ROLE_FILE_CHOOSER: + * @ATSPI_ROLE_FILLER: + * @ATSPI_ROLE_FOCUS_TRAVERSABLE: + * @ATSPI_ROLE_FONT_CHOOSER: + * @ATSPI_ROLE_FRAME: + * @ATSPI_ROLE_GLASS_PANE: + * @ATSPI_ROLE_HTML_CONTAINER: + * @ATSPI_ROLE_ICON: + * @ATSPI_ROLE_IMAGE: + * @ATSPI_ROLE_INTERNAL_FRAME: + * @ATSPI_ROLE_LABEL: + * @ATSPI_ROLE_LAYERED_PANE: + * @ATSPI_ROLE_LIST: + * @ATSPI_ROLE_LIST_ITEM: + * @ATSPI_ROLE_MENU: + * @ATSPI_ROLE_MENU_BAR: + * @ATSPI_ROLE_MENU_ITEM: + * @ATSPI_ROLE_OPTION_PANE: + * @ATSPI_ROLE_PAGE_TAB: + * @ATSPI_ROLE_PAGE_TAB_LIST: + * @ATSPI_ROLE_PANEL: + * @ATSPI_ROLE_PASSWORD_TEXT: + * @ATSPI_ROLE_POPUP_MENU: + * @ATSPI_ROLE_PROGRESS_BAR: + * @ATSPI_ROLE_PUSH_BUTTON: + * @ATSPI_ROLE_RADIO_BUTTON: + * @ATSPI_ROLE_RADIO_MENU_ITEM: + * @ATSPI_ROLE_ROOT_PANE: + * @ATSPI_ROLE_ROW_HEADER: + * @ATSPI_ROLE_SCROLL_BAR: + * @ATSPI_ROLE_SCROLL_PANE: + * @ATSPI_ROLE_SEPARATOR: + * @ATSPI_ROLE_SLIDER: + * @ATSPI_ROLE_SPIN_BUTTON: + * @ATSPI_ROLE_SPLIT_PANE: + * @ATSPI_ROLE_STATUS_BAR: + * @ATSPI_ROLE_TABLE: + * @ATSPI_ROLE_TABLE_CELL: + * @ATSPI_ROLE_TABLE_COLUMN_HEADER: + * @ATSPI_ROLE_TABLE_ROW_HEADER: + * @ATSPI_ROLE_TEAROFF_MENU_ITEM: + * @ATSPI_ROLE_TERMINAL: + * @ATSPI_ROLE_TEXT: + * @ATSPI_ROLE_TOGGLE_BUTTON: + * @ATSPI_ROLE_TOOL_BAR: + * @ATSPI_ROLE_TOOL_TIP: + * @ATSPI_ROLE_TREE: + * @ATSPI_ROLE_TREE_TABLE: + * @ATSPI_ROLE_UNKNOWN: + * @ATSPI_ROLE_VIEWPORT: + * @ATSPI_ROLE_WINDOW: + * @ATSPI_ROLE_EXTENDED: + * @ATSPI_ROLE_HEADER: + * @ATSPI_ROLE_FOOTER: + * @ATSPI_ROLE_PARAGRAPH: + * @ATSPI_ROLE_RULER: + * @ATSPI_ROLE_APPLICATION: + * @ATSPI_ROLE_AUTOCOMPLETE: + * @ATSPI_ROLE_EDITBAR: + * @ATSPI_ROLE_EMBEDDED: + * @ATSPI_ROLE_ENTRY: + * @ATSPI_ROLE_CHART: + * @ATSPI_ROLE_CAPTION: + * @ATSPI_ROLE_DOCUMENT_FRAME: + * @ATSPI_ROLE_HEADING: + * @ATSPI_ROLE_PAGE: + * @ATSPI_ROLE_SECTION: + * @ATSPI_ROLE_REDUNDANT_OBJECT: + * @ATSPI_ROLE_FORM: + * @ATSPI_ROLE_LINK: + * @ATSPI_ROLE_INPUT_METHOD_WINDOW: + * @ATSPI_ROLE_LAST_DEFINED: + * + * Bitfield/set of flags generated from the AT-SPI specification. + */ +typedef enum { + ATSPI_ROLE_INVALID, + ATSPI_ROLE_ACCELERATOR_LABEL, + ATSPI_ROLE_ALERT, + ATSPI_ROLE_ANIMATION, + ATSPI_ROLE_ARROW, + ATSPI_ROLE_CALENDAR, + ATSPI_ROLE_CANVAS, + ATSPI_ROLE_CHECK_BOX, + ATSPI_ROLE_CHECK_MENU_ITEM, + ATSPI_ROLE_COLOR_CHOOSER, + ATSPI_ROLE_COLUMN_HEADER, + ATSPI_ROLE_COMBO_BOX, + ATSPI_ROLE_DATE_EDITOR, + ATSPI_ROLE_DESKTOP_ICON, + ATSPI_ROLE_DESKTOP_FRAME, + ATSPI_ROLE_DIAL, + ATSPI_ROLE_DIALOG, + ATSPI_ROLE_DIRECTORY_PANE, + ATSPI_ROLE_DRAWING_AREA, + ATSPI_ROLE_FILE_CHOOSER, + ATSPI_ROLE_FILLER, + ATSPI_ROLE_FOCUS_TRAVERSABLE, + ATSPI_ROLE_FONT_CHOOSER, + ATSPI_ROLE_FRAME, + ATSPI_ROLE_GLASS_PANE, + ATSPI_ROLE_HTML_CONTAINER, + ATSPI_ROLE_ICON, + ATSPI_ROLE_IMAGE, + ATSPI_ROLE_INTERNAL_FRAME, + ATSPI_ROLE_LABEL, + ATSPI_ROLE_LAYERED_PANE, + ATSPI_ROLE_LIST, + ATSPI_ROLE_LIST_ITEM, + ATSPI_ROLE_MENU, + ATSPI_ROLE_MENU_BAR, + ATSPI_ROLE_MENU_ITEM, + ATSPI_ROLE_OPTION_PANE, + ATSPI_ROLE_PAGE_TAB, + ATSPI_ROLE_PAGE_TAB_LIST, + ATSPI_ROLE_PANEL, + ATSPI_ROLE_PASSWORD_TEXT, + ATSPI_ROLE_POPUP_MENU, + ATSPI_ROLE_PROGRESS_BAR, + ATSPI_ROLE_PUSH_BUTTON, + ATSPI_ROLE_RADIO_BUTTON, + ATSPI_ROLE_RADIO_MENU_ITEM, + ATSPI_ROLE_ROOT_PANE, + ATSPI_ROLE_ROW_HEADER, + ATSPI_ROLE_SCROLL_BAR, + ATSPI_ROLE_SCROLL_PANE, + ATSPI_ROLE_SEPARATOR, + ATSPI_ROLE_SLIDER, + ATSPI_ROLE_SPIN_BUTTON, + ATSPI_ROLE_SPLIT_PANE, + ATSPI_ROLE_STATUS_BAR, + ATSPI_ROLE_TABLE, + ATSPI_ROLE_TABLE_CELL, + ATSPI_ROLE_TABLE_COLUMN_HEADER, + ATSPI_ROLE_TABLE_ROW_HEADER, + ATSPI_ROLE_TEAROFF_MENU_ITEM, + ATSPI_ROLE_TERMINAL, + ATSPI_ROLE_TEXT, + ATSPI_ROLE_TOGGLE_BUTTON, + ATSPI_ROLE_TOOL_BAR, + ATSPI_ROLE_TOOL_TIP, + ATSPI_ROLE_TREE, + ATSPI_ROLE_TREE_TABLE, + ATSPI_ROLE_UNKNOWN, + ATSPI_ROLE_VIEWPORT, + ATSPI_ROLE_WINDOW, + ATSPI_ROLE_EXTENDED, + ATSPI_ROLE_HEADER, + ATSPI_ROLE_FOOTER, + ATSPI_ROLE_PARAGRAPH, + ATSPI_ROLE_RULER, + ATSPI_ROLE_APPLICATION, + ATSPI_ROLE_AUTOCOMPLETE, + ATSPI_ROLE_EDITBAR, + ATSPI_ROLE_EMBEDDED, + ATSPI_ROLE_ENTRY, + ATSPI_ROLE_CHART, + ATSPI_ROLE_CAPTION, + ATSPI_ROLE_DOCUMENT_FRAME, + ATSPI_ROLE_HEADING, + ATSPI_ROLE_PAGE, + ATSPI_ROLE_SECTION, + ATSPI_ROLE_REDUNDANT_OBJECT, + ATSPI_ROLE_FORM, + ATSPI_ROLE_LINK, + ATSPI_ROLE_INPUT_METHOD_WINDOW, + ATSPI_ROLE_LAST_DEFINED, +} AtspiRole; + +/** + * NUM_ATSPI_ROLES: + * + * 1 higher than the highest valid value of #AtspiRole. + */ +#define NUM_ATSPI_ROLES (90+1) + + +#ifdef __cplusplus +} +#endif +#endif /* _ATSPI_CONSTANTS_H_ */ diff --git a/atspi/atspi-event-types.h b/atspi/atspi-event-types.h new file mode 100644 index 0000000..154ba1b --- /dev/null +++ b/atspi/atspi-event-types.h @@ -0,0 +1,128 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSPI_EVENT_TYPES_H_ +#define _ATSPI_EVENT_TYPES_H_ + +#include + +#include "atspi-accessible.h" + +typedef guint AtspiControllerEventMask; + +typedef guint AtspiKeyMaskType; + +typedef guint AtspiKeyEventMask; +typedef guint AtspiDeviceEventMask; + +// TODO: auto-generate the below structs +typedef struct _AtspiDeviceEvent AtspiDeviceEvent; +struct _AtspiDeviceEvent +{ + AtspiEventType type; + guint id; + gushort hw_code; + gushort modifiers; + guint timestamp; + gchar * event_string; + gboolean is_text; +}; + +typedef struct _AtspiEventListenerMode AtspiEventListenerMode; +struct _AtspiEventListenerMode +{ + gboolean synchronous; + gboolean preemptive; + gboolean global; +}; + +typedef struct _AtspiKeyDefinition AtspiKeyDefinition; +struct _AtspiKeyDefinition +{ + gint keycode; + gint keysym; + gchar *keystring; + gint unused; +}; + +typedef struct _AtspiEvent AtspiEvent; +struct _AtspiEvent +{ + const gchar *type; + AtspiAccessible *source; + gint detail1; + gint detail2; + GVariant *any; +}; + +typedef void AtspiKeystrokeListener; + +/** + * AtspiKeySet: + * @keysyms: + * @keycodes: + * @len: + * + * Structure containing identifying information about a set of keycode or + * keysyms. + **/ +typedef struct _AtspiKeySet +{ + guint *keysyms; + gushort *keycodes; + gchar **keystrings; + gshort len; +} AtspiKeySet; + +/** + *AtspiKeyListenerSyncType: + *@SPI_KEYLISTENER_NOSYNC: Events may be delivered asynchronously, + * which means in some cases they may already have been delivered to the + * application before the AT client receives the notification. + *@SPI_KEYLISTENER_SYNCHRONOUS: Events are delivered synchronously, before the + * currently focussed application sees them. + *@ATSPI_KEYLISTENER_CANCONSUME: Events may be consumed by the AT client. Presumes and + * requires #ATSPI_KEYLISTENER_SYNCHRONOUS, incompatible with #ATSPI_KEYLISTENER_NOSYNC. + *@SPI_KEYLISTENER_ALL_WINDOWS: Events are received not from the application toolkit layer, but + * from the device driver or windowing system subsystem; such notifications are 'global' in the + * sense that they are not broken or defeated by applications that participate poorly + * in the accessibility APIs, or not at all; however because of the intrusive nature of + * such snooping, it can have side-effects on certain older platforms. If unconditional + * event notifications, even when inaccessible or "broken" applications have focus, are not + * required, it may be best to avoid this enum value/flag. + * + *Specified the tyupe of a key listener event. + * Certain of the values above can and should be bitwise-'OR'ed + * together, observing the compatibility limitations specified in the description of + * each value. For instance, #ATSPI_KEYLISTENER_ALL_WINDOWS | #ATSPI_KEYLISTENER_CANCONSUME is + * a commonly used combination which gives the AT complete control over the delivery of matching + * events. However, such filters should be used sparingly as they may have a negative impact on + * system performance. + **/ +typedef enum { + ATSPI_KEYLISTENER_NOSYNC = 0, + ATSPI_KEYLISTENER_SYNCHRONOUS = 1, + ATSPI_KEYLISTENER_CANCONSUME = 2, + ATSPI_KEYLISTENER_ALL_WINDOWS = 4 +} AtspiKeyListenerSyncType; +#endif /* _ATSPI_EVENT_TYPES_H_ */ diff --git a/atspi/atspi-listener-private.h b/atspi/atspi-listener-private.h new file mode 100644 index 0000000..7907863 --- /dev/null +++ b/atspi/atspi-listener-private.h @@ -0,0 +1,37 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSPI_LISTENER_PRIVATE_H_ +#define _ATSPI_LISTENER_PRIVATE_H_ + +#include "dbus/dbus.h" +#include "glib.h" +#include "atspi-listener.h" + +DBusHandlerResult +atspi_dbus_handle_deviceEvent (DBusConnection *bus, DBusMessage *message, void *data); + +gchar * +_atspi_device_listener_get_path (AtspiDeviceListener *listener); +#endif /* _ATSPI_LISTENER_PRIVATE_H_ */ diff --git a/atspi/atspi-listener.c b/atspi/atspi-listener.c new file mode 100644 index 0000000..15492e7 --- /dev/null +++ b/atspi/atspi-listener.c @@ -0,0 +1,383 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian Inc. + * Copyright 2002 Sun Microsystems, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "atspi-private.h" + +typedef struct +{ + union + { + AtspiEventListenerCB event; + AtspiDeviceListenerCB device_event; + gpointer method; + } cb; + gpointer user_data; +} EventHandler; + +GObjectClass *event_parent_class; +GObjectClass *device_parent_class; + +static guint32 _e_id = 0; + +/* + * Misc. helpers. + */ + +static EventHandler * +atspi_event_handler_new (gpointer method, gpointer user_data) +{ + EventHandler *eh = g_new0 (EventHandler, 1); + + eh->cb.method = method; + eh->user_data = user_data; + + return eh; +} + +static GList * +event_list_remove_by_cb (GList *list, gpointer callback) +{ + GList *l, *next; + + for (l = list; l; l = next) + { + EventHandler *eh = l->data; + next = l->next; + + if (eh->cb.method == callback) + { + list = g_list_delete_link (list, l); + g_free (eh); + } + } + + return list; +} + +/* + * Standard event dispatcher + */ + +G_DEFINE_TYPE (AtspiEventListener, atspi_event_listener, + G_TYPE_OBJECT) + +static void +atspi_event_dispatch (AtspiEventListener *listener, + const AtspiEvent *event) +{ + GList *l; + + /* FIXME: re-entrancy hazard on this list */ + for (l = listener->callbacks; l; l = l->next) + { + EventHandler *eh = l->data; + /* cast hides our private stuff from client handlers */ + eh->cb.event (event, eh->user_data); + } +} + +static guint listener_id = 0; +static GList *device_listeners = NULL; + +static gboolean +id_is_free (guint id) +{ + GList *l; + + for (l = device_listeners; l; l = g_list_next (l)) + { + AtspiDeviceListener *listener = l->data; + if (listener->id == id) return FALSE; + } + return TRUE; +} + +static void +remove_listener (GObject *obj, gpointer data) +{ + device_listeners = g_list_remove (device_listeners, obj); +} + +static void +atspi_event_listener_init (AtspiEventListener *listener) +{ +} + +static void +atspi_event_listener_finalize (GObject *object) +{ + AtspiEventListener *listener = (AtspiEventListener *) object; + GList *l; + + for (l = listener->callbacks; l; l = l->next) + { + g_free (l->data); + } + + g_list_free (listener->callbacks); + + event_parent_class->finalize (object); +} + +static void +atspi_event_listener_class_init (AtspiEventListenerClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + + event_parent_class = g_type_class_peek_parent (klass); + object_class->finalize = atspi_event_listener_finalize; + + klass->event = atspi_event_dispatch; +} + +AtspiEventListener * +atspi_event_listener_new (void) +{ + AtspiEventListener *listener; + + listener = g_object_new (atspi_event_listener_get_type (), NULL); + + return listener; +} + +void +atspi_event_listener_add_cb (AtspiEventListener *listener, + AtspiEventListenerCB callback, + void *user_data) +{ + g_return_if_fail (ATSPI_IS_EVENT_LISTENER (listener)); + + listener->callbacks = g_list_prepend (listener->callbacks, + atspi_event_handler_new ((void *) callback, user_data)); +} + +void +atspi_event_listener_remove_cb (AtspiEventListener *listener, + AtspiEventListenerCB callback) +{ + g_return_if_fail (ATSPI_IS_EVENT_LISTENER (listener)); + + listener->callbacks = event_list_remove_by_cb (listener->callbacks, (void *) callback); +} + +/* + * Device event handler + */ +static gboolean +atspi_device_event_dispatch (AtspiDeviceListener *listener, + const AtspiDeviceEvent *event) +{ + GList *l; + AtspiDeviceEvent anevent; + gboolean handled = FALSE; + + /* FIXME: re-enterancy hazard on this list */ + for (l = listener->callbacks; l; l = l->next) + { + EventHandler *eh = l->data; + + if ((handled = eh->cb.device_event (&anevent, eh->user_data))) + { + break; + } + } + + return handled; +} + +static void +atspi_device_listener_init (AtspiDeviceListener *listener) +{ + GList *new_list; + + do + { + listener->id = listener_id++; + } while (!id_is_free (listener->id)); + new_list = g_list_append (device_listeners, listener); + if (new_list) device_listeners = new_list; +} + +static void +atspi_device_listener_finalize (GObject *object) +{ + AtspiDeviceListener *listener = (AtspiDeviceListener *) object; + GList *l; + + for (l = listener->callbacks; l; l = l->next) + { + g_free (l->data); + } + + g_list_free (listener->callbacks); + + device_parent_class->finalize (object); +} + +static void +atspi_device_listener_class_init (AtspiDeviceListenerClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + + device_parent_class = g_type_class_peek_parent (klass); + object_class->finalize = atspi_device_listener_finalize; + + klass->device_event = atspi_device_event_dispatch; +} + +G_DEFINE_TYPE (AtspiDeviceListener, atspi_device_listener, + G_TYPE_OBJECT) + +AtspiDeviceListener * +atspi_device_listener_new (void) +{ + AtspiDeviceListener *listener = g_object_new (atspi_device_listener_get_type (), NULL); + + return listener; +} + +void +atspi_device_listener_add_cb (AtspiDeviceListener *listener, + AtspiDeviceListenerCB callback, + void *user_data) +{ + g_return_if_fail (ATSPI_IS_DEVICE_LISTENER (listener)); + + listener->callbacks = g_list_prepend (listener->callbacks, + atspi_event_handler_new ((void *)callback, user_data)); +} + +void +atspi_device_listener_remove_cb (AtspiDeviceListener *listener, + AtspiDeviceListenerCB callback) +{ + g_return_if_fail (ATSPI_IS_DEVICE_LISTENER (listener)); + + listener->callbacks = event_list_remove_by_cb (listener->callbacks, (void *) callback); +} + +static const char *device_event_type = "(uinnisb)"; + +static void +read_device_event_from_iter (DBusMessageIter *iter, AtspiDeviceEvent *event) +{ + dbus_uint32_t type; + dbus_int32_t id; + dbus_int16_t hw_code; + dbus_int16_t modifiers; + dbus_int32_t timestamp; + char *event_string; + dbus_bool_t is_text; + DBusMessageIter iter_struct; + + dbus_message_iter_recurse (iter, &iter_struct); + + dbus_message_iter_get_basic (&iter_struct, &type); + event->type = type; + dbus_message_iter_next (&iter_struct); + + dbus_message_iter_get_basic (&iter_struct, &id); + event->id = id; + dbus_message_iter_next (&iter_struct); + + dbus_message_iter_get_basic (&iter_struct, &hw_code); + event->hw_code = hw_code; + dbus_message_iter_next (&iter_struct); + + dbus_message_iter_get_basic (&iter_struct, &modifiers); + event->modifiers = modifiers; + dbus_message_iter_next (&iter_struct); + + dbus_message_iter_get_basic (&iter_struct, ×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; +} + +/* + * atspi_dbus_handle_DeviceEvent: (skip) + */ +DBusHandlerResult +atspi_dbus_handle_DeviceEvent (DBusConnection *bus, DBusMessage *message, void *data) +{ + const char *path = dbus_message_get_path (message); + int id; + AtspiDeviceEvent event; + AtspiDeviceListener *listener; + DBusMessageIter iter; + AtspiDeviceListenerClass *klass; + dbus_bool_t retval = FALSE; + GList *l; + DBusMessage *reply; + void *p = &event; + + if (strcmp (dbus_message_get_signature (message), "(uinnisb)") != 0) + { + g_warning ("Atspi: Unknown signature for an event"); + goto done; + } + + if (sscanf (path, "/org/a11y/atspi/listeners/%d", &id) != 1) + { + g_warning ("Atspi: Bad listener path: %s\n", path); + goto done; + } + + for (l = device_listeners; l; l = g_list_next (l)) + { + listener = l->data; + if (listener->id == id) break; + } + + if (!l) + { + goto done; + } + dbus_message_iter_init (message, &iter); + read_device_event_from_iter (&iter, &event); + klass = ATSPI_DEVICE_LISTENER_GET_CLASS (listener); + if (klass->device_event) + { + retval = (*klass->device_event) (listener, &event); + } +done: + reply = dbus_message_new_method_return (message); + if (reply) + { + dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &retval, DBUS_TYPE_INVALID); + dbus_connection_send (_atspi_bus(), reply, NULL); + dbus_message_unref (reply); + } + return DBUS_HANDLER_RESULT_HANDLED; +} + +gchar * +_atspi_device_listener_get_path (AtspiDeviceListener *listener) +{ + return g_strdup_printf ("/org/a11y/atspi/listeners/%d", listener->id); +} diff --git a/atspi/atspi-listener.h b/atspi/atspi-listener.h new file mode 100644 index 0000000..14fc6bf --- /dev/null +++ b/atspi/atspi-listener.h @@ -0,0 +1,135 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSPI_LISTENER_H_ +#define _ATSPI_LISTENER_H_ + +#include "atspi-event-types.h" + +/* + * Function prototype typedefs for Event Listener Callbacks. + * + * usage: signatures should be + * void (*AtspiEventListenerCB) (AtspiEvent *event); + * + * gboolean (*AtspiKeystrokeListenerCB) (AtspiKeystrokeEvent *Event); + * Note that AtspiKeystrokeListeners may consume the event received + * if one of their callbacks returns TRUE (see atspi_register_accessible_keystroke_listener) + */ + +/** + * AtspiEventListenerCB: + * @event: The event for which notification is sent. + * @user_data: User data which is passed to the callback each time a notification takes place. + * + * A function prototype for callbacks via which clients are notified of AT-SPI events. + * + **/ +typedef void (*AtspiEventListenerCB) (const AtspiEvent *event, + void *user_data); + +/** + * AtspiDeviceListenerCB: + * @stroke: The #AtspiDeviceEvent for which notification is being received. + * @user_data: Data which is passed to the client each time this callback is notified. + * + * A callback function prototype via which clients receive device event notifications. + * + * Returns: %TRUE if the client wishes to consume/preempt the event, preventing it from being + * relayed to the currently focussed application, %FALSE if the event delivery should proceed as normal. + **/ +typedef gboolean (*AtspiDeviceListenerCB) (const AtspiDeviceEvent *stroke, + void *user_data); + +#define ATSPI_TYPE_DEVICE_LISTENER (atspi_device_listener_get_type ()) +#define ATSPI_DEVICE_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_DEVICE_LISTENER, AtspiDeviceListener)) +#define ATSPI_DEVICE_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_DEVICE_LISTENER, AtspiDeviceListenerClass)) +#define ATSPI_IS_DEVICE_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_DEVICE_LISTENER)) +#define ATSPI_IS_DEVICE_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_DEVICE_LISTENER)) +#define ATSPI_DEVICE_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_DEVICE_LISTENER, AtspiDeviceListenerClass)) + +#define ATSPI_TYPE_EVENT_LISTENER (atspi_event_listener_get_type ()) +#define ATSPI_EVENT_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_EVENT_LISTENER, AtspiEventListener)) +#define ATSPI_EVENT_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_EVENT_LISTENER, AtspiEventListenerClass)) +#define ATSPI_IS_EVENT_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_EVENT_LISTENER)) +#define ATSPI_IS_EVENT_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_EVENT_LISTENER)) +#define ATSPI_EVENT_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_EVENT_LISTENER, AtspiEventListenerClass)) + +typedef struct _AtspiEventListener AtspiEventListener; +struct _AtspiEventListener +{ + GObject parent; + GList *callbacks; +}; + +typedef struct _AtspiEventListenerClass AtspiEventListenerClass; +struct _AtspiEventListenerClass +{ + GObject parent_class; + void (*event) (AtspiEventListener *, const AtspiEvent *); +}; + +typedef struct _AtspiDeviceListener AtspiDeviceListener; +struct _AtspiDeviceListener +{ + GObject parent; + GList *callbacks; + guint id; +}; + +typedef struct _AtspiDeviceListenerClass AtspiDeviceListenerClass; +struct _AtspiDeviceListenerClass +{ + GObject parent_class; + gboolean (*device_event) (AtspiDeviceListener *, const AtspiDeviceEvent *); +}; + +AtspiEventListener *atspi_event_listener_new (void); + +void atspi_event_listener_add_cb (AtspiEventListener *listener, + AtspiEventListenerCB callback, + void *user_data); + +void atspi_event_listener_remove_cb (AtspiEventListener *listener, + AtspiEventListenerCB callback); + +AtspiDeviceListener * +atspi_device_listener_new (void); + +void +atspi_device_listener_add_cb (AtspiDeviceListener *listener, + AtspiDeviceListenerCB callback, + void *user_data); + +void +atspi_device_listener_remove_cb (AtspiDeviceListener *listener, + AtspiDeviceListenerCB callback); + +/* private */ +DBusHandlerResult +atspi_dbus_handle_deviceEvent (DBusConnection *bus, DBusMessage *message, void *data); + +gchar * +_atspi_device_listener_get_path (AtspiDeviceListener *listener); +#endif /* _ATSPI_LISTENER_H_ */ diff --git a/atspi/atspi-misc-private.h b/atspi/atspi-misc-private.h new file mode 100644 index 0000000..15b831e --- /dev/null +++ b/atspi/atspi-misc-private.h @@ -0,0 +1,114 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSPI_MISC_PRIVATE_H_ +#define _ATSPI_MISC_PRIVATE_H_ + +/* Private internal implementation details of at-spi. */ + +#include "atspi.h" + +#include "dbus/dbus.h" + +#include "dbind/dbind.h" + +typedef struct _AtspiReference AtspiReference; +struct _AtspiReference +{ + char *name; + char *path; +}; + +/* constants */ +#define ATSPI_DBUS_NAME_REGISTRY "org.a11y.atspi.Registry" +#define ATSPI_DBUS_PATH_REGISTRY "/org/a11y/atspi/registry" +#define ATSPI_DBUS_INTERFACE_REGISTRY "org.a11y.atspi.Registry" + +#define ATSPI_DBUS_PATH_NULL "/org/a11y/atspi/null" +#define ATSPI_DBUS_PATH_ROOT "/org/a11y/atspi/accessible/root" + +#define ATSPI_DBUS_PATH_DEC "/org/a11y/atspi/registry/deviceeventcontroller" +#define ATSPI_DBUS_INTERFACE_DEC "org.a11y.atspi.DeviceEventController" +#define ATSPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER "org.a11y.atspi.DeviceEventListener" + +#define ATSPI_DBUS_INTERFACE_CACHE "org.a11y.atspi.Cache" +#define ATSPI_DBUS_INTERFACE_ACCESSIBLE "org.a11y.atspi.Accessible" +#define ATSPI_DBUS_INTERFACE_ACTION "org.a11y.atspi.Action" +#define ATSPI_DBUS_INTERFACE_APPLICATION "org.a11y.atspi.Application" +#define ATSPI_DBUS_INTERFACE_COLLECTION "org.a11y.atspi.Collection" +#define ATSPI_DBUS_INTERFACE_COMPONENT "org.a11y.atspi.Component" +#define ATSPI_DBUS_INTERFACE_DOCUMENT "org.a11y.atspi.Document" +#define ATSPI_DBUS_INTERFACE_EDITABLE_TEXT "org.a11y.atspi.EditableText" +#define ATSPI_DBUS_INTERFACE_EVENT_KEYBOARD "org.a11y.atspi.Event.Keyboard" +#define ATSPI_DBUS_INTERFACE_EVENT_MOUSE "org.a11y.atspi.Event.Mouse" +#define ATSPI_DBUS_INTERFACE_HYPERLINK "org.a11y.atspi.Hyperlink" +#define ATSPI_DBUS_INTERFACE_HYPERTEXT "org.a11y.atspi.Hypertext" +#define ATSPI_DBUS_INTERFACE_IMAGE "org.a11y.atspi.Image" +#define ATSPI_DBUS_INTERFACE_SELECTION "org.a11y.atspi.Selection" +#define ATSPI_DBUS_INTERFACE_TABLE "org.a11y.atspi.Table" +#define ATSPI_DBUS_INTERFACE_TEXT "org.a11y.atspi.Text" +#define ATSPI_DBUS_INTERFACE_VALUE "org.a11y.atspi.Value" +#define ATSPI_DBUS_INTERFACE_SOCKET "org.a11y.atspi.Socket" + +/* externs */ +extern const char *atspi_path_dec; +extern const char *atspi_path_registry; +extern const char *atspi_path_root; +extern const char *atspi_bus_registry; +extern const char *atspi_interface_accessible; +extern const char *atspi_interface_action; +extern const char *atspi_interface_application; +extern const char *atspi_interface_component; +extern const char *atspi_interface_dec; +extern const char *atspi_interface_device_event_listener; +extern const char *atspi_interface_document; +extern const char *atspi_interface_editable_text; +extern const char *atspi_interface_hyperlink; +extern const char *atspi_interface_hypertext; +extern const char *atspi_interface_image; +extern const char *atspi_interface_registry; +extern const char *atspi_interface_selection; +extern const char *atspi_interface_table; +extern const char *atspi_interface_text; +extern const char *atspi_interface_cache; +extern const char *atspi_interface_value; + +/* function prototypes */ +DBusConnection * _atspi_bus (); + +AtspiAccessible * _atspi_ref_accessible (const char *app, const char *path); + +AtspiAccessible * _atspi_ref_related_accessible (AtspiAccessible *obj, const AtspiReference *ref); + +dbus_bool_t _atspi_dbus_call (AtspiAccessible *obj, const char *interface, const char *method, GError **error, const char *type, ...); + +DBusMessage *_atspi_dbus_call_partial (AtspiAccessible *obj, const char *interface, const char *method, GError **error, const char *type, ...); + +dbus_bool_t _atspi_dbus_get_property (AtspiAccessible *obj, const char *interface, const char *name, GError **error, const char *type, void *data); + +DBusMessage * _atspi_dbus_send_with_reply_and_block (DBusMessage *message); + +GHashTable * +_atspi_dbus_hash_from_message (DBusMessage *message); +#endif /* _ATSPI_MISC_PRIVATE_H_ */ diff --git a/atspi/atspi-misc.c b/atspi/atspi-misc.c new file mode 100644 index 0000000..874d533 --- /dev/null +++ b/atspi/atspi-misc.c @@ -0,0 +1,828 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * + * Basic SPI initialization and event loop function prototypes + * + */ + +#include "atspi-private.h" + +static DBusConnection *bus = NULL; +static GHashTable *apps = NULL; +static GHashTable *live_refs = NULL; +static GQueue *exception_handlers = NULL; +static DBusError exception; + +const char *atspi_path_dec = ATSPI_DBUS_PATH_DEC; +const char *atspi_path_registry = ATSPI_DBUS_PATH_REGISTRY; +const char *atspi_path_root = ATSPI_DBUS_PATH_ROOT; +const char *atspi_bus_registry = ATSPI_DBUS_NAME_REGISTRY; +const char *atspi_interface_accessible = ATSPI_DBUS_INTERFACE_ACCESSIBLE; +const char *atspi_interface_action = ATSPI_DBUS_INTERFACE_ACTION; +const char *atspi_interface_application = ATSPI_DBUS_INTERFACE_APPLICATION; +const char *atspi_interface_component = ATSPI_DBUS_INTERFACE_COMPONENT; +const char *atspi_interface_dec = ATSPI_DBUS_INTERFACE_DEC; +const char *atspi_interface_device_event_listener = ATSPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER; +const char *atspi_interface_document = ATSPI_DBUS_INTERFACE_DOCUMENT; +const char *atspi_interface_editable_text = ATSPI_DBUS_INTERFACE_EDITABLE_TEXT; +const char *atspi_interface_hyperlink = ATSPI_DBUS_INTERFACE_HYPERLINK; +const char *atspi_interface_hypertext = ATSPI_DBUS_INTERFACE_HYPERTEXT; +const char *atspi_interface_image = ATSPI_DBUS_INTERFACE_IMAGE; +const char *atspi_interface_registry = ATSPI_DBUS_INTERFACE_REGISTRY; +const char *atspi_interface_selection = ATSPI_DBUS_INTERFACE_SELECTION; +const char *atspi_interface_table = ATSPI_DBUS_INTERFACE_TABLE; +const char *atspi_interface_text = ATSPI_DBUS_INTERFACE_TEXT; +const char *atspi_interface_cache = ATSPI_DBUS_INTERFACE_CACHE; +const char *atspi_interface_value = ATSPI_DBUS_INTERFACE_VALUE; + +static const char *interfaces[] = +{ + ATSPI_DBUS_INTERFACE_ACCESSIBLE, + ATSPI_DBUS_INTERFACE_ACTION, + ATSPI_DBUS_INTERFACE_APPLICATION, + ATSPI_DBUS_INTERFACE_COLLECTION, + ATSPI_DBUS_INTERFACE_COMPONENT, + ATSPI_DBUS_INTERFACE_DOCUMENT, + ATSPI_DBUS_INTERFACE_EDITABLE_TEXT, + ATSPI_DBUS_INTERFACE_HYPERLINK, + ATSPI_DBUS_INTERFACE_HYPERTEXT, + ATSPI_DBUS_INTERFACE_IMAGE, + "org.a11y.atspi.LoginHelper", + ATSPI_DBUS_INTERFACE_SELECTION, + ATSPI_DBUS_INTERFACE_TABLE, + ATSPI_DBUS_INTERFACE_TEXT, + ATSPI_DBUS_INTERFACE_VALUE, + NULL +}; + +static gint get_iface_num (const char *iface) +{ + /* TODO: Use a binary search or hash to improve performance */ + int i; + + for (i = 0; interfaces[i]; i++) + { + if (!strcmp(iface, interfaces[i])) return i; + } + return -1; +} + +static GHashTable * +get_live_refs (void) +{ + if (!live_refs) + { + live_refs = g_hash_table_new (g_direct_hash, g_direct_equal); + } + return live_refs; +} + +DBusConnection * +_atspi_bus () +{ + return bus; +} + +#define APP_IS_REGISTRY(app) (!strcmp (app->bus_name, atspi_bus_registry)) + +static void +cleanup () +{ + GHashTable *refs; + + refs = live_refs; + live_refs = NULL; + if (refs) + { + g_hash_table_destroy (refs); + } +} + +static gboolean atspi_inited = FALSE; + +static GHashTable *app_hash = NULL; + +static AtspiApplication * +get_application (const char *bus_name) +{ + AtspiApplication *app = NULL; + char *bus_name_dup; + + if (!app_hash) + { + app_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_hash_table_unref); + if (!app_hash) return NULL; + } + app = g_hash_table_lookup (app_hash, bus_name); + if (app) return app; + bus_name_dup = g_strdup (bus_name); + if (!bus_name_dup) return NULL; + // TODO: change below to something that will send state-change:defunct notification if necessary */ + app = g_new (AtspiApplication, 1); + if (!app) return NULL; + app->bus_name = bus_name_dup; + if (APP_IS_REGISTRY (app)) + { + app->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + } + else + { + app->hash = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_object_unref); + } + g_hash_table_insert (app_hash, bus_name_dup, app); + return app; +} + +static AtspiAccessible * +ref_accessible (const char *app_name, const char *path) +{ + int id; + guint *id_val; + AtspiApplication *app = get_application (app_name); + AtspiAccessible *a; + + if (!strcmp (path, "/org/a11y/atspi/accessible/root")) + return g_object_ref (app->root); + + if (sscanf (path, "/org/a11y/atspi/accessible/%d", &id) != 1) + { + return NULL; + } + + a = g_hash_table_lookup (app->hash, &id); + if (a) + { + g_object_ref (a); + return a; + } + id_val = g_new (guint, 1); + if (!id_val) return NULL; + *id_val = id; + a = atspi_accessible_new (); + if (!a) + { + g_free (id_val); + return NULL; + } + a->app = app; + a->path = g_strdup_printf ("/org/a11y/atspi/accessible/%d", id); + g_hash_table_insert (app->hash, id_val, a); + g_object_ref (a); /* for the hash */ + return a; +} + +typedef struct +{ + char *path; + char *parent; + GArray *children; + GArray *interfaces; + char *name; + dbus_uint32_t role; + char *description; + GArray *state_bitflags; +} CACHE_ADDITION; + +static DBusHandlerResult +handle_remove_accessible (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + const char *sender = dbus_message_get_sender (message); + AtspiApplication *app; + const char *path; + DBusMessageIter iter, iter_struct; + const char *signature = dbus_message_get_signature (message); + AtspiAccessible *a; + int id; + + if (strcmp (signature, "(so)") != 0) + { + g_warning ("at-spi: Unknown signature %s for RemoveAccessible", signature); + return DBUS_HANDLER_RESULT_HANDLED; + } + + dbus_message_iter_init (message, &iter); + dbus_message_iter_recurse (&iter, &iter_struct); + dbus_message_iter_get_basic (&iter_struct, &sender); + dbus_message_iter_get_basic (&iter_struct, &path); + app = get_application (sender); + a = ref_accessible (sender, path); + if (a->accessible_parent && g_list_find (a->accessible_parent->children, a)) + { + a->accessible_parent->children = g_list_remove (a->accessible_parent->children, a); + g_object_unref (a); + } + if (sscanf (a->path, "/org/a11y/atspi/accessible/%d", &id) == 1) + { + g_warning("atspi: FIX HASH REMOVE"); + g_hash_table_remove (app->hash, id); + } + else + g_warning ("libspi: Strange path %s\n", a->path); + g_object_unref (a); /* unref our own ref */ + return DBUS_HANDLER_RESULT_HANDLED; +} + +static gboolean +add_app_to_desktop (AtspiAccessible *a, const char *bus_name) +{ + DBusError error; + char *root_path; + + dbus_error_init (&error); + AtspiAccessible *obj = ref_accessible (bus_name, atspi_path_root); + if (obj) + { + GList *new_list = g_list_append (a->children, obj); + if (new_list) + { + a->children = new_list; + return TRUE; + } + } + else + { + g_warning ("Error calling getRoot for %s: %s", bus_name, error.message); + } + return FALSE; +} + +static void +send_children_changed (AtspiAccessible *parent, AtspiAccessible *child, gboolean add) +{ + AtspiEvent e; + + memset (&e, 0, sizeof(e)); + e.type = (add? "object:children-changed:add": "object:children-changed:remove"); + e.source = parent; + e.detail1 = g_list_index (parent->children, child); + atspi_dispatch_event (&e); +} + +static void +unref_object_and_descendants (AtspiAccessible *obj) +{ + GList *l; + + for (l = obj->children; l; l = l->next) + { + unref_object_and_descendants (l->data); + } + g_object_unref_internal (obj, TRUE); +} + +static gboolean +remove_app_from_desktop (AtspiAccessible *a, const char *bus_name) +{ + GList *l; + AtspiAccessible *child; + + for (l = a->children; l; l = l->next) + { + child = l->data; + if (!strcmp (bus_name, child->app->bus_name)) break; + } + if (!l) + { + g_warning ("Removing unregistered app %s; doing nothing\n", bus_name); + return FALSE; + } + send_children_changed (a, child, FALSE); + a->children = g_list_remove (a->children, child); + unref_object_and_descendants (child); + return TRUE; +} + +static AtspiAccessible *desktop; + +static void +get_reference_from_iter (DBusMessageIter *iter, const char **app_name, const char **path) +{ + DBusMessageIter iter_struct; + + dbus_message_iter_recurse (iter, &iter_struct); + dbus_message_iter_get_basic (&iter_struct, &app_name); + dbus_message_iter_get_basic (&iter_struct, &path); + dbus_message_iter_next (iter); +} + +static void +add_accessible_from_iter (DBusMessageIter *iter) +{ + gint i; + GList *new_list; + DBusMessageIter iter_struct, iter_array; + const char *app_name, *path; + AtspiApplication *app; + AtspiAccessible *accessible; + const char *name, *description; + dbus_uint32_t role; + dbus_uint32_t *states; + int count; + + dbus_message_iter_recurse (iter, &iter_struct); + + /* get accessible */ + get_reference_from_iter (&iter_struct, &app_name, &path); + accessible = ref_accessible (app_name, path); + + /* get parent */ + get_reference_from_iter (&iter_struct, &app_name, &path); + accessible->accessible_parent = ref_accessible (app_name, path); + + /* Get children */ + dbus_message_iter_recurse (&iter_struct, &iter_array); + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + AtspiAccessible *child; + get_reference_from_iter (&iter_array, &app_name, &path); + child = ref_accessible (app_name, path); + new_list = g_list_append (accessible->children, child); + if (new_list) accessible->children = new_list; + } + + /* interfaces */ + accessible->interfaces = 0; + dbus_message_iter_next (&iter_struct); + dbus_message_iter_recurse (&iter_struct, &iter_array); + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + const char *iface; + gint n; + dbus_message_iter_get_basic (&iter_array, &iface); + if (!strcmp (iface, "org.freedesktop.DBus.Introspectable")) continue; + n = get_iface_num (iface); + if (n == -1) + { + g_warning ("Unknown interface %s", iface); + } + else accessible->interfaces |= (1 << n); + } + dbus_message_iter_next (&iter_struct); + + /* name */ + dbus_message_iter_get_basic (&iter_struct, &name); + accessible->name = g_strdup (name); + dbus_message_iter_next (&iter_struct); + + /* role */ + dbus_message_iter_get_basic (&iter_struct, &role); + accessible->role = role; + dbus_message_iter_next (&iter_struct); + + /* description */ + dbus_message_iter_get_basic (&iter_struct, &description); + accessible->description = g_strdup (description); + dbus_message_iter_next (&iter_struct); + + dbus_message_iter_recurse (&iter_struct, &iter_array); + dbus_message_iter_get_fixed_array (&iter_array, &states, &count); + if (count != 2) + { + g_warning ("at-spi: expected 2 values in states array; got %d\n", count); + accessible->states = atspi_state_set_new (0); + } + else + { + guint64 val = ((guint64)states [1]) << 32; + val += states [0]; + accessible->states = atspi_state_set_new (val); + } + dbus_message_iter_next (&iter_struct); + + /* This is a bit of a hack since the cache holds a ref, so we don't need + * the one provided for us anymore */ + g_object_unref (accessible); +} + +static void +add_accessibles (const char *app_name) +{ + DBusError error; + DBusMessage *message, *reply; + DBusMessageIter iter, iter_array; + + AtspiApplication *app = get_application (app_name); + /* TODO: Move this functionality into app initializer? */ + dbus_error_init (&error); + message = dbus_message_new_method_call (app_name, "/org/a11y/atspi/accessible/cache", atspi_interface_cache, "GetItems"); + reply = _atspi_dbus_send_with_reply_and_block (message); + if (!reply || strcmp (dbus_message_get_signature (reply), "a((so)(so)a(so)assusau)") != 0) + { + g_warning ("at-spi: Error in GetItems"); + return; + if (reply) + dbus_message_unref (reply); + } + dbus_message_iter_init (reply, &iter); + dbus_message_iter_recurse (&iter, &iter_array); + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + add_accessible_from_iter (&iter_array); + dbus_message_iter_next (&iter_array); + } + dbus_message_unref (reply); +} + +/* TODO: Do we stil need this function? */ +static AtspiAccessible * +ref_accessible_desktop (AtspiApplication *app) +{ + DBusError error; + GArray *apps = NULL; + GArray *additions; + gint i; + DBusMessage *message, *reply; + DBusMessageIter iter, iter_array; + + if (desktop) + { + g_object_ref (desktop); + return desktop; + } + desktop = atspi_accessible_new (); + if (!desktop) + { + return NULL; + } + g_hash_table_insert (app->hash, 0, desktop); + desktop->app = app; + g_object_ref (desktop); /* for the hash */ + desktop->name = g_strdup ("main"); + dbus_error_init (&error); + message = dbus_message_new_method_call (atspi_bus_registry, + atspi_path_root, + atspi_interface_accessible, + "GetChildren"); + if (!message) + return; + reply = _atspi_dbus_send_with_reply_and_block (message); + if (!reply || strcmp (dbus_message_get_signature (reply), "a(so") != 0) + { + g_error ("Couldn't get application list: %s", error.message); + if (reply) + dbus_message_unref (reply); + return; + } + dbus_message_iter_init (reply, &iter); + dbus_message_iter_recurse (&iter, &iter_array); + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + const char *app_name, *path; + get_reference_from_iter (&iter_array, &app_name, &path); + add_accessibles (app_name); + add_app_to_desktop (desktop, app_name); + } + dbus_message_unref (reply); + return desktop; +} + +AtspiAccessible * +_atspi_ref_accessible (const char *app, const char *path) +{ + AtspiApplication *a = get_application (app); + if (!a) return NULL; + if ( APP_IS_REGISTRY(a)) + { + return ref_accessible_desktop (a); + } + return ref_accessible (app, path); +} + +AtspiAccessible * +_atspi_ref_related_accessible (AtspiAccessible *obj, const AtspiReference *ref) +{ + const char *app = (ref->name && ref->name[0]? ref->name: obj->app->bus_name); + return ref_accessible (app, obj->path); +} + +const char *cache_signal_type = "((so)(so)a(so)assusau)"; + +static DBusHandlerResult +handle_add_accessible (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + DBusMessageIter iter; + const char *sender = dbus_message_get_sender (message); + AtspiApplication *app = get_application (sender); + const char *type = cache_signal_type; + + if (strcmp (dbus_message_get_signature (message), cache_signal_type) != 0) + { + g_warning ("atspi: AddAccessible with unknown signature %s\n", dbus_message_get_signature (message)); + return; + } + + dbus_message_iter_init (message, &iter); + add_accessible_from_iter (&iter); +} + +static DBusHandlerResult +atspi_dbus_filter (DBusConnection *bus, DBusMessage *message, void *data) +{ + int type = dbus_message_get_type (message); + const char *interface = dbus_message_get_interface (message); + const char *member = dbus_message_get_member (message); + dbus_uint32_t v; + char *bus_name; + + if (type == DBUS_MESSAGE_TYPE_SIGNAL && + !strncmp (interface, "org.a11y.atspi.Event.", 28)) + { + g_warning ("atspi: TODO: event"); + //return handle_event (bus, message, data); + } + if (dbus_message_is_method_call (message, atspi_interface_device_event_listener, "notifyEvent")) + { + g_warning ("atspi: TODO: DeviceEvent"); + //return handle_device_event (bus, message, data); + } + if (dbus_message_is_signal (message, atspi_interface_cache, "AddAccessible")) + { + return handle_add_accessible (bus, message, data); + } + if (dbus_message_is_signal (message, atspi_interface_cache, "RemoveAccessible")) + { + return handle_remove_accessible (bus, message, data); + } + /* TODO: Handle ChildrenChanged, StateChanged, PropertyChanged */ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static const char *signal_interfaces[] = +{ + "org.a11y.atspi.Event.Object", + "org.a11y.atspi.Event.Window", + "org.a11y.atspi.Event.Mouse", + "org.a11y.atspi.Event.Terminal", + "org.a11y.atspi.Event.Document", + "org.a11y.atspi.Event.Focus", + NULL +}; + +/** + * atspi_init: + * + * Connects to the accessibility registry and initializes the SPI. + * + * Returns: 0 on success, otherwise an integer error code. + **/ +int +atspi_init (void) +{ + DBusError error; + char *match; + int i; + + if (atspi_inited) + { + return 1; + } + + atspi_inited = TRUE; + + g_type_init (); + + get_live_refs(); + g_atexit (cleanup); + + dbus_error_init (&error); + bus = dbus_bus_get (DBUS_BUS_SESSION, &error); + if (!bus) + { + g_error ("Couldn't get session bus"); + return 2; + } + dbus_bus_register (bus, &error); + dbus_connection_setup_with_g_main(bus, g_main_context_default()); + dbus_connection_add_filter (bus, atspi_dbus_filter, NULL, NULL); + match = g_strdup_printf ("type='signal',interface='%s',member='AddAccessible'", atspi_interface_cache); + dbus_error_init (&error); + dbus_bus_add_match (bus, match, &error); + g_free (match); + match = g_strdup_printf ("type='signal',interface='%s',member='RemoveAccessible'", atspi_interface_cache); + dbus_bus_add_match (bus, match, &error); + g_free (match); + for (i = 0; signal_interfaces[i]; i++) + { + match = g_strdup_printf ("type='signal',interface='%s'", signal_interfaces[i]); + dbus_bus_add_match (bus, match, &error); + g_free (match); + } + return 0; +} + + static GMainLoop *mainloop; + +/** + * atspi_event_main: + * + * Starts/enters the main event loop for the AT-SPI services. + * + * (NOTE: This method does not return control, it is exited via a call to + * atspi_event_quit () from within an event handler). + * + **/ +void +atspi_event_main (void) +{ + mainloop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (mainloop); +} + +/** + * atspi_event_quit: + * + * Quits the last main event loop for the SPI services, + * see atspi_event_main + **/ +void +atspi_event_quit (void) +{ + g_main_loop_quit (mainloop); +} + +/** + * atspi_exit: + * + * Disconnects from the Accessibility Registry and releases + * any floating resources. Call only once at exit. + * + * Returns: 0 if there were no leaks, otherwise non zero. + **/ +int +atspi_exit (void) +{ + int leaked; + + if (!atspi_inited) + { + return 0; + } + + atspi_inited = FALSE; + + if (live_refs) + { + leaked = g_hash_table_size (live_refs); + } + else + { + leaked = 0; + } + + cleanup (); + + return leaked; +} + +dbus_bool_t +_atspi_dbus_call (AtspiAccessible *obj, const char *interface, const char *method, GError **error, const char *type, ...) +{ + va_list args; + dbus_bool_t retval; + DBusError err; + + dbus_error_init (&err); + va_start (args, type); + retval = dbind_method_call_reentrant_va (_atspi_bus(), obj->app->bus_name, obj->path, interface, method, &err, type, args); + va_end (args); + if (dbus_error_is_set (&err)) + { + /* TODO: Set gerror */ + dbus_error_free (&err); + } + return retval; +} + +DBusMessage * +_atspi_dbus_call_partial (AtspiAccessible *obj, const char *interface, const char *method, GError **error, const char *type, ...) +{ + va_list args; + dbus_bool_t retval; + DBusError err; + DBusMessage *msg = NULL, *reply = NULL; + DBusMessageIter iter; + const char *p; + + dbus_error_init (&err); + va_start (args, type); + + msg = dbus_message_new_method_call (obj->app->bus_name, obj->path, interface, method); + if (!msg) + goto out; + + p = type; + dbus_message_iter_init_append (msg, &iter); + dbind_any_marshal_va (&iter, &p, args); + + reply = dbind_send_and_allow_reentry (_atspi_bus(), msg, &err); +out: + va_end (args); + if (dbus_error_is_set (&err)) + { + /* TODO: Set gerror */ + dbus_error_free (&err); + } + return reply; +} + +dbus_bool_t +_atspi_dbus_get_property (AtspiAccessible *obj, const char *interface, const char *name, GError **error, const char *type, void *data) +{ + DBusMessage *message, *reply; + DBusMessageIter iter, iter_variant; + DBusError err; + dbus_bool_t retval = FALSE; + + message = dbus_message_new_method_call (obj->app->bus_name, obj->path, "org.freedesktop.DBus.Properties", "Get"); + if (!message) + { + // TODO: throw exception + goto done; + } + dbus_message_append_args (message, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID); + dbus_error_init (&err); + reply = dbus_connection_send_with_reply_and_block (_atspi_bus(), message, 1000, &err); + dbus_message_unref (message); + if (!reply) + { + // TODO: throw exception + goto done; + } + dbus_message_iter_init (reply, &iter); + dbus_message_iter_recurse (&iter, &iter_variant); + if (dbus_message_iter_get_arg_type (&iter_variant) != type[0]) + { + g_warning ("atspi_dbus_get_property: Wrong type: expected %s, got %c\n", type, dbus_message_iter_get_arg_type (&iter_variant)); + goto done; + } + dbus_message_iter_get_basic (&iter_variant, data); + dbus_message_unref (reply); + if (type[0] == 's') *(char **)data = g_strdup (*(char **)data); + retval = TRUE; +done: + return retval; +} + +DBusMessage * +_atspi_dbus_send_with_reply_and_block (DBusMessage *message) +{ + DBusMessage *reply; + DBusError err; + + dbus_error_init (&err); + g_warning ("TODO: Write _atspi_dbus_send_with_reply_and_block"); + reply = dbus_connection_send_with_reply_and_block (_atspi_bus(), message, 1000, &err); + dbus_message_unref (message); + return reply; +} + +GHashTable * +_atspi_dbus_hash_from_message (DBusMessage *message) +{ + GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal); + DBusMessageIter iter, iter_array, iter_dict; + const char *signature; + + signature = dbus_message_get_signature (message); + + if (strcmp (signature, "a{ss}") != 0) + { + g_warning ("Trying to get hash from message of unexpected type %s\n", signature); + return NULL; + } + + dbus_message_iter_init (message, &iter); + dbus_message_iter_recurse (&iter, &iter_array); + do + { + const char *name, *value; + dbus_message_iter_recurse (&iter_array, &iter_dict); + dbus_message_iter_get_basic (&iter_dict, &name); + dbus_message_iter_get_basic (&iter_dict, &value); + g_hash_table_insert (hash, g_strdup (name), g_strdup (value)); + } while (dbus_message_iter_next (&iter_array)); + return hash; +} + diff --git a/atspi/atspi-misc.h b/atspi/atspi-misc.h new file mode 100644 index 0000000..7cf13c7 --- /dev/null +++ b/atspi/atspi-misc.h @@ -0,0 +1,36 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSPI_MISC_H_ +#define _ATSPI_MISC_H_ + +int atspi_init (void); + +void atspi_event_main (); + +void atspi_event_quit (); + +int atspi_exit (); + +#endif /* _ATSPI_MISC_H_ */ diff --git a/atspi/atspi-private.h b/atspi/atspi-private.h new file mode 100644 index 0000000..fe06c1f --- /dev/null +++ b/atspi/atspi-private.h @@ -0,0 +1,33 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSPI_PRIVATE_H_ +#define _ATSPI_PRIVATE_H_ + +#include "atspi-listener-private.h" +#include "atspi-misc-private.h" + +#include "atspi.h" + +#endif /* _ATSPI_PRIVATE_H_ */ diff --git a/atspi/atspi-registry.c b/atspi/atspi-registry.c new file mode 100644 index 0000000..2e4763b --- /dev/null +++ b/atspi/atspi-registry.c @@ -0,0 +1,364 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* atspi_registry.c: Global functions wrapping the registry */ + +#include "atspi-private.h" + +static GArray *desktops; + +/** + * atspi_get_desktop_count: + * + * Get the number of virtual desktops. + * NOTE: currently multiple virtual desktops are not implemented, this + * function always returns '1'. + * + * Returns: an integer indicating the number of active virtual desktops. + **/ +gint +atspi_get_desktop_count () +{ + return 1; +} + +/** + * atspi_get_desktop: + * @i: an integer indicating which of the accessible desktops is to be returned. + * + * Get the virtual desktop indicated by index @i. + * NOTE: currently multiple virtual desktops are not implemented. + * + * Returns: a pointer to the 'i-th' virtual desktop's #AtspiAccessible + * representation. + **/ +AtspiAccessible* +atspi_get_desktop (gint i) +{ + if (i != 0) return NULL; + return _atspi_ref_accessible (atspi_bus_registry, atspi_path_root); +} + +/** + * atspi_get_desktop_list: + * @desktop_list: a pointer to an array of #Accessible references. + * + * Get the list of virtual desktops. On return, @list will point + * to a newly-created, NULL terminated array of virtual desktop + * pointers. + * It is the responsibility of the caller to free this array when + * it is no longer needed. + * + * Not Yet Implemented : this implementation always returns a single + * #Accessible desktop. + * + * Returns: an integer indicating how many virtual desktops have been + * placed in the list pointed to by parameter @list. + **/ +/* TODO: Make this a garray */ +GArray * +atspi_get_desktop_list () +{ + GArray *array = g_array_new (TRUE, TRUE, sizeof (AtspiAccessible *)); + AtspiAccessible *desktop; + + desktop = _atspi_ref_accessible (atspi_bus_registry, atspi_path_root); + if (array) + g_array_index (array, AtspiAccessible *, 0) = desktop; + return array; +} + +/** + * ATSPI_KEYSET_ALL_KEYS: + * @ATSPI_KEYSET_ALL_KEYS: A special value for an AccessibleKeySet type, which tacitly + * includes all keycodes and keyvals for the specified modifier set. + **/ + +/** + * atspi_register_accessible_keystroke_listener: + * @listener: a pointer to the #AccessibleKeystrokeListener for which + * keystroke events are requested. + * @keys: a pointer to the #AccessibleKeySet indicating which + * keystroke events are requested, or #ATSPI_KEYSET_ALL_KEYS + * to indicate that all keycodes and keyvals for the specified + * modifier set are to be included. + * @modmask: an #AccessibleKeyMaskType mask indicating which + * key event modifiers must be set in combination with @keys, + * events will only be reported for key events for which all + * modifiers in @modmask are set. If you wish to listen for + * events with multiple modifier combinations you must call + * registerAccessibleKeystrokeListener() once for each combination. + * @eventmask: an #AccessibleKeyMaskType mask indicating which + * types of key events are requested (#ATSPI_KEY_PRESSED, etc.). + * @sync_type: a #AccessibleKeyListenerSyncType parameter indicating + * the behavior of the notification/listener transaction. + * + * Register a listener for keystroke events, either pre-emptively for + * all windows (ATSPI_KEYLISTENER_ALL_WINDOWS), + * non-preemptively (ATSPI_KEYLISTENER_NOSYNC), or + * pre-emptively at the toolkit level (ATSPI_KEYLISTENER_CANCONSUME). + * If ALL_WINDOWS or CANCONSUME are used, the event is consumed + * upon receipt if one of @listener's callbacks returns #TRUE. + * ( Other sync_type values may be available in the future ) + * + * Returns: #TRUE if successful, otherwise #FALSE. + **/ +gboolean +atspi_register_accessible_keystroke_listener (AtspiKeystrokeListener *listener, + AtspiKeySet *keys, + AtspiKeyMaskType modmask, + AtspiKeyEventMask eventmask, + AtspiKeyListenerSyncType sync_type, GError **error) +{ + gchar *path = _atspi_device_listener_get_path (listener); + gint i; + GArray *key_set; + dbus_uint32_t key_events = 0; + AtspiControllerEventMask controller_event_mask; + AtspiEventListenerMode listener_mode; + gboolean retval = FALSE; + DBusError d_error; + + if (!listener) + { + return retval; + } + + /* copy the keyval filter values from the C api into the DBind KeySet */ + if (keys) + { + key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), keys->len); + key_set->len = keys->len; + for (i = 0; i < keys->len; ++i) + { + AtspiKeyDefinition *kd = ((AtspiKeyDefinition *) key_set->data) + i; + kd->keycode = keys->keycodes[i]; + kd->keysym = keys->keysyms[i]; + if (keys->keystrings && keys->keystrings[i]) + { + kd->keystring = keys->keystrings[i]; + } + else + { + kd->keystring = ""; + } + } + } + else + { + key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0); + } + + /* copy the event filter values from the C api into the DBus key_events */ + if (eventmask & ATSPI_KEY_PRESSED) + { + key_events |= (1 << ATSPI_KEY_PRESSED_EVENT); + } + if (eventmask & ATSPI_KEY_RELEASED) + { + key_events |= (1 << ATSPI_KEY_RELEASED_EVENT); + } + + controller_event_mask = (dbus_uint32_t) modmask; + + listener_mode.synchronous = + (dbus_bool_t) ((sync_type & ATSPI_KEYLISTENER_SYNCHRONOUS)!=0); + listener_mode.preemptive = + (dbus_bool_t) ((sync_type & ATSPI_KEYLISTENER_CANCONSUME)!=0); + listener_mode.global = + (dbus_bool_t) ((sync_type & ATSPI_KEYLISTENER_ALL_WINDOWS)!=0); + + dbus_error_init (&d_error); + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "RegisterKeystrokeListener", &d_error, "oa(iisi)uu(bbb)=>b", path, key_set, controller_event_mask, key_events, &listener_mode, &retval); + + g_array_free (key_set, TRUE); + g_free (path); + + return retval; +} + +/** + * atspi_deregister_accessible_keystroke_listener: + * @listener: a pointer to the #AccessibleKeystrokeListener for which + * keystroke events are requested. + * @modmask: the key modifier mask for which this listener is to be + * 'deregistered' (of type #AtspiKeyMaskType). + * + * Removes a keystroke event listener from the registry's listener queue, + * ceasing notification of events with modifiers matching @modmask. + * + * Returns: #TRUE if successful, otherwise #FALSE. + **/ +gboolean +atspi_deregister_accessible_keystroke_listener (AtspiKeystrokeListener *listener, + AtspiKeyMaskType modmask, GError **error) +{ + gchar *path = _atspi_device_listener_get_path (listener); + AtspiControllerEventMask controller_event_mask; + GArray *key_set; + dbus_uint32_t key_events = 0; + DBusError d_error; + + dbus_error_init (&d_error); + if (!listener) + { + return FALSE; + } + + controller_event_mask = (dbus_uint32_t) modmask; + + key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0); + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "DeregisterKeystrokeListener", &d_error, "oa(iisi)uu", path, &key_set, key_events, controller_event_mask); + g_free (path); + return TRUE; +} + +/** + * atspi_register_device_event_listener: + * @listener: a pointer to the #AtspiDeviceListener which requests + * the events. + * @eventmask: an #AtspiDeviceEventMask mask indicating which + * types of key events are requested (#ATSPI_KEY_PRESSED, etc.). + * @filter: Unused parameter. + * + * Register a listener for device events, for instance button events. + * + * Returns: #TRUE if successful, otherwise #FALSE. + **/ +gboolean +atspi_register_device_event_listener (AtspiDeviceListener *listener, + AtspiDeviceEventMask event_mask, + void *filter, GError **error) +{ + gboolean retval = FALSE; + dbus_uint32_t d_event_mask = event_mask; + gint i; + gchar *path = _atspi_device_listener_get_path (listener); + DBusError d_error; + + dbus_error_init (&d_error); + if (!listener) + { + return retval; + } + + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "RegisterDeviceEventListener", &d_error, "ou=>b", path, d_event_mask, &retval); + g_free (path); + return retval; +} + +/** + * atspi_deregister_device_event_listener: + * @listener: a pointer to the #AtspiDeviceListener for which + * device events are requested. + * @filter: Unused parameter. + * + * Removes a device event listener from the registry's listener queue, + * ceasing notification of events of the specified type. + * + * Returns: #TRUE if successful, otherwise #FALSE. + **/ +gboolean +atspi_deregister_device_event_listener (AtspiDeviceListener *listener, + void *filter, GError **error) +{ + dbus_uint32_t event_types = 0; + gchar *path = _atspi_device_listener_get_path (listener); + DBusError d_error; + + dbus_error_init (&d_error); + + if (!listener) + { + return FALSE; + } + + event_types |= (1 << ATSPI_BUTTON_PRESSED_EVENT); + event_types |= (1 << ATSPI_BUTTON_RELEASED_EVENT); + + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "DeregisterDeviceEventListener", &d_error, "ou", path, event_types); + g_free (path); + return TRUE; +} + +/** + * atspi_generate_keyboard_event: + * @keyval: a long integer indicating the keycode or keysym of the key event + * being synthesized. + * @keystring: an (optional) UTF-8 string which, if @keyval is NULL, + * indicates a 'composed' keyboard input string which is + * being synthesized; this type of keyboard event synthesis does + * not emulate hardware keypresses but injects the string + * as though a composing input method (such as XIM) were used. + * @synth_type: a #AccessibleKeySynthType flag indicating whether @keyval + * is to be interpreted as a keysym rather than a keycode + * (ATSPI_KEYSYM), or whether to synthesize + * ATSPI_KEY_PRESS, ATSPI_KEY_RELEASE, or both (ATSPI_KEY_PRESSRELEASE). + * + * Synthesize a keyboard event (as if a hardware keyboard event occurred in the + * current UI context). + * + * Returns: #TRUE if successful, otherwise #FALSE. + **/ +gboolean +atspi_generate_keyboard_event (glong keyval, + const gchar *keystring, + AtspiKeySynthType synth_type, GError **error) +{ + dbus_uint32_t d_synth_type = synth_type; + dbus_int32_t d_keyval = keyval; + DBusError d_error; + + dbus_error_init (&d_error); + if (!keystring) keystring = ""; + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "GenerateKeyboardEvent", &d_error, "isu", d_keyval, keystring, d_synth_type); + + return TRUE; +} + +/** + * atspi_generate_mouse_event: + * @x: a #long indicating the screen x coordinate of the mouse event. + * @y: a #long indicating the screen y coordinate of the mouse event. + * @name: a string indicating which mouse event to be synthesized + * (e.g. "b1p", "b1c", "b2r", "rel", "abs"). + * + * Synthesize a mouse event at a specific screen coordinate. + * Most AT clients should use the #AccessibleAction interface when + * tempted to generate mouse events, rather than this method. + * Event names: b1p = button 1 press; b2r = button 2 release; + * b3c = button 3 click; b2d = button 2 double-click; + * abs = absolute motion; rel = relative motion. + * + * Returns: #TRUE if successful, otherwise #FALSE. + **/ +gboolean +atspi_generate_mouse_event (glong x, glong y, const gchar *name, GError **error) +{ + dbus_int32_t dbus_x = x, dbus__y = y; + DBusError d_error; + + dbus_error_init (&d_error); + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "GenerateMouseEvent", &d_error, "iis", x, y, name); + return TRUE; +} diff --git a/atspi/atspi-registry.h b/atspi/atspi-registry.h new file mode 100644 index 0000000..4fa64e9 --- /dev/null +++ b/atspi/atspi-registry.h @@ -0,0 +1,66 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSPI_REGISTRY_H_ +#define _ATSPI_REGISTRY_H_ + +#include "atspi-accessible.h" +#include "atspi-event-types.h" +#include "atspi-listener.h" + +gint atspi_get_desktop_count (); + +AtspiAccessible* atspi_get_desktop (gint i); + +GArray *atspi_get_desktop_list (); + +gboolean +atspi_register_accessible_keystroke_listener (AtspiKeystrokeListener *listener, + AtspiKeySet *keys, + AtspiKeyMaskType modmask, + AtspiKeyEventMask event_mask, + AtspiKeyListenerSyncType sync_type, GError **error); + +gboolean +atspi_deregister_accessible_keystroke_listener (AtspiKeystrokeListener *listener, + AtspiKeyMaskType modmask, GError **error); + +gboolean +atspi_register_device_event_listener (AtspiDeviceListener *listener, + AtspiDeviceEventMask eventmask, + void *filter, GError **error); + +gboolean +atspi_deregister_device_event_listener (AtspiDeviceListener *listener, + void *filter, GError **error); + +gboolean +atspi_generate_keyboard_event (glong keyval, + const gchar *keystring, + AtspiKeySynthType synth_type, GError **error); + +gboolean +atspi_generate_mouse_event (glong x, glong y, const gchar *name, GError **error); + +#endif /* _ATSPI_REGISTRY_H_ */ diff --git a/atspi/atspi-stateset.c b/atspi/atspi-stateset.c new file mode 100644 index 0000000..74d45c3 --- /dev/null +++ b/atspi/atspi-stateset.c @@ -0,0 +1,28 @@ +#include "atspi-private.h" + +static void atspi_state_set_class_init (AtspiStateSetClass *klass); + +G_DEFINE_TYPE (AtspiStateSet, atspi_state_set, G_TYPE_OBJECT) + +static void +atspi_state_set_init (AtspiStateSet *set) +{ + set->states = 0; +} + +static void +atspi_state_set_class_init (AtspiStateSetClass* klass) +{ +} + +AtspiStateSet * +atspi_state_set_new (gint64 states) +{ + AtspiStateSet *set; + + set = g_object_new (ATSPI_TYPE_STATE_SET, NULL); + g_return_val_if_fail (set != NULL, NULL); + + set->states = states; + return set; +} diff --git a/atspi/atspi-stateset.h b/atspi/atspi-stateset.h new file mode 100644 index 0000000..44690b5 --- /dev/null +++ b/atspi/atspi-stateset.h @@ -0,0 +1,29 @@ +#ifndef _ATSPI_STATE_SET_H_ +#define _ATSPI_STATE_SET_H_ + +#define ATSPI_TYPE_STATE_SET (atspi_state_set_get_type ()) +#define ATSPI_STATE_SET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_STATE_SET, AtspiStateSet)) +#define ATSPI_STATE_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_STATE_SET, AtspiStateSetClass)) +#define ATSPI_IS_STATE_SET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_STATE_SET)) +#define ATSPI_IS_STATE_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_STATE_SET)) +#define ATSPI_STATE_SET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_STATE_SET, AtspiStateSetClass)) + +typedef struct _AtspiStateSet AtspiStateSet; +struct _AtspiStateSet +{ + GObject parent; + gint64 states; +}; + +typedef struct _AtspiStateSetClass AtspiStateSetClass; +struct _AtspiStateSetClass +{ + GObjectClass parent_class; +}; + +GType atspi_state_set_get_type (void); + +AtspiStateSet * +atspi_state_set_new (gint64 states); + +#endif /* _ATSPI_STATE_SET_H_ */ diff --git a/atspi/atspi.h b/atspi/atspi.h new file mode 100644 index 0000000..1d4c134 --- /dev/null +++ b/atspi/atspi.h @@ -0,0 +1,36 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSPI_H +#define _ATSPI_H + +#include "glib.h" + +#include "atspi-constants.h" +#include "atspi-event-types.h" +#include "atspi-accessible.h" +#include "atspi-listener.h" +#include "atspi-misc.h" +#include "atspi-registry.h" + +#endif diff --git a/configure.ac b/configure.ac index 70533dc..8706931 100644 --- a/configure.ac +++ b/configure.ac @@ -160,6 +160,8 @@ else fi AC_SUBST(DBUS_SERVICES_DIR) +GOBJECT_INTROSPECTION_CHECK([0.9.6]) + AC_SUBST(LIBTOOL_EXPORT_OPTIONS) AC_ARG_ENABLE([relocate], @@ -175,7 +177,9 @@ AC_SUBST(enable_relocate) AC_CONFIG_FILES([Makefile xml/Makefile -libspi/Makefile + dbind/Makefile +dbind/dbind-config.h + atspi/Makefile registryd/Makefile bus/at-spi-dbus-bus bus/Makefile]) diff --git a/dbind/Makefile.am b/dbind/Makefile.am new file mode 100644 index 0000000..f7e6f53 --- /dev/null +++ b/dbind/Makefile.am @@ -0,0 +1,22 @@ +noinst_LTLIBRARIES = libdbind.la + +AM_CPPFLAGS = \ + -DG_LOG_DOMAIN=\"dbind\" \ + -I$(top_srcdir) \ + $(WARN_CFLAGS) \ + $(DBUS_CFLAGS) \ + $(GLIB_CFLAGS) + +libdbind_la_SOURCES = \ + dbind-config.h \ + dbind.h \ + dbind.c \ + dbind-any.h \ + dbind-any.c +libdbind_la_LIBADD = $(DBUS_LIBS) $(GLIB_LIBS) + +TESTS = dbtest + +check_PROGRAMS = dbtest +dbtest_SOURCES = dbtest.c +dbtest_LDFLAGS = libdbind.la diff --git a/dbind/dbind-any.c b/dbind/dbind-any.c new file mode 100644 index 0000000..95dd9ab --- /dev/null +++ b/dbind/dbind-any.c @@ -0,0 +1,670 @@ +/* type driven marshalling */ +#include +#include + +#include "config.h" +#include "dbind-config.h" +#include "dbind-any.h" + +#undef DEBUG + +/* Align a value upward to a boundary, expressed as a number of bytes. + * E.g. align to an 8-byte boundary with argument of 8. + * + * (this + boundary - 1) + * & + * ~(boundary - 1) + */ +#define ALIGN_VALUE(this, boundary) \ + (( ((gulong)(this)) + (((gulong)(boundary)) -1)) & (~(((gulong)(boundary))-1))) + +#define ALIGN_ADDRESS(this, boundary) \ + ((gpointer)ALIGN_VALUE(this, boundary)) + +#define PTR_PLUS(ptr, offset) \ + ((gpointer) (((guchar *)(ptr)) + (offset))) + +#define DBIND_POD_CASES \ + DBUS_TYPE_BYTE: \ + case DBUS_TYPE_INT16: \ + case DBUS_TYPE_UINT16: \ + case DBUS_TYPE_INT32: \ + case DBUS_TYPE_UINT32: \ + case DBUS_TYPE_BOOLEAN: \ + case DBUS_TYPE_INT64: \ + case DBUS_TYPE_UINT64: \ + case DBUS_TYPE_DOUBLE + +/*---------------------------------------------------------------------------*/ + +static void +warn_braces () +{ + fprintf (stderr, "Error: dbus flags structures & dicts with braces rather than " + " an explicit type member of 'struct'\n"); +} + +/*---------------------------------------------------------------------------*/ + +static unsigned int +dbind_find_c_alignment_r (const char **type) +{ + unsigned int retval = 1; + + char t = **type; + (*type)++; + +#ifdef DEBUG + fprintf (stderr, "\tfind align for %c (0x%x)\n", t, t); +#endif + + switch (t) { + case DBUS_TYPE_BYTE: + return DBIND_ALIGNOF_CHAR; + case DBUS_TYPE_BOOLEAN: + return DBIND_ALIGNOF_DBUS_BOOL_T; + case DBUS_TYPE_INT16: + case DBUS_TYPE_UINT16: + return DBIND_ALIGNOF_DBUS_INT16_T; + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + return DBIND_ALIGNOF_DBUS_INT32_T; + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: + return DBIND_ALIGNOF_DBUS_INT64_T; + case DBUS_TYPE_DOUBLE: + return DBIND_ALIGNOF_DOUBLE; + /* ptr types */ + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: + case DBUS_TYPE_ARRAY: + return DBIND_ALIGNOF_DBIND_POINTER; + case DBUS_STRUCT_BEGIN_CHAR: + /* TODO: I think this would break with a nested struct */ +#if DBIND_ALIGNOF_DBIND_STRUCT > 1 + retval = MAX (retval, DBIND_ALIGNOF_DBIND_STRUCT); +#endif + while (**type != DBUS_STRUCT_END_CHAR) { + int elem_align = dbind_find_c_alignment_r (type); + retval = MAX (retval, elem_align); + } + (*type)++; + return retval; + case DBUS_DICT_ENTRY_BEGIN_CHAR: +#if DBIND_ALIGNOF_DBIND_STRUCT > 1 + retval = MAX (retval, DBIND_ALIGNOF_DBIND_STRUCT); +#endif + while (**type != DBUS_DICT_ENTRY_END_CHAR) { + int elem_align = dbind_find_c_alignment_r (type); + retval = MAX (retval, elem_align); + } + (*type)++; + return retval; + case DBUS_TYPE_STRUCT: + case DBUS_TYPE_DICT_ENTRY: + warn_braces (); + return DBIND_ALIGNOF_DBIND_POINTER; + case '\0': + g_assert_not_reached(); + break; + default: + return 1; + } +} + +/*---------------------------------------------------------------------------*/ + +/* gather immediate allocation information for this type */ +static size_t +dbind_gather_alloc_info_r (const char **type) +{ + char t = **type; + (*type)++; + if (t == DBUS_TYPE_ARRAY) + { + switch (**type) + { + case DBUS_STRUCT_BEGIN_CHAR: + while (**type != DBUS_STRUCT_END_CHAR && **type != '\0') (*type)++; + if (**type != '\0') (*type)++; + break; + case DBUS_DICT_ENTRY_BEGIN_CHAR: + while (**type != DBUS_DICT_ENTRY_END_CHAR && **type != '\0') (*type)++; + if (**type != '\0') (*type)++; + break; + case '\0': + break; + default: + (*type)++; + break; + } + } + + switch (t) { + case DBUS_TYPE_BYTE: + return sizeof (char); + case DBUS_TYPE_BOOLEAN: + return sizeof (dbus_bool_t); + case DBUS_TYPE_INT16: + case DBUS_TYPE_UINT16: + return sizeof (dbus_int16_t); + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + return sizeof (dbus_int32_t); + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: + return sizeof (dbus_int64_t); + case DBUS_TYPE_DOUBLE: + return sizeof (double); + /* ptr types */ + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: + case DBUS_TYPE_ARRAY: + return sizeof (void *); + case DBUS_STRUCT_BEGIN_CHAR: { + int sum = 0, stralign; + + stralign = dbind_find_c_alignment (*type - 1); + + while (**type != DBUS_STRUCT_END_CHAR) { + sum = ALIGN_VALUE (sum, dbind_find_c_alignment (*type)); + sum += dbind_gather_alloc_info_r (type); + } + sum = ALIGN_VALUE (sum, stralign); + + g_assert (**type == DBUS_STRUCT_END_CHAR); + (*type)++; + + return sum; + } + case DBUS_DICT_ENTRY_BEGIN_CHAR: { + int sum = 0, stralign; + + stralign = dbind_find_c_alignment (*type - 1); + + while (**type != DBUS_DICT_ENTRY_END_CHAR) { + sum = ALIGN_VALUE (sum, dbind_find_c_alignment (*type)); + sum += dbind_gather_alloc_info_r (type); + } + sum = ALIGN_VALUE (sum, stralign); + + g_assert (**type == DBUS_DICT_ENTRY_END_CHAR); + (*type)++; + + return sum; + } + case DBUS_TYPE_STRUCT: + case DBUS_TYPE_DICT_ENTRY: + warn_braces (); + default: + return 0; + } +} + +static size_t +dbind_gather_alloc_info (const char *type) +{ + return dbind_gather_alloc_info_r (&type); +} + +/*---------------------------------------------------------------------------*/ + +static void +dbind_any_free_r (const char **type, void **data) +{ +#ifdef DEBUG + fprintf (stderr, "any free '%c' to %p\n", **type, *data); +#endif + + switch (**type) { + case DBIND_POD_CASES: + *data = ((guchar *)*data) + dbind_gather_alloc_info (*type); + (*type)++; + break; + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: +#ifdef DEBUG + fprintf (stderr, "string free %p\n", **(void ***)data); +#endif + g_free (**(void ***)data); + *data = ((guchar *)*data) + dbind_gather_alloc_info (*type); + (*type)++; + break; + case DBUS_TYPE_ARRAY: { + int i; + GArray *vals = **(void ***)data; + size_t elem_size, elem_align; + const char *saved_child_type; + + (*type)++; + saved_child_type = *type; + + elem_size = dbind_gather_alloc_info (*type); + elem_align = dbind_find_c_alignment_r (type); + + for (i = 0; i < vals->len; i++) { + void *ptr = vals->data + elem_size * i; + *type = saved_child_type; /* rewind type info */ + ptr = ALIGN_ADDRESS (ptr, elem_align); + dbind_any_free_r (type, &ptr); + } + g_array_free (vals, TRUE); + break; + } + case DBUS_STRUCT_BEGIN_CHAR: { + gconstpointer data0 = *data; + int offset = 0, stralign; + + stralign = dbind_find_c_alignment (*type); + (*type)++; + + offset = 0 ; + while (**type != DBUS_STRUCT_END_CHAR) { + const char *subt = *type; + offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type)); + *data = PTR_PLUS (data0, offset); + dbind_any_free_r (type, data); + offset += dbind_gather_alloc_info (subt); + } + + offset = ALIGN_VALUE (offset, stralign); + *data = PTR_PLUS (data0, offset); + + g_assert (**type == DBUS_STRUCT_END_CHAR); + (*type)++; + + break; + } + case DBUS_DICT_ENTRY_BEGIN_CHAR: { + gconstpointer data0 = *data; + int offset = 0, stralign; + + stralign = dbind_find_c_alignment (*type); + (*type)++; + + offset = 0 ; + while (**type != DBUS_DICT_ENTRY_END_CHAR) { + char *subt = *type; + offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type)); + *data = PTR_PLUS (data0, offset); + dbind_any_free_r (type, data); + offset += dbind_gather_alloc_info (subt); + } + + offset = ALIGN_VALUE (offset, stralign); + *data = PTR_PLUS (data0, offset); + + g_assert (**type == DBUS_DICT_ENTRY_END_CHAR); + (*type)++; + + break; + } + case DBUS_TYPE_STRUCT: + case DBUS_TYPE_DICT_ENTRY: + warn_braces (); + break; + } +} + +/*---------------------------------------------------------------------------*/ + +void +dbind_any_marshal (DBusMessageIter *iter, + const char **type, + void **data) +{ + size_t len; + +#ifdef DEBUG + fprintf (stderr, "any marshal '%c' to %p\n", **type, *data); +#endif + + switch (**type) { + case DBIND_POD_CASES: + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: + len = dbind_gather_alloc_info (*type); + dbus_message_iter_append_basic (iter, **type, *data); + *data = ((guchar *)*data) + len; + (*type)++; + break; + case DBUS_TYPE_ARRAY: { + int i; + GArray *vals = **(void ***)data; + size_t elem_size, elem_align; + DBusMessageIter sub; + const char *saved_child_type; + char *child_type_string; + + (*type)++; + saved_child_type = *type; + + elem_size = dbind_gather_alloc_info (*type); + elem_align = dbind_find_c_alignment_r (type); + + /* wow this part of the API sucks too ... */ + child_type_string = g_strndup (saved_child_type, *type - saved_child_type); + /* fprintf (stderr, "array child type '%s'\n", child_type_string); */ + dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, + child_type_string, &sub); + for (i = 0; i < vals->len; i++) { + void *ptr = vals->data + elem_size * i; + *type = saved_child_type; /* rewind type info */ + ptr = ALIGN_ADDRESS (ptr, elem_align); + dbind_any_marshal (&sub, type, &ptr); + } + + dbus_message_iter_close_container (iter, &sub); + g_free (child_type_string); + break; + } + case DBUS_STRUCT_BEGIN_CHAR: { + gconstpointer data0 = *data; + int offset = 0, stralign; + DBusMessageIter sub; + + stralign = dbind_find_c_alignment (*type); + + (*type)++; + + dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, &sub); + + offset = 0 ; + while (**type != DBUS_STRUCT_END_CHAR) { + const char *subt = *type; + offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type)); + *data = PTR_PLUS (data0, offset); + dbind_any_marshal (&sub, type, data); + offset += dbind_gather_alloc_info (subt); + } + + offset = ALIGN_VALUE (offset, stralign); + *data = PTR_PLUS (data0, offset); + + dbus_message_iter_close_container (iter, &sub); + + g_assert (**type == DBUS_STRUCT_END_CHAR); + (*type)++; + + break; + } + case DBUS_DICT_ENTRY_BEGIN_CHAR: { + gconstpointer data0 = *data; + int offset = 0, stralign; + DBusMessageIter sub; + + stralign = dbind_find_c_alignment (*type); + + (*type)++; + + dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL, &sub); + + offset = 0 ; + while (**type != DBUS_DICT_ENTRY_END_CHAR) { + char *subt = *type; + offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type)); + *data = PTR_PLUS (data0, offset); + dbind_any_marshal (&sub, type, data); + offset += dbind_gather_alloc_info (subt); + } + + offset = ALIGN_VALUE (offset, stralign); + *data = PTR_PLUS (data0, offset); + + dbus_message_iter_close_container (iter, &sub); + + g_assert (**type == DBUS_DICT_ENTRY_END_CHAR); + (*type)++; + + break; + } + case DBUS_TYPE_STRUCT: + case DBUS_TYPE_DICT_ENTRY: + warn_braces (); + break; + } +} + +/*---------------------------------------------------------------------------*/ + +void +dbind_any_marshal_va (DBusMessageIter *iter, + const char **arg_types, + va_list args) +{ + const char *p = *arg_types; + + /* Guard against null arg types + Fix for - http://bugs.freedesktop.org/show_bug.cgi?id=23027 + */ + if (p == NULL) + p = ""; + + { + /* special case base-types since we need to walk the stack worse-luck */ + for (;*p != '\0' && *p != '=';) { + int intarg; + void *ptrarg; + double doublearg; + dbus_int64_t int64arg; + void *arg = NULL; + + switch (*p) { + case DBUS_TYPE_BYTE: + case DBUS_TYPE_BOOLEAN: + case DBUS_TYPE_INT16: + case DBUS_TYPE_UINT16: + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + intarg = va_arg (args, int); + arg = &intarg; + break; + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: + int64arg = va_arg (args, dbus_int64_t); + arg = &int64arg; + break; + case DBUS_TYPE_DOUBLE: + doublearg = va_arg (args, double); + arg = &doublearg; + break; + /* ptr types */ + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: + case DBUS_TYPE_ARRAY: + case DBUS_TYPE_DICT_ENTRY: + ptrarg = va_arg (args, void *); + arg = &ptrarg; + break; + case DBUS_STRUCT_BEGIN_CHAR: + ptrarg = va_arg (args, void *); + arg = ptrarg; + break; + case DBUS_DICT_ENTRY_BEGIN_CHAR: + ptrarg = va_arg (args, void *); + arg = ptrarg; + break; + + case DBUS_TYPE_VARIANT: + fprintf (stderr, "No variant support yet - very toolkit specific\n"); + ptrarg = va_arg (args, void *); + arg = &ptrarg; + break; + default: + fprintf (stderr, "Unknown / invalid arg type %c\n", *p); + break; + } + if (arg != NULL) + dbind_any_marshal (iter, &p, &arg); + } + } +} + +/*---------------------------------------------------------------------------*/ + +void +dbind_any_demarshal (DBusMessageIter *iter, + const char **type, + void **data) +{ + size_t len; + +#ifdef DEBUG + fprintf (stderr, "any demarshal '%c' to %p\n", **type, *data); +#endif + + switch (**type) { + case DBIND_POD_CASES: + len = dbind_gather_alloc_info (*type); + dbus_message_iter_get_basic (iter, *data); + *data = ((guchar *)*data) + len; + (*type)++; + break; + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: + len = dbind_gather_alloc_info (*type); + dbus_message_iter_get_basic (iter, *data); +#ifdef DEBUG + fprintf (stderr, "dup string '%s' (%p)\n", **(void ***)data, **(void ***)data); +#endif + **(void ***)data = g_strdup (**(void ***)data); + *data = ((guchar *)*data) + len; + (*type)++; + break; + case DBUS_TYPE_ARRAY: { + GArray *vals; + DBusMessageIter child; + size_t elem_size, elem_align; + const char *stored_child_type; + int i; + + (*type)++; + stored_child_type = *type; + + elem_size = dbind_gather_alloc_info (*type); + elem_align = dbind_find_c_alignment_r (type); + vals = g_array_new (FALSE, FALSE, elem_size); + (**(void ***)data) = vals; + *data = ((guchar *)*data) + sizeof (void *); + + i = 0; + dbus_message_iter_recurse (iter, &child); + while (dbus_message_iter_get_arg_type (&child) != DBUS_TYPE_INVALID) { + void *ptr; + const char *subt = stored_child_type; + g_array_set_size (vals, i + 1); + ptr = vals->data + elem_size * i; + ptr = ALIGN_ADDRESS (ptr, elem_align); + dbind_any_demarshal (&child, &subt, &ptr); + i++; + }; + break; + } + case DBUS_STRUCT_BEGIN_CHAR: { + gconstpointer data0 = *data; + int offset = 0, stralign; + DBusMessageIter child; + + stralign = dbind_find_c_alignment (*type); + + (*type)++; + + dbus_message_iter_recurse (iter, &child); + + while (**type != DBUS_STRUCT_END_CHAR) { + const char *subt = *type; + offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type)); + *data = PTR_PLUS (data0, offset); + dbind_any_demarshal (&child, type, data); + offset += dbind_gather_alloc_info (subt); + } + + offset = ALIGN_VALUE (offset, stralign); + *data = PTR_PLUS (data0, offset); + + g_assert (**type == DBUS_STRUCT_END_CHAR); + (*type)++; + + break; + } + case DBUS_DICT_ENTRY_BEGIN_CHAR: { + gconstpointer data0 = *data; + int offset = 0, stralign; + DBusMessageIter child; + + stralign = dbind_find_c_alignment (*type); + + (*type)++; + + dbus_message_iter_recurse (iter, &child); + + while (**type != DBUS_DICT_ENTRY_END_CHAR) { + char *subt = *type; + offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type)); + *data = PTR_PLUS (data0, offset); + dbind_any_demarshal (&child, type, data); + offset += dbind_gather_alloc_info (subt); + } + + offset = ALIGN_VALUE (offset, stralign); + *data = PTR_PLUS (data0, offset); + + g_assert (**type == DBUS_DICT_ENTRY_END_CHAR); + (*type)++; + + break; + } + case DBUS_TYPE_STRUCT: + case DBUS_TYPE_DICT_ENTRY: + warn_braces (); + break; + } + dbus_message_iter_next (iter); +} + +/*---------------------------------------------------------------------------*/ + +void +dbind_any_demarshal_va (DBusMessageIter *iter, + const char **arg_types, + va_list args) +{ + const char *p = *arg_types; + for (;*p != '\0';) { + void *arg = va_arg (args, void *); + dbind_any_demarshal (iter, &p, &arg); + } +} + +/*---------------------------------------------------------------------------*/ + +/* nice deep free ... */ +void +dbind_any_free (const char *type, + void *ptr) +{ + dbind_any_free_r (&type, &ptr); +} + +/* should this be the default normalization ? */ +void +dbind_any_free_ptr (const char *type, void *ptr) +{ + dbind_any_free (type, &ptr); +} + +/*---------------------------------------------------------------------------*/ + +unsigned int +dbind_find_c_alignment (const char *type) +{ + return dbind_find_c_alignment_r (&type); +} + +/*END------------------------------------------------------------------------*/ diff --git a/dbind/dbind-any.h b/dbind/dbind-any.h new file mode 100644 index 0000000..4aa0b95 --- /dev/null +++ b/dbind/dbind-any.h @@ -0,0 +1,31 @@ +#ifndef _DBIND_ANY_H_ +#define _DBIND_ANY_H_ + +#define DBUS_API_SUBJECT_TO_CHANGE +#include + +unsigned int dbind_find_c_alignment (const char *type); + +void dbind_any_marshal (DBusMessageIter *iter, + const char **type, + void **val); + +void dbind_any_marshal_va (DBusMessageIter *iter, + const const char **arg_types, + va_list args); + +void dbind_any_demarshal (DBusMessageIter *iter, + const char **type, + void **val); + +void dbind_any_demarshal_va (DBusMessageIter *iter, + const char **arg_types, + va_list args); + +void dbind_any_free (const char *type, + void *ptr_to_ptr); + +void dbind_any_free_ptr (const char *type, + void *ptr); + +#endif /* _DBIND_ANY_H_ */ diff --git a/dbind/dbind.c b/dbind/dbind.c new file mode 100644 index 0000000..5c49d66 --- /dev/null +++ b/dbind/dbind.c @@ -0,0 +1,230 @@ + + +#include +#include +#include + +#include "config.h" +#include "dbind/dbind.h" + +/* + * FIXME: compare types - to ensure they match & + * do dynamic padding of structures etc. + */ + +/*---------------------------------------------------------------------------*/ + +static void +set_reply (DBusPendingCall *pending, void *user_data) +{ + void **replyptr = (void **)user_data; + + *replyptr = dbus_pending_call_steal_reply (pending); +} + +DBusMessage * +dbind_send_and_allow_reentry (DBusConnection *bus, DBusMessage *message, DBusError *error) +{ + DBusPendingCall *pending; + DBusMessage *reply = NULL; + + if (!dbus_connection_send_with_reply (bus, message, &pending, -1)) + { + return NULL; + } + dbus_pending_call_set_notify (pending, set_reply, (void *)&reply, NULL); + while (!reply) + { + if (!dbus_connection_read_write_dispatch (bus, -1)) return NULL; + } + return reply; +} + +dbus_bool_t +dbind_method_call_reentrant_va (DBusConnection *cnx, + const char *bus_name, + const char *path, + const char *interface, + const char *method, + DBusError *opt_error, + const char *arg_types, + va_list args) +{ + dbus_bool_t success = FALSE; + DBusMessage *msg = NULL, *reply = NULL; + DBusMessageIter iter; + DBusError *err, real_err; + const char *p; + + if (opt_error) + err = opt_error; + else { + dbus_error_init (&real_err); + err = &real_err; + } + + msg = dbus_message_new_method_call (bus_name, path, interface, method); + if (!msg) + goto out; + + p = arg_types; + dbus_message_iter_init_append (msg, &iter); + dbind_any_marshal_va (&iter, &p, args); + + reply = dbind_send_and_allow_reentry (cnx, msg, err); + if (!reply) + goto out; + + if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) + { + const char *name = dbus_message_get_error_name (reply); + dbus_set_error (err, name, g_strdup ("")); + goto out; + } + /* demarshal */ + if (p[0] == '=' && p[1] == '>') + { + DBusMessageIter iter; + p += 2; + dbus_message_iter_init (reply, &iter); + dbind_any_demarshal_va (&iter, &p, args); + } + + success = TRUE; +out: + if (msg) + dbus_message_unref (msg); + + if (reply) + dbus_message_unref (reply); + + if (err == &real_err) + dbus_error_free (err); + + return success; +} + +/** + * dbind_method_call_reentrant: + * + * @cnx: A D-Bus Connection used to make the method call. + * @bus_name: The D-Bus bus name of the program where the method call should + * be made. + * @path: The D-Bus object path that should handle the method. + * @interface: The D-Bus interface used to scope the method name. + * @method: Method to be invoked. + * @opt_error: D-Bus error. + * @arg_types: Variable length arguments interleaving D-Bus argument types + * and pointers to argument data. + * + * Makes a D-Bus method call using the supplied location data, method name and + * argument data.This function is re-entrant. It continuously reads from the D-Bus + * bus and dispatches messages until a reply has been recieved. + **/ +dbus_bool_t +dbind_method_call_reentrant (DBusConnection *cnx, + const char *bus_name, + const char *path, + const char *interface, + const char *method, + DBusError *opt_error, + const char *arg_types, + ...) +{ + dbus_bool_t success = FALSE; + va_list args; + + va_start (args, arg_types); + success = dbind_method_call_reentrant_va (cnx, + bus_name, + path, + interface, + method, + opt_error, + arg_types, + args); + va_end (args); + + return success; +} + +/*---------------------------------------------------------------------------*/ + +dbus_bool_t +dbind_emit_signal_va (DBusConnection *cnx, + const char *path, + const char *interface, + const char *signal, + DBusError *opt_error, + const char *arg_types, + va_list args) +{ + dbus_bool_t success = FALSE; + DBusMessage *msg = NULL; + DBusMessageIter iter; + DBusError *err, real_err; + const char *p; + + if (opt_error) + err = opt_error; + else { + dbus_error_init (&real_err); + err = &real_err; + } + + msg = dbus_message_new_signal (path, interface, signal); + if (!msg) + goto out; + + p = arg_types; + dbus_message_iter_init_append (msg, &iter); + dbind_any_marshal_va (&iter, &p, args); + + if (!dbus_connection_send (cnx, msg, NULL)) + goto out; + + success = TRUE; +out: + + if (msg) + dbus_message_unref (msg); + + if (err == &real_err) + dbus_error_free (err); + + return success; +} + +/** + * dbind_emit_signal: + * + * @cnx: A D-Bus Connection used to make the method call. + * @path: The D-Bus object path that this signal is emitted from. + * @interface: The D-Bus interface used to scope the method name. + * @signal: Name of signal to emit. + * @opt_error: D-Bus error. + * @arg_types: Variable length arguments interleaving D-Bus argument types + * and pointers to argument data. + * + * Emits a D-Bus signal using the supplied signal name and argument data. + **/ +dbus_bool_t +dbind_emit_signal (DBusConnection *cnx, + const char *path, + const char *interface, + const char *signal, + DBusError *opt_error, + const char *arg_types, + ...) +{ + dbus_bool_t success = FALSE; + va_list args; + + va_start (args, arg_types); + success = dbind_emit_signal_va (cnx, path, interface, signal, opt_error, arg_types, args); + va_end (args); + + return success; +} + +/*END------------------------------------------------------------------------*/ diff --git a/dbind/dbind.h b/dbind/dbind.h new file mode 100644 index 0000000..3a8b209 --- /dev/null +++ b/dbind/dbind.h @@ -0,0 +1,49 @@ +#ifndef _DBIND_H_ +#define _DBIND_H_ + +#define DBUS_API_SUBJECT_TO_CHANGE +#include +#include + +DBusMessage * +dbind_send_and_allow_reentry (DBusConnection *bus, DBusMessage *message, DBusError *error); + +dbus_bool_t +dbind_method_call_reentrant_va (DBusConnection *cnx, + const char *bus_name, + const char *path, + const char *interface, + const char *method, + DBusError *opt_error, + const char *arg_types, + va_list args); + +dbus_bool_t +dbind_method_call_reentrant (DBusConnection *cnx, + const char *bus_name, + const char *path, + const char *interface, + const char *method, + DBusError *opt_error, + const char *arg_types, + ...); + +dbus_bool_t +dbind_emit_signal_va (DBusConnection *cnx, + const char *path, + const char *interface, + const char *signal, + DBusError *opt_error, + const char *arg_types, + va_list args); + +dbus_bool_t +dbind_emit_signal (DBusConnection *cnx, + const char *path, + const char *interface, + const char *signal, + DBusError *opt_error, + const char *arg_types, + ...); + +#endif /* _DBIND_H_ */ diff --git a/dbind/dbtest.c b/dbind/dbtest.c new file mode 100644 index 0000000..3ff4ddc --- /dev/null +++ b/dbind/dbtest.c @@ -0,0 +1,404 @@ +#include +#include +#include +#include + +/* Wow! dbus is unpleasant to use */ + +#define DESKICE_PATH "/Novell/ICEDesktop/Daemon" +#define DESKICE_NAMESPACE "Novell.ICEDesktop.Daemon" + +void marshal (DBusMessage *msg, char *type, void *ptr) +{ + DBusMessageIter iter; + + dbus_message_iter_init_append (msg, &iter); + dbind_any_marshal (&iter, &type, &ptr); +} + +void demarshal (DBusMessage *msg, char *type, void *ptr) +{ + DBusMessageIter iter; + + if (!dbus_message_iter_init (msg, &iter)) + fprintf (stderr, "no data in msg\n"); + else + dbind_any_demarshal (&iter, &type, &ptr); +} + +#if 0 +dbus_bool_t dbus_message_marshal (DBusMessage *msg, + char **marshalled_data_p, + int *len_p); + +void dump_msg (DBusMessage *msg) +{ + char *data = NULL; + int len, i, j; + + dbus_message_marshal (msg, &data, &len); + for (i = 0; i < (len+15)/16; i++) { + fprintf (stderr, "%4.d | ", i * 16); + for (j = 0; j < 16; j++) { + unsigned char c = (i*16+j <= len) ? data[i*16+j] : 0; + fprintf (stderr, "0x%.2x ", c); + } + fprintf (stderr, " | "); + for (j = 0; j < 16; j++) { + char c = (i*16+j <= len) ? data[i*16+j] : '\0'; + fprintf (stderr, "%c", g_ascii_isprint (c) ? c : '.'); + } + } +} +#endif + +void test_simple () +{ + dbus_int32_t v1, v2; + DBusMessage *msg; + + msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + v1 = 42; + marshal (msg, "i", &v1); + demarshal (msg, "i", &v2); + g_assert (v2 == 42); + g_assert (v1 == v2); + + dbind_any_free ("i", &v2); /* nop */ + dbus_message_unref (msg); + + fprintf (stderr, "simple ok\n"); +} + +void test_array () +{ + GArray *a1, *a2; + DBusMessage *msg; + + /* pod types */ + a1 = g_array_new (FALSE, FALSE, sizeof (dbus_int32_t)); + g_array_set_size (a1, 4); + g_array_index (a1, dbus_int32_t, 0) = 42; + g_array_index (a1, dbus_int32_t, 1) = 17; + g_array_index (a1, dbus_int32_t, 2) = 26; + g_array_index (a1, dbus_int32_t, 3) = 38; + + msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + marshal (msg, "ai", &a1); + demarshal (msg, "ai", &a2); + + g_assert (a2 != NULL); + g_assert (a2->len == 4); + g_assert (g_array_index (a2, dbus_int32_t, 0) == 42); + g_assert (g_array_index (a2, dbus_int32_t, 1) == 17); + g_assert (g_array_index (a2, dbus_int32_t, 2) == 26); + g_assert (g_array_index (a2, dbus_int32_t, 3) == 38); + g_array_free (a1, TRUE); + + dbind_any_free ("ai", &a2); + dbus_message_unref (msg); + + fprintf (stderr, "array ok\n"); +} + +/* this taught me that the struct type is a mis-nomer, + it is generated by brackets */ +void test_struct_native () +{ + DBusMessage *msg; + DBusMessageIter iter, arr, str; + + /* manually create ar(ss) */ + msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + + dbus_message_iter_init_append (msg, &iter); + + dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ss)", &arr); + { + char *foo; + dbus_message_iter_open_container (&arr, DBUS_TYPE_STRUCT, NULL, &str); + + foo = "foo"; + dbus_message_iter_append_basic (&str, DBUS_TYPE_STRING, &foo); + foo = "baa"; + dbus_message_iter_append_basic (&str, DBUS_TYPE_STRING, &foo); + + dbus_message_iter_close_container (&arr, &str); + } + dbus_message_iter_close_container (&iter, &arr); + + fprintf (stderr, "native struct marshalling ok\n"); + + dbus_message_unref (msg); +} + + +void test_struct_simple () +{ + typedef struct { + char *foo; + char *baa; + char *baz; + } FooBaa; + GArray *a1 = NULL, *a2 = NULL; + DBusMessage *msg; + + a1 = g_array_new (FALSE, FALSE, sizeof (FooBaa)); + g_array_set_size (a1, 2); + g_array_index (a1, FooBaa, 0).foo = "foo"; + g_array_index (a1, FooBaa, 0).baa = "baa"; + g_array_index (a1, FooBaa, 0).baz = "baz"; + g_array_index (a1, FooBaa, 1).foo = "Foo"; + g_array_index (a1, FooBaa, 1).baa = "baA"; + g_array_index (a1, FooBaa, 1).baz = "BaZ"; + + msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + marshal (msg, "a(sss)", &a1); + demarshal (msg, "a(sss)", &a2); + + g_assert (a2 != NULL); + g_assert (a2 != a1); + g_assert (a2->len == 2); + g_assert (!strcmp (g_array_index (a2, FooBaa, 0).foo, "foo")); + g_assert (!strcmp (g_array_index (a2, FooBaa, 0).baa, "baa")); + g_assert (!strcmp (g_array_index (a2, FooBaa, 0).baz, "baz")); + g_assert (!strcmp (g_array_index (a2, FooBaa, 1).foo, "Foo")); + g_assert (!strcmp (g_array_index (a2, FooBaa, 1).baa, "baA")); + g_assert (!strcmp (g_array_index (a2, FooBaa, 1).baz, "BaZ")); + + fprintf (stderr, "simple struct ok\n"); + + dbind_any_free ("a(sss)", &a2); + dbus_message_unref (msg); +} + +void test_struct_complex () +{ + typedef struct { + dbus_int32_t x, y; + } Point; + typedef struct { + unsigned char pad1; + double val; + Point tl, br; + char pad2; + char *name; + } Complex; +#define TYPEOF_POINT \ + DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ + DBUS_TYPE_INT32_AS_STRING \ + DBUS_TYPE_INT32_AS_STRING \ + DBUS_STRUCT_END_CHAR_AS_STRING +#define TYPEOF_COMPLEX \ + DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ + DBUS_TYPE_BYTE_AS_STRING \ + DBUS_TYPE_DOUBLE_AS_STRING \ + TYPEOF_POINT \ + TYPEOF_POINT \ + DBUS_TYPE_BYTE_AS_STRING \ + DBUS_TYPE_STRING_AS_STRING \ + DBUS_STRUCT_END_CHAR_AS_STRING + + + DBusMessage *msg; + Complex c1, c2; + + memset (&c1, 0, sizeof (c1)); + memset (&c2, 0, sizeof (c2)); + + c1.pad1 = 2; + c1.val = 0.1327569; + c1.tl.x = 1; + c1.tl.y = 17; + c1.br.x = 2587; + c1.br.y = -1; + c1.pad2 = 1; + c1.name = "stroustrup"; + + msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + marshal (msg, TYPEOF_COMPLEX, &c1); + demarshal (msg, TYPEOF_COMPLEX, &c2); + + g_assert (c2.pad1 == 2); + g_assert (c2.val == c1.val); + g_assert (c2.val != 0); + g_assert (c2.tl.x == 1); + g_assert (c2.tl.y == 17); + g_assert (c2.br.x == 2587); + g_assert (c2.br.y == -1); + g_assert (c2.pad2 == 1); + g_assert (!strcmp (c1.name, "stroustrup")); + + fprintf (stderr, "complex struct ok\n"); + + dbind_any_free (TYPEOF_COMPLEX, &c2); + dbus_message_unref (msg); +} + +void test_struct_with_array () +{ + typedef struct { + GArray *vals; + unsigned char pad1; + } ArrayStruct; +#define TYPEOF_ARRAYSTRUCT \ + DBUS_TYPE_ARRAY_AS_STRING \ + DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ + DBUS_TYPE_ARRAY_AS_STRING \ + DBUS_TYPE_UINT32_AS_STRING \ + DBUS_TYPE_BYTE_AS_STRING \ + DBUS_STRUCT_END_CHAR_AS_STRING + + + DBusMessage *msg; + GArray *a1, *a2; + ArrayStruct *p, *q; + + + a1 = g_array_new (FALSE, FALSE, sizeof (ArrayStruct)); + g_array_set_size (a1, 2); + p = &g_array_index (a1, ArrayStruct, 0); + p[0].vals = g_array_new (FALSE, FALSE, sizeof (dbus_uint32_t)); + g_array_set_size (p[0].vals, 2); + g_array_index (p[0].vals, dbus_uint32_t, 0) = 1; + g_array_index (p[0].vals, dbus_uint32_t, 1) = 1000; + p[0].pad1 = 2; + p[1].vals = g_array_new (FALSE, FALSE, sizeof (dbus_uint32_t)); + g_array_set_size (p[1].vals, 2); + g_array_index (p[1].vals, dbus_uint32_t, 0) = 1000000; + g_array_index (p[1].vals, dbus_uint32_t, 1) = 1000000000; + p[1].pad1 = 8; + + msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + marshal (msg, TYPEOF_ARRAYSTRUCT, &a1); + demarshal (msg, TYPEOF_ARRAYSTRUCT, &a2); + + q = &g_array_index (a2, ArrayStruct, 0); + g_assert (p[0].pad1 == 2); + g_assert (g_array_index (p[1].vals, dbus_uint32_t, 1) == 1000000000); + + fprintf (stderr, "struct with array ok\n"); + + dbind_any_free (TYPEOF_ARRAYSTRUCT, &a2); + dbus_message_unref (msg); + g_array_free (p[0].vals, TRUE); + g_array_free (p[1].vals, TRUE); +} + +void test_twovals () +{ + typedef struct { + dbus_int32_t v1; + dbus_int32_t v2; + } TwoVal; +#define TYPEOF_TWOVAL \ + DBUS_TYPE_INT32_AS_STRING \ + DBUS_TYPE_INT32_AS_STRING \ + + DBusMessage *msg; + DBusMessageIter iter; + TwoVal i, o; + char *type_twoval = TYPEOF_TWOVAL; + char *type; + void *ptr; + + msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + i.v1 = 42; + i.v2 = 1764; + dbus_message_iter_init_append (msg, &iter); + type = type_twoval; + ptr = &i; + dbind_any_marshal (&iter, &type, &ptr); + dbind_any_marshal (&iter, &type, &ptr); + dbus_message_iter_init (msg, &iter); + type = type_twoval; + ptr = &o; + dbind_any_demarshal (&iter, &type, &ptr); + dbind_any_demarshal (&iter, &type, &ptr); + g_assert (o.v1 == 42); + g_assert (o.v2 == 1764); + g_assert (i.v1 == o.v1); + g_assert (i.v2 == o.v2); + + dbind_any_free ("ii", &o); /* nop */ + dbus_message_unref (msg); + + fprintf (stderr, "two-val ok\n"); +} + +void test_marshalling () +{ + test_simple (); + test_array (); + test_struct_native (); + test_struct_simple (); + test_struct_complex (); + test_struct_with_array (); + test_twovals (); + + fprintf (stderr, "Marshalling ok\n"); +} + +void test_teamspaces (DBusConnection *bus) +{ + GArray *spaces; + DBusError error; + int i; + typedef struct { + char *name; + char *id; + char *url; + } TeamSpace; + + dbus_error_init (&error); + if (!dbind_method_call_reentrant (bus, + NULL, + DESKICE_PATH, + DESKICE_NAMESPACE, + "GetTeamList", + &error, + "=>a(sss)", + &spaces)) { + fprintf (stderr, "Error getting team spaces %s: %s\n", + error.name, error.message); + dbus_error_free (&error); + return; + } + + if (!spaces) { + fprintf (stderr, "no teamspaces\n"); + return; + } + fprintf (stderr, "%d teamspace(s)\n", spaces->len); + for (i = 0; i < spaces->len; i++) { + TeamSpace *space = &g_array_index (spaces, TeamSpace, i); + fprintf (stderr, "\t%d: %s, %s, %s\n", i, space->name, space->id, space->url); + } + + dbind_any_free_ptr ("a(sss)", spaces); +} + +void test_helpers () +{ + dbind_find_c_alignment ("(sss)"); + dbind_find_c_alignment ("a(sss)"); + dbind_find_c_alignment ("(s(s)yd(d)s)"); + dbind_find_c_alignment ("a{ss}"); + fprintf (stderr, "helpers passed\n"); +} + +int main (int argc, char **argv) +{ + DBusConnection *bus; + DBusError err; + + dbus_error_init (&err); + + bus = dbus_bus_get (DBUS_BUS_SESSION, &err); + + test_helpers (); + test_marshalling (); + test_teamspaces (bus); + + return 0; +} diff --git a/xml/Makefile.am b/xml/Makefile.am index c56e7e0..ad5a8f0 100644 --- a/xml/Makefile.am +++ b/xml/Makefile.am @@ -29,8 +29,10 @@ CLEANFILES = \ introspection.h \ Processed.xml -BUILT_SOURCES = spec.xml -CLEANFILES = spec.xml +#BUILT_SOURCES = spec.xml +#CLEANFILES += spec.xml + +XML_SPEC = $(filter %.xml,$(EXTRA_DIST)) spec.xml: $(XML_SPEC) xsltproc --xinclude $(top_srcdir)/tools/identity.xsl Accessibility.xml >spec.xml -- 2.7.4