diff options
Diffstat (limited to 'atk/atkobject.c')
-rw-r--r-- | atk/atkobject.c | 1514 |
1 files changed, 1514 insertions, 0 deletions
diff --git a/atk/atkobject.c b/atk/atkobject.c new file mode 100644 index 0000000000..7ece1754f5 --- /dev/null +++ b/atk/atkobject.c @@ -0,0 +1,1514 @@ +/* ATK - Accessibility Toolkit + * Copyright 2001 Sun Microsystems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "config.h" + +#include <string.h> +#include <locale.h> + +#include <glib-object.h> +#include <glib/gi18n-lib.h> + +#include "atk.h" +#include "atkmarshal.h" +#include "atkprivate.h" + +/** + * SECTION:atkobject + * @Short_description: The base object class for the Accessibility Toolkit API. + * @Title:AtkObject + * + * This class is the primary class for accessibility support via the + * Accessibility ToolKit (ATK). Objects which are instances of + * #AtkObject (or instances of AtkObject-derived types) are queried + * for properties which relate basic (and generic) properties of a UI + * component such as name and description. Instances of #AtkObject + * may also be queried as to whether they implement other ATK + * interfaces (e.g. #AtkAction, #AtkComponent, etc.), as appropriate + * to the role which a given UI component plays in a user interface. + * + * All UI components in an application which provide useful + * information or services to the user must provide corresponding + * #AtkObject instances on request (in GTK+, for instance, usually on + * a call to #gtk_widget_get_accessible ()), either via ATK support + * built into the toolkit for the widget class or ancestor class, or + * in the case of custom widgets, if the inherited #AtkObject + * implementation is insufficient, via instances of a new #AtkObject + * subclass. + * + * See also: #AtkObjectFactory, #AtkRegistry. (GTK+ users see also + * #GtkAccessible). + * + */ + +static GPtrArray *role_names = NULL; + +enum +{ + PROP_0, /* gobject convention */ + + PROP_NAME, + PROP_DESCRIPTION, + PROP_PARENT, /* ancestry has changed */ + PROP_ROLE, + PROP_LAYER, + PROP_MDI_ZORDER, + PROP_TABLE_SUMMARY, + PROP_TABLE_CAPTION_OBJECT, + PROP_HYPERTEXT_NUM_LINKS, + PROP_ACCESSIBLE_ID, + PROP_LAST /* gobject convention */ +}; + +enum { + CHILDREN_CHANGED, + PROPERTY_CHANGE, + STATE_CHANGE, + VISIBLE_DATA_CHANGED, + ACTIVE_DESCENDANT_CHANGED, + + LAST_SIGNAL +}; + +/* These are listed here for extraction by intltool */ +#if 0 + N_("invalid") + N_("accelerator label") + N_("alert") + N_("animation") + N_("arrow") + N_("calendar") + N_("canvas") + N_("check box") + N_("check menu item") + N_("color chooser") + N_("column header") + N_("combo box") + N_("dateeditor") + N_("desktop icon") + N_("desktop frame") + N_("dial") + N_("dialog") + N_("directory pane") + N_("drawing area") + N_("file chooser") + N_("filler") + /* I know it looks wrong but that is what Java returns */ + N_("fontchooser") + N_("frame") + N_("glass pane") + N_("html container") + N_("icon") + N_("image") + N_("internal frame") + N_("label") + N_("layered pane") + N_("list") + N_("list item") + N_("menu") + N_("menu bar") + N_("menu item") + N_("option pane") + N_("page tab") + N_("page tab list") + N_("panel") + N_("password text") + N_("popup menu") + N_("progress bar") + N_("push button") + N_("radio button") + N_("radio menu item") + N_("root pane") + N_("row header") + N_("scroll bar") + N_("scroll pane") + N_("separator") + N_("slider") + N_("split pane") + N_("spin button") + N_("statusbar") + N_("table") + N_("table cell") + N_("table column header") + N_("table row header") + N_("tear off menu item") + N_("terminal") + N_("text") + N_("toggle button") + N_("tool bar") + N_("tool tip") + N_("tree") + N_("tree table") + N_("unknown") + N_("viewport") + N_("window") + N_("header") + N_("footer") + N_("paragraph") + N_("ruler") + N_("application") + N_("autocomplete") + N_("edit bar") + N_("embedded component") + N_("entry") + N_("chart") + N_("caption") + N_("document frame") + N_("heading") + N_("page") + N_("section") + N_("redundant object") + N_("form") + N_("link") + N_("input method window") + N_("table row") + N_("tree item") + N_("document spreadsheet") + N_("document presentation") + N_("document text") + N_("document web") + N_("document email") + N_("comment") + N_("list box") + N_("grouping") + N_("image map") + N_("notification") + N_("info bar") + N_("level bar") + N_("title bar") + N_("block quote") + N_("audio") + N_("video") + N_("definition") + N_("article") + N_("landmark") + N_("log") + N_("marquee") + N_("math") + N_("rating") + N_("timer") + N_("description list") + N_("description term") + N_("description value") +#endif /* 0 */ + +typedef struct { + gchar *accessible_id; +} AtkObjectPrivate; + +static gint AtkObject_private_offset; + +static void atk_object_class_init (AtkObjectClass *klass); +static void atk_object_init (AtkObject *accessible, + AtkObjectClass *klass); +static AtkRelationSet* atk_object_real_ref_relation_set + (AtkObject *accessible); +static void atk_object_real_initialize (AtkObject *accessible, + gpointer data); +static void atk_object_real_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void atk_object_real_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void atk_object_finalize (GObject *object); +static const gchar* atk_object_real_get_name (AtkObject *object); +static const gchar* atk_object_real_get_description + (AtkObject *object); +static AtkObject* atk_object_real_get_parent (AtkObject *object); +static AtkRole atk_object_real_get_role (AtkObject *object); +static AtkLayer atk_object_real_get_layer (AtkObject *object); +static AtkStateSet* atk_object_real_ref_state_set + (AtkObject *object); +static void atk_object_real_set_name (AtkObject *object, + const gchar *name); +static void atk_object_real_set_description + (AtkObject *object, + const gchar *description); +static void atk_object_real_set_parent (AtkObject *object, + AtkObject *parent); +static void atk_object_real_set_role (AtkObject *object, + AtkRole role); +static void atk_object_notify (GObject *obj, + GParamSpec *pspec); +static const gchar* atk_object_real_get_object_locale + (AtkObject *object); + +static guint atk_object_signals[LAST_SIGNAL] = { 0, }; + +static gpointer parent_class = NULL; + +static const gchar* const atk_object_name_property_name = "accessible-name"; +static const gchar* const atk_object_name_property_description = "accessible-description"; +static const gchar* const atk_object_name_property_parent = "accessible-parent"; +static const gchar* const atk_object_name_property_role = "accessible-role"; +static const gchar* const atk_object_name_property_component_layer = "accessible-component-layer"; +static const gchar* const atk_object_name_property_component_mdi_zorder = "accessible-component-mdi-zorder"; +static const gchar* const atk_object_name_property_table_summary = "accessible-table-summary"; +static const gchar* const atk_object_name_property_table_caption_object = "accessible-table-caption-object"; +static const gchar* const atk_object_name_property_hypertext_num_links = "accessible-hypertext-nlinks"; + +static void +initialize_role_names () +{ + GTypeClass *enum_class; + GEnumValue *enum_value; + int i; + gchar *role_name = NULL; + + if (role_names) + return; + + role_names = g_ptr_array_new (); + enum_class = g_type_class_ref (ATK_TYPE_ROLE); + if (!G_IS_ENUM_CLASS(enum_class)) + return; + + for (i = 0; i < ATK_ROLE_LAST_DEFINED; i++) + { + enum_value = g_enum_get_value (G_ENUM_CLASS (enum_class), i); + role_name = g_strdup (enum_value->value_nick); + // We want the role names to be in the format "check button" and not "check-button" + _compact_name (role_name); + g_ptr_array_add (role_names, role_name); + } + + g_type_class_unref (enum_class); + +} + +GType +atk_object_get_type (void) +{ + static GType type = 0; + + if (!type) + { + static const GTypeInfo typeInfo = + { + sizeof (AtkObjectClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) atk_object_class_init, + (GClassFinalizeFunc) NULL, + NULL, + sizeof (AtkObject), + 0, + (GInstanceInitFunc) atk_object_init, + } ; + type = g_type_register_static (G_TYPE_OBJECT, "AtkObject", &typeInfo, 0) ; + + AtkObject_private_offset = + g_type_add_instance_private (type, sizeof (AtkObjectPrivate)); + } + return type; +} + +static inline gpointer +atk_object_get_instance_private (AtkObject *self) +{ + return (G_STRUCT_MEMBER_P (self, AtkObject_private_offset)); +} + +static void +atk_object_class_init (AtkObjectClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + if (AtkObject_private_offset != 0) + g_type_class_adjust_private_offset (klass, &AtkObject_private_offset); + + gobject_class->set_property = atk_object_real_set_property; + gobject_class->get_property = atk_object_real_get_property; + gobject_class->finalize = atk_object_finalize; + gobject_class->notify = atk_object_notify; + + klass->get_name = atk_object_real_get_name; + klass->get_description = atk_object_real_get_description; + klass->get_parent = atk_object_real_get_parent; + klass->get_n_children = NULL; + klass->ref_child = NULL; + klass->get_index_in_parent = NULL; + klass->ref_relation_set = atk_object_real_ref_relation_set; + klass->get_role = atk_object_real_get_role; + klass->get_layer = atk_object_real_get_layer; + klass->get_mdi_zorder = NULL; + klass->initialize = atk_object_real_initialize; + klass->ref_state_set = atk_object_real_ref_state_set; + klass->set_name = atk_object_real_set_name; + klass->set_description = atk_object_real_set_description; + klass->set_parent = atk_object_real_set_parent; + klass->set_role = atk_object_real_set_role; + klass->get_object_locale = atk_object_real_get_object_locale; + + /* + * We do not define default signal handlers here + */ + klass->children_changed = NULL; + klass->focus_event = NULL; + klass->property_change = NULL; + klass->visible_data_changed = NULL; + klass->active_descendant_changed = NULL; + + _gettext_initialization (); + + g_object_class_install_property (gobject_class, + PROP_NAME, + g_param_spec_string (atk_object_name_property_name, + _("Accessible Name"), + _("Object instance’s name formatted for assistive technology access"), + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_DESCRIPTION, + g_param_spec_string (atk_object_name_property_description, + _("Accessible Description"), + _("Description of an object, formatted for assistive technology access"), + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_PARENT, + g_param_spec_object (atk_object_name_property_parent, + _("Accessible Parent"), + _("Parent of the current accessible as returned by atk_object_get_parent()"), + ATK_TYPE_OBJECT, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_ROLE, + g_param_spec_enum (atk_object_name_property_role, + _("Accessible Role"), + _("The accessible role of this object"), + ATK_TYPE_ROLE, + ATK_ROLE_UNKNOWN, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_LAYER, + g_param_spec_int (atk_object_name_property_component_layer, + _("Accessible Layer"), + _("The accessible layer of this object"), + 0, + G_MAXINT, + 0, + G_PARAM_READABLE)); + g_object_class_install_property (gobject_class, + PROP_MDI_ZORDER, + g_param_spec_int (atk_object_name_property_component_mdi_zorder, + _("Accessible MDI Value"), + _("The accessible MDI value of this object"), + G_MININT, + G_MAXINT, + G_MININT, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_TABLE_SUMMARY, + g_param_spec_object (atk_object_name_property_table_summary, + _("Accessible Table Summary"), + _("Is used to notify that the table summary has changed"), + ATK_TYPE_OBJECT, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_TABLE_CAPTION_OBJECT, + g_param_spec_object (atk_object_name_property_table_caption_object, + _("Accessible Table Caption Object"), + _("Is used to notify that the table caption has changed"), + ATK_TYPE_OBJECT, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_HYPERTEXT_NUM_LINKS, + g_param_spec_int (atk_object_name_property_hypertext_num_links, + _("Number of Accessible Hypertext Links"), + _("The number of links which the current AtkHypertext has"), + 0, + G_MAXINT, + 0, + G_PARAM_READABLE)); + + /** + * AtkObject::children-changed: + * @atkobject: the object which received the signal. + * @arg1: The index of the added or removed child. The value can be + * -1. This is used if the value is not known by the implementor + * when the child is added/removed or irrelevant. + * @arg2: (type AtkObject): A gpointer to the child AtkObject which was added or + * removed. If the child was removed, it is possible that it is not + * available for the implementor. In that case this pointer can be + * NULL. + * + * The signal "children-changed" is emitted when a child is added or + * removed form an object. It supports two details: "add" and + * "remove" + */ + atk_object_signals[CHILDREN_CHANGED] = + g_signal_new ("children_changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (AtkObjectClass, children_changed), + NULL, NULL, + g_cclosure_marshal_VOID__UINT_POINTER, + G_TYPE_NONE, + 2, G_TYPE_UINT, G_TYPE_POINTER); + + /** + * AtkObject::property-change: + * @atkobject: the object which received the signal. + * @arg1: (type AtkPropertyValues): an #AtkPropertyValues containing the new + * value of the property which changed. + * + * The signal "property-change" is emitted when an object's property + * value changes. @arg1 contains an #AtkPropertyValues with the name + * and the new value of the property whose value has changed. Note + * that, as with GObject notify, getting this signal does not + * guarantee that the value of the property has actually changed; it + * may also be emitted when the setter of the property is called to + * reinstate the previous value. + * + * Toolkit implementor note: ATK implementors should use + * g_object_notify() to emit property-changed + * notifications. #AtkObject::property-changed is needed by the + * implementation of atk_add_global_event_listener() because GObject + * notify doesn't support emission hooks. + */ + atk_object_signals[PROPERTY_CHANGE] = + g_signal_new ("property_change", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (AtkObjectClass, property_change), + (GSignalAccumulator) NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + + /** + * AtkObject::state-change: + * @atkobject: the object which received the signal. + * @arg1: The name of the state which has changed + * @arg2: A boolean which indicates whether the state has been set or unset. + * + * The "state-change" signal is emitted when an object's state + * changes. The detail value identifies the state type which has + * changed. + */ + atk_object_signals[STATE_CHANGE] = + g_signal_new ("state_change", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (AtkObjectClass, state_change), + (GSignalAccumulator) NULL, NULL, + atk_marshal_VOID__STRING_BOOLEAN, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_BOOLEAN); + + /** + * AtkObject::visible-data-changed: + * @atkobject: the object which received the signal. + * + * The "visible-data-changed" signal is emitted when the visual + * appearance of the object changed. + */ + atk_object_signals[VISIBLE_DATA_CHANGED] = + g_signal_new ("visible_data_changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (AtkObjectClass, visible_data_changed), + (GSignalAccumulator) NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * AtkObject::active-descendant-changed: + * @atkobject: the object which received the signal. + * @arg1: (type AtkObject): the newly focused object. + * + * The "active-descendant-changed" signal is emitted by an object + * which has the state ATK_STATE_MANAGES_DESCENDANTS when the focus + * object in the object changes. For instance, a table will emit the + * signal when the cell in the table which has focus changes. + */ + atk_object_signals[ACTIVE_DESCENDANT_CHANGED] = + g_signal_new ("active_descendant_changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (AtkObjectClass, active_descendant_changed), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, + 1, G_TYPE_POINTER); +} + +static void +atk_object_init (AtkObject *accessible, + AtkObjectClass *klass) +{ + AtkObjectPrivate *private = atk_object_get_instance_private (accessible); + + accessible->name = NULL; + accessible->description = NULL; + accessible->accessible_parent = NULL; + accessible->relation_set = atk_relation_set_new(); + accessible->role = ATK_ROLE_UNKNOWN; + private->accessible_id = NULL; +} + +GType +atk_implementor_get_type (void) +{ + static GType type = 0; + + if (!type) + { + static const GTypeInfo typeInfo = + { + sizeof (AtkImplementorIface), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + } ; + + type = g_type_register_static (G_TYPE_INTERFACE, "AtkImplementorIface", &typeInfo, 0) ; + } + + return type; +} + +/** + * atk_object_get_name: + * @accessible: an #AtkObject + * + * Gets the accessible name of the accessible. + * + * Returns: a character string representing the accessible name of the object. + **/ +const gchar* +atk_object_get_name (AtkObject *accessible) +{ + AtkObjectClass *klass; + + g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->get_name) + return (klass->get_name) (accessible); + else + return NULL; +} + +/** + * atk_object_get_description: + * @accessible: an #AtkObject + * + * Gets the accessible description of the accessible. + * + * Returns: a character string representing the accessible description + * of the accessible. + * + **/ +const gchar* +atk_object_get_description (AtkObject *accessible) +{ + AtkObjectClass *klass; + + g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->get_description) + return (klass->get_description) (accessible); + else + return NULL; +} + +/** + * atk_object_get_parent: + * @accessible: an #AtkObject + * + * Gets the accessible parent of the accessible. By default this is + * the one assigned with atk_object_set_parent(), but it is assumed + * that ATK implementors have ways to get the parent of the object + * without the need of assigning it manually with + * atk_object_set_parent(), and will return it with this method. + * + * If you are only interested on the parent assigned with + * atk_object_set_parent(), use atk_object_peek_parent(). + * + * Returns: (transfer none): an #AtkObject representing the accessible + * parent of the accessible + **/ +AtkObject* +atk_object_get_parent (AtkObject *accessible) +{ + AtkObjectClass *klass; + + g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->get_parent) + return (klass->get_parent) (accessible); + else + return NULL; +} + +/** + * atk_object_peek_parent: + * @accessible: an #AtkObject + * + * Gets the accessible parent of the accessible, if it has been + * manually assigned with atk_object_set_parent. Otherwise, this + * function returns %NULL. + * + * This method is intended as an utility for ATK implementors, and not + * to be exposed to accessible tools. See atk_object_get_parent() for + * further reference. + * + * Returns: (transfer none): an #AtkObject representing the accessible + * parent of the accessible if assigned + **/ +AtkObject* +atk_object_peek_parent (AtkObject *accessible) +{ + return accessible->accessible_parent; +} + +/** + * atk_object_get_n_accessible_children: + * @accessible: an #AtkObject + * + * Gets the number of accessible children of the accessible. + * + * Returns: an integer representing the number of accessible children + * of the accessible. + **/ +gint +atk_object_get_n_accessible_children (AtkObject *accessible) +{ + AtkObjectClass *klass; + + g_return_val_if_fail (ATK_IS_OBJECT (accessible), 0); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->get_n_children) + return (klass->get_n_children) (accessible); + else + return 0; +} + +/** + * atk_object_ref_accessible_child: + * @accessible: an #AtkObject + * @i: a gint representing the position of the child, starting from 0 + * + * Gets a reference to the specified accessible child of the object. + * The accessible children are 0-based so the first accessible child is + * at index 0, the second at index 1 and so on. + * + * Returns: (transfer full): an #AtkObject representing the specified + * accessible child of the accessible. + **/ +AtkObject* +atk_object_ref_accessible_child (AtkObject *accessible, + gint i) +{ + AtkObjectClass *klass; + + g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->ref_child) + return (klass->ref_child) (accessible, i); + else + return NULL; +} + +/** + * atk_object_ref_relation_set: + * @accessible: an #AtkObject + * + * Gets the #AtkRelationSet associated with the object. + * + * Returns: (transfer full): an #AtkRelationSet representing the relation set + * of the object. + **/ +AtkRelationSet* +atk_object_ref_relation_set (AtkObject *accessible) +{ + AtkObjectClass *klass; + + g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->ref_relation_set) + return (klass->ref_relation_set) (accessible); + else + return NULL; +} + +/** + * atk_object_get_role: + * @accessible: an #AtkObject + * + * Gets the role of the accessible. + * + * Returns: an #AtkRole which is the role of the accessible + **/ +AtkRole +atk_object_get_role (AtkObject *accessible) +{ + AtkObjectClass *klass; + + g_return_val_if_fail (ATK_IS_OBJECT (accessible), ATK_ROLE_UNKNOWN); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->get_role) + return (klass->get_role) (accessible); + else + return ATK_ROLE_UNKNOWN; +} + +/** + * atk_object_ref_state_set: + * @accessible: an #AtkObject + * + * Gets a reference to the state set of the accessible; the caller must + * unreference it when it is no longer needed. + * + * Returns: (transfer full): a reference to an #AtkStateSet which is the state + * set of the accessible + **/ +AtkStateSet* +atk_object_ref_state_set (AtkObject *accessible) +{ + AtkObjectClass *klass; + + g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->ref_state_set) + return (klass->ref_state_set) (accessible); + else + return NULL; +} + +/** + * atk_object_get_index_in_parent: + * @accessible: an #AtkObject + * + * Gets the 0-based index of this accessible in its parent; returns -1 if the + * accessible does not have an accessible parent. + * + * Returns: an integer which is the index of the accessible in its parent + **/ +gint +atk_object_get_index_in_parent (AtkObject *accessible) +{ + AtkObjectClass *klass; + + g_return_val_if_fail (ATK_OBJECT (accessible), -1); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->get_index_in_parent) + return (klass->get_index_in_parent) (accessible); + else + return -1; +} + +/** + * atk_object_set_name: + * @accessible: an #AtkObject + * @name: a character string to be set as the accessible name + * + * Sets the accessible name of the accessible. You can't set the name + * to NULL. This is reserved for the initial value. In this aspect + * NULL is similar to ATK_ROLE_UNKNOWN. If you want to set the name to + * a empty value you can use "". + **/ +void +atk_object_set_name (AtkObject *accessible, + const gchar *name) +{ + AtkObjectClass *klass; + gboolean notify = FALSE; + + g_return_if_fail (ATK_IS_OBJECT (accessible)); + g_return_if_fail (name != NULL); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->set_name) + { + /* Do not notify for initial name setting. See bug 665870 */ + notify = (accessible->name != NULL); + + (klass->set_name) (accessible, name); + if (notify) + g_object_notify (G_OBJECT (accessible), atk_object_name_property_name); + } +} + +/** + * atk_object_set_description: + * @accessible: an #AtkObject + * @description: a character string to be set as the accessible description + * + * Sets the accessible description of the accessible. You can't set + * the description to NULL. This is reserved for the initial value. In + * this aspect NULL is similar to ATK_ROLE_UNKNOWN. If you want to set + * the name to a empty value you can use "". + **/ +void +atk_object_set_description (AtkObject *accessible, + const gchar *description) +{ + AtkObjectClass *klass; + gboolean notify = FALSE; + + g_return_if_fail (ATK_IS_OBJECT (accessible)); + g_return_if_fail (description != NULL); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->set_description) + { + /* Do not notify for initial name setting. See bug 665870 */ + notify = (accessible->description != NULL); + + (klass->set_description) (accessible, description); + if (notify) + g_object_notify (G_OBJECT (accessible), + atk_object_name_property_description); + } +} + +/** + * atk_object_set_parent: + * @accessible: an #AtkObject + * @parent: an #AtkObject to be set as the accessible parent + * + * Sets the accessible parent of the accessible. @parent can be NULL. + **/ +void +atk_object_set_parent (AtkObject *accessible, + AtkObject *parent) +{ + AtkObjectClass *klass; + + g_return_if_fail (ATK_IS_OBJECT (accessible)); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->set_parent) + { + (klass->set_parent) (accessible, parent); + g_object_notify (G_OBJECT (accessible), atk_object_name_property_parent); + } +} + +/** + * atk_object_set_role: + * @accessible: an #AtkObject + * @role: an #AtkRole to be set as the role + * + * Sets the role of the accessible. + **/ +void +atk_object_set_role (AtkObject *accessible, + AtkRole role) +{ + AtkObjectClass *klass; + AtkRole old_role; + + g_return_if_fail (ATK_IS_OBJECT (accessible)); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->set_role) + { + old_role = atk_object_get_role (accessible); + if (old_role != role) + { + (klass->set_role) (accessible, role); + if (old_role != ATK_ROLE_UNKNOWN) + /* Do not notify for initial role setting */ + g_object_notify (G_OBJECT (accessible), atk_object_name_property_role); + } + } +} + +/** + * atk_object_notify_state_change: + * @accessible: an #AtkObject + * @state: an #AtkState whose state is changed + * @value: a gboolean which indicates whether the state is being set on or off + * + * Emits a state-change signal for the specified state. + * + * Note that as a general rule when the state of an existing object changes, + * emitting a notification is expected. + **/ +void +atk_object_notify_state_change (AtkObject *accessible, + AtkState state, + gboolean value) +{ + const gchar* name; + + g_return_if_fail (ATK_IS_OBJECT (accessible)); + + name = atk_state_type_get_name (state); + g_signal_emit (accessible, atk_object_signals[STATE_CHANGE], + g_quark_from_string (name), + name, value, NULL); +} + +/** + * atk_implementor_ref_accessible: + * @implementor: The #GObject instance which should implement #AtkImplementorIface + * if a non-null return value is required. + * + * Gets a reference to an object's #AtkObject implementation, if + * the object implements #AtkObjectIface + * + * Returns: (transfer full): a reference to an object's #AtkObject + * implementation + */ +AtkObject * +atk_implementor_ref_accessible (AtkImplementor *implementor) +{ + AtkImplementorIface *iface; + AtkObject *accessible = NULL; + + g_return_val_if_fail (ATK_IS_IMPLEMENTOR (implementor), NULL); + + iface = ATK_IMPLEMENTOR_GET_IFACE (implementor); + + if (iface != NULL) + accessible = iface->ref_accessible (implementor); + + g_return_val_if_fail ((accessible != NULL), NULL); + + return accessible; +} + + +/** + * atk_object_get_attributes: + * @accessible: An #AtkObject. + * + * Get a list of properties applied to this object as a whole, as an #AtkAttributeSet consisting of + * name-value pairs. As such these attributes may be considered weakly-typed properties or annotations, + * as distinct from strongly-typed object data available via other get/set methods. + * Not all objects have explicit "name-value pair" #AtkAttributeSet properties. + * + * Since: 1.12 + * + * Returns: (transfer full): an #AtkAttributeSet consisting of all + * explicit properties/annotations applied to the object, or an empty + * set if the object has no name-value pair attributes assigned to + * it. This #atkattributeset should be freed by a call to + * atk_attribute_set_free(). + */ +AtkAttributeSet * +atk_object_get_attributes (AtkObject *accessible) +{ + AtkObjectClass *klass; + + g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->get_attributes) + return (klass->get_attributes) (accessible); + else + return NULL; + +} + +static AtkRelationSet* +atk_object_real_ref_relation_set (AtkObject *accessible) +{ + g_return_val_if_fail (accessible->relation_set, NULL); + g_object_ref (accessible->relation_set); + + return accessible->relation_set; +} + +static void +atk_object_real_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + AtkObject *accessible; + + accessible = ATK_OBJECT (object); + + switch (prop_id) + { + case PROP_NAME: + atk_object_set_name (accessible, g_value_get_string (value)); + break; + case PROP_DESCRIPTION: + atk_object_set_description (accessible, g_value_get_string (value)); + break; + case PROP_ROLE: + atk_object_set_role (accessible, g_value_get_enum (value)); + break; + case PROP_PARENT: + atk_object_set_parent (accessible, g_value_get_object (value)); + break; + case PROP_TABLE_SUMMARY: + if (ATK_IS_TABLE (accessible)) + atk_table_set_summary (ATK_TABLE (accessible), g_value_get_object (value)); + break; + case PROP_TABLE_CAPTION_OBJECT: + if (ATK_IS_TABLE (accessible)) + atk_table_set_caption (ATK_TABLE (accessible), g_value_get_object (value)); + break; + case PROP_ACCESSIBLE_ID: + atk_object_set_accessible_id (accessible, g_value_get_string (value)); + break; + default: + break; + } +} + +static void +atk_object_real_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + AtkObject *accessible; + + accessible = ATK_OBJECT (object); + + switch (prop_id) + { + case PROP_NAME: + g_value_set_string (value, atk_object_get_name (accessible)); + break; + case PROP_DESCRIPTION: + g_value_set_string (value, atk_object_get_description (accessible)); + break; + case PROP_ROLE: + g_value_set_enum (value, atk_object_get_role (accessible)); + break; + case PROP_LAYER: + if (ATK_IS_COMPONENT (accessible)) + g_value_set_int (value, atk_component_get_layer (ATK_COMPONENT (accessible))); + break; + case PROP_MDI_ZORDER: + if (ATK_IS_COMPONENT (accessible)) + g_value_set_int (value, atk_component_get_mdi_zorder (ATK_COMPONENT (accessible))); + break; + case PROP_PARENT: + g_value_set_object (value, atk_object_get_parent (accessible)); + break; + case PROP_TABLE_SUMMARY: + if (ATK_IS_TABLE (accessible)) + g_value_set_object (value, atk_table_get_summary (ATK_TABLE (accessible))); + break; + case PROP_TABLE_CAPTION_OBJECT: + if (ATK_IS_TABLE (accessible)) + g_value_set_object (value, atk_table_get_caption (ATK_TABLE (accessible))); + break; + case PROP_HYPERTEXT_NUM_LINKS: + if (ATK_IS_HYPERTEXT (accessible)) + g_value_set_int (value, atk_hypertext_get_n_links (ATK_HYPERTEXT (accessible))); + break; + case PROP_ACCESSIBLE_ID: + g_value_set_string (value, atk_object_get_accessible_id (accessible)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +atk_object_finalize (GObject *object) +{ + AtkObject *accessible; + AtkObjectPrivate *private; + + g_return_if_fail (ATK_IS_OBJECT (object)); + + accessible = ATK_OBJECT (object); + private = atk_object_get_instance_private (accessible); + + g_free (accessible->name); + g_free (accessible->description); + + /* + * Free memory allocated for relation set if it have been allocated. + */ + if (accessible->relation_set) + g_object_unref (accessible->relation_set); + + if (accessible->accessible_parent) + g_object_unref (accessible->accessible_parent); + + g_free(private->accessible_id); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static const gchar* +atk_object_real_get_name (AtkObject *object) +{ + return object->name; +} + +static const gchar* +atk_object_real_get_description (AtkObject *object) +{ + return object->description; +} + +static AtkObject* +atk_object_real_get_parent (AtkObject *object) +{ + return atk_object_peek_parent (object); +} + +static AtkRole +atk_object_real_get_role (AtkObject *object) +{ + return object->role; +} + +static AtkLayer +atk_object_real_get_layer (AtkObject *object) +{ + return object->layer; +} + +static AtkStateSet* +atk_object_real_ref_state_set (AtkObject *accessible) +{ + AtkStateSet *state_set; + AtkObject *focus_object; + + state_set = atk_state_set_new (); + + focus_object = atk_get_focus_object (); + if (focus_object == accessible) + atk_state_set_add_state (state_set, ATK_STATE_FOCUSED); + + return state_set; +} + +static void +atk_object_real_set_name (AtkObject *object, + const gchar *name) +{ + g_free (object->name); + object->name = g_strdup (name); +} + +static void +atk_object_real_set_description (AtkObject *object, + const gchar *description) +{ + g_free (object->description); + object->description = g_strdup (description); +} + +static void +atk_object_real_set_parent (AtkObject *object, + AtkObject *parent) +{ + if (object->accessible_parent) + g_object_unref (object->accessible_parent); + + object->accessible_parent = parent; + if (object->accessible_parent) + g_object_ref (object->accessible_parent); +} + +static void +atk_object_real_set_role (AtkObject *object, + AtkRole role) +{ + object->role = role; +} + +/** + * atk_object_initialize: + * @accessible: a #AtkObject + * @data: a #gpointer which identifies the object for which the AtkObject was created. + * + * This function is called when implementing subclasses of #AtkObject. + * It does initialization required for the new object. It is intended + * that this function should called only in the ..._new() functions used + * to create an instance of a subclass of #AtkObject + **/ +void +atk_object_initialize (AtkObject *accessible, + gpointer data) +{ + AtkObjectClass *klass; + + g_return_if_fail (ATK_IS_OBJECT (accessible)); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->initialize) + klass->initialize (accessible, data); +} + +/* + * This function is a signal handler for notify signal which gets emitted + * when a property changes value. + * + * It constructs an AtkPropertyValues structure and emits a "property_changed" + * signal which causes the user specified AtkPropertyChangeHandler + * to be called. + */ +static void +atk_object_notify (GObject *obj, + GParamSpec *pspec) +{ + AtkPropertyValues values = { NULL, }; + + g_value_init (&values.new_value, pspec->value_type); + g_object_get_property (obj, pspec->name, &values.new_value); + values.property_name = pspec->name; + g_signal_emit (obj, atk_object_signals[PROPERTY_CHANGE], + g_quark_from_string (pspec->name), + &values, NULL); + g_value_unset (&values.new_value); +} + +/** + * atk_role_get_name: + * @role: The #AtkRole whose name is required + * + * Gets the description string describing the #AtkRole @role. + * + * Returns: the string describing the AtkRole + */ +const gchar* +atk_role_get_name (AtkRole role) +{ + g_return_val_if_fail (role >= 0, NULL); + + if (!role_names) + initialize_role_names (); + + if (role < role_names->len) + return g_ptr_array_index (role_names, role); + + return NULL; +} + +/** + * atk_role_get_localized_name: + * @role: The #AtkRole whose localized name is required + * + * Gets the localized description string describing the #AtkRole @role. + * + * Returns: the localized string describing the AtkRole + **/ +const gchar* +atk_role_get_localized_name (AtkRole role) +{ + _gettext_initialization (); + + return dgettext (GETTEXT_PACKAGE, atk_role_get_name (role)); +} + +static const gchar* +atk_object_real_get_object_locale (AtkObject *object) +{ + return setlocale (LC_MESSAGES, NULL); +} + +/** + * atk_object_get_object_locale: + * @accessible: an #AtkObject + * + * Gets a UTF-8 string indicating the POSIX-style LC_MESSAGES locale + * of @accessible. + * + * Since: 2.8 + * + * Returns: a UTF-8 string indicating the POSIX-style LC_MESSAGES + * locale of @accessible. + **/ +const gchar* +atk_object_get_object_locale (AtkObject *accessible) +{ + AtkObjectClass *klass; + + g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL); + + klass = ATK_OBJECT_GET_CLASS (accessible); + if (klass->get_object_locale) + return (klass->get_object_locale) (accessible); + else + return NULL; +} + + +/** + * atk_role_for_name: + * @name: a string which is the (non-localized) name of an ATK role. + * + * Get the #AtkRole type corresponding to a rolew name. + * + * Returns: the #AtkRole enumerated type corresponding to the specified name, + * or #ATK_ROLE_INVALID if no matching role is found. + **/ +AtkRole +atk_role_for_name (const gchar *name) +{ + AtkRole role = ATK_ROLE_INVALID; + gint i; + + g_return_val_if_fail (name, ATK_ROLE_INVALID); + + if (!role_names) + initialize_role_names (); + + for (i = 0; i < role_names->len; i++) + { + gchar *role_name = (gchar *)g_ptr_array_index (role_names, i); + + g_return_val_if_fail (role_name, ATK_ROLE_INVALID); + + if (strcmp (name, role_name) == 0) + { + role = i; + break; + } + } + + return role; +} + +/** + * atk_object_add_relationship: + * @object: The #AtkObject to which an AtkRelation is to be added. + * @relationship: The #AtkRelationType of the relation + * @target: The #AtkObject which is to be the target of the relation. + * + * Adds a relationship of the specified type with the specified target. + * + * Returns: TRUE if the relationship is added. + **/ +gboolean +atk_object_add_relationship (AtkObject *object, + AtkRelationType relationship, + AtkObject *target) +{ + AtkObject *array[1]; + AtkRelation *relation; + + g_return_val_if_fail (ATK_IS_OBJECT (object), FALSE); + g_return_val_if_fail (ATK_IS_OBJECT (target), FALSE); + + if (atk_relation_set_contains_target (object->relation_set, + relationship, target)) + return FALSE; + + array[0] = target; + relation = atk_relation_new (array, 1, relationship); + atk_relation_set_add (object->relation_set, relation); + g_object_unref (relation); + + return TRUE; +} + +/** + * atk_object_remove_relationship: + * @object: The #AtkObject from which an AtkRelation is to be removed. + * @relationship: The #AtkRelationType of the relation + * @target: The #AtkObject which is the target of the relation to be removed. + * + * Removes a relationship of the specified type with the specified target. + * + * Returns: TRUE if the relationship is removed. + **/ +gboolean +atk_object_remove_relationship (AtkObject *object, + AtkRelationType relationship, + AtkObject *target) +{ + gboolean ret = FALSE; + AtkRelation *relation; + GPtrArray *array; + + g_return_val_if_fail (ATK_IS_OBJECT (object), FALSE); + g_return_val_if_fail (ATK_IS_OBJECT (target), FALSE); + + relation = atk_relation_set_get_relation_by_type (object->relation_set, relationship); + + if (relation) + { + ret = atk_relation_remove_target (relation, target); + array = atk_relation_get_target (relation); + if (!array || array->len == 0) + atk_relation_set_remove (object->relation_set, relation); + } + return ret; +} + +/** + * atk_object_get_accessible_id: + * @accessible: an #AtkObject + * + * Gets the accessible id of the accessible. + * + * Since: 2.34 + * + * Returns: a character string representing the accessible id of the object, or + * NULL if no such string was set. + **/ +const gchar* +atk_object_get_accessible_id (AtkObject *accessible) +{ + AtkObjectPrivate *private = atk_object_get_instance_private (accessible); + return private->accessible_id; +} + +/** + * atk_object_set_accessible_id: + * @accessible: an #AtkObject + * @name: a character string to be set as the accessible id + * + * Sets the accessible ID of the accessible. This is not meant to be presented + * to the user, but to be an ID which is stable over application development. + * Typically, this is the gtkbuilder ID. Such an ID will be available for + * instance to identify a given well-known accessible object for tailored screen + * reading, or for automatic regression testing. + * + * Since: 2.34 + **/ +void +atk_object_set_accessible_id (AtkObject *accessible, const gchar *id) +{ + AtkObjectPrivate *private = atk_object_get_instance_private (accessible); + g_free (private->accessible_id); + private->accessible_id = g_strdup (id); +} + +static void +atk_object_real_initialize (AtkObject *accessible, + gpointer data) +{ + return; +} |