2 * AT-SPI - Assistive Technology Service Provider Interface
3 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
5 * Copyright 2001, 2002 Sun Microsystems Inc.,
6 * Copyright 2001, 2002 Ximian, Inc.
7 * Copyright 2010, 2011 Novell, Inc.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
25 #include "atspi-private.h"
26 #include "atspi-accessible-private.h"
29 static gboolean enable_caching = FALSE;
30 static guint quark_locale;
33 atspi_action_interface_init (AtspiAction *action)
38 atspi_collection_interface_init (AtspiCollection *component)
43 atspi_component_interface_init (AtspiComponent *component)
48 atspi_document_interface_init (AtspiDocument *document)
53 atspi_editable_text_interface_init (AtspiEditableText *editable_text)
58 atspi_hypertext_interface_init (AtspiHypertext *hypertext)
63 atspi_image_interface_init (AtspiImage *image)
68 atspi_selection_interface_init (AtspiSelection *selection)
73 atspi_table_interface_init (AtspiTable *table)
78 atspi_table_cell_interface_init (AtspiTableCell *cell)
83 atspi_text_interface_init (AtspiText *text)
88 atspi_value_interface_init (AtspiValue *value)
92 G_DEFINE_TYPE_WITH_CODE (AtspiAccessible, atspi_accessible, ATSPI_TYPE_OBJECT,
93 G_ADD_PRIVATE (AtspiAccessible)
94 G_IMPLEMENT_INTERFACE (ATSPI_TYPE_ACTION, atspi_action_interface_init)
95 G_IMPLEMENT_INTERFACE (ATSPI_TYPE_COLLECTION, atspi_collection_interface_init)
96 G_IMPLEMENT_INTERFACE (ATSPI_TYPE_COMPONENT, atspi_component_interface_init)
97 G_IMPLEMENT_INTERFACE (ATSPI_TYPE_DOCUMENT, atspi_document_interface_init)
98 G_IMPLEMENT_INTERFACE (ATSPI_TYPE_EDITABLE_TEXT, atspi_editable_text_interface_init)
99 G_IMPLEMENT_INTERFACE (ATSPI_TYPE_HYPERTEXT, atspi_hypertext_interface_init)
100 G_IMPLEMENT_INTERFACE (ATSPI_TYPE_IMAGE, atspi_image_interface_init)
101 G_IMPLEMENT_INTERFACE (ATSPI_TYPE_SELECTION, atspi_selection_interface_init)
102 G_IMPLEMENT_INTERFACE (ATSPI_TYPE_TABLE, atspi_table_interface_init)
103 G_IMPLEMENT_INTERFACE (ATSPI_TYPE_TABLE_CELL, atspi_table_cell_interface_init)
104 G_IMPLEMENT_INTERFACE (ATSPI_TYPE_TEXT, atspi_text_interface_init)
105 G_IMPLEMENT_INTERFACE (ATSPI_TYPE_VALUE, atspi_value_interface_init))
107 #ifdef DEBUG_REF_COUNTS
108 static gint accessible_count = 0;
112 atspi_accessible_init (AtspiAccessible *accessible)
114 #ifdef DEBUG_REF_COUNTS
116 g_hash_table_insert (_atspi_get_live_refs (), accessible, NULL);
117 g_print("at-spi: init: %d objects\n", accessible_count);
120 accessible->priv = atspi_accessible_get_instance_private (accessible);
122 accessible->children = g_ptr_array_new_with_free_func (g_object_unref);
126 atspi_accessible_dispose (GObject *object)
128 AtspiAccessible *accessible = ATSPI_ACCESSIBLE (object);
130 AtspiAccessible *parent;
133 /* TODO: Only fire if object not already marked defunct */
134 memset (&e, 0, sizeof (e));
135 e.type = "object:state-changed:defunct";
136 e.source = accessible;
139 _atspi_send_event (&e);
141 g_clear_object (&accessible->states);
143 parent = accessible->accessible_parent;
146 accessible->accessible_parent = NULL;
147 if (parent->children)
148 g_ptr_array_remove (parent->children, accessible);
149 g_object_unref (parent);
152 if (accessible->children) for (i = accessible->children->len - 1; i >= 0; i--)
154 AtspiAccessible *child = g_ptr_array_index (accessible->children, i);
155 if (child && child->accessible_parent == accessible)
157 child->accessible_parent = NULL;
158 g_object_unref (accessible);
162 if (accessible->children)
164 g_ptr_array_free (accessible->children, TRUE);
165 accessible->children = NULL;
168 G_OBJECT_CLASS (atspi_accessible_parent_class) ->dispose (object);
172 atspi_accessible_finalize (GObject *object)
174 AtspiAccessible *accessible = ATSPI_ACCESSIBLE (object);
176 g_free (accessible->description);
177 g_free (accessible->name);
179 if (accessible->attributes)
180 g_hash_table_unref (accessible->attributes);
182 if (accessible->priv->cache)
183 g_hash_table_destroy (accessible->priv->cache);
185 #ifdef DEBUG_REF_COUNTS
187 g_hash_table_remove (_atspi_get_live_refs (), accessible);
188 g_print ("at-spi: finalize: %d objects\n", accessible_count);
191 G_OBJECT_CLASS (atspi_accessible_parent_class)->finalize (object);
195 atspi_accessible_class_init (AtspiAccessibleClass *klass)
197 GObjectClass *object_class = G_OBJECT_CLASS (klass);
199 object_class->dispose = atspi_accessible_dispose;
200 object_class->finalize = atspi_accessible_finalize;
202 quark_locale = g_quark_from_string ("accessible-locale");
206 * atspi_accessible_get_name:
207 * @obj: a pointer to the #AtspiAccessible object on which to operate.
209 * Gets the name of an #AtspiAccessible object.
211 * Returns: a UTF-8 string indicating the name of the #AtspiAccessible object
212 * or NULL on exception.
215 atspi_accessible_get_name (AtspiAccessible *obj, GError **error)
217 g_return_val_if_fail (obj != NULL, g_strdup (""));
218 if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_NAME))
220 if (!_atspi_dbus_get_property (obj, atspi_interface_accessible, "Name", error,
222 return g_strdup ("");
223 _atspi_accessible_add_cache (obj, ATSPI_CACHE_NAME);
225 return g_strdup (obj->name);
230 * atspi_accessible_get_unique_id:
231 * @obj: a pointer to the #AtspiAccessible object on which to operate.
233 * Gets the identificator, uniquely identifying object, or NULL if an error occured.
235 * Returns: a UTF-8 string describing the #AtspiAccessible object
236 * or NULL on exception or NULL object passed.
239 atspi_accessible_get_unique_id(AtspiAccessible *obj, GError **error)
242 g_set_error(error, ATSPI_ERROR, ATSPI_ERROR_IPC, "argument is null");
247 gchar *bus_name = atspi_accessible_get_bus_name(obj, error);
248 if (bus_name && bus_name[0]) {
249 gchar *path = atspi_accessible_get_path(obj, error);
251 id = g_strdup_printf("%s:%s", bus_name, path);
253 g_set_error(error, ATSPI_ERROR, ATSPI_ERROR_IPC, "failed to get path");
257 g_set_error(error, ATSPI_ERROR, ATSPI_ERROR_IPC, "failed to get bus name");
263 * atspi_accessible_get_bus_name:
264 * @obj: a pointer to the #AtspiAccessible object on which to operate.
266 * Gets the bus name, where object belongs.
268 * Returns: a UTF-8 string describing the #AtspiAccessible object's
269 * bus name or empty string on exception or NULL object passed.
272 atspi_accessible_get_bus_name(AtspiAccessible *obj, GError **error)
274 if (!obj || !obj->parent.app)
276 return g_strdup (obj->parent.app->bus_name);
280 * atspi_accessible_get_path:
281 * @obj: a pointer to the #AtspiAccessible object on which to operate.
283 * Gets the path, uniquely identifying object over its bus name.
285 * Returns: a UTF-8 string describing the #AtspiAccessible object
286 * or empty string on exception or NULL object passed.
289 atspi_accessible_get_path(AtspiAccessible *obj, GError **error)
291 static const char *prefix = "/org/a11y/atspi/accessible/";
292 static int prefix_len = 27;
296 AtspiObject *o = ATSPI_OBJECT (obj);
299 if (strncmp(o->path, prefix, prefix_len) == 0)
300 return g_strdup(o->path + prefix_len);
301 return g_strdup (o->path);
305 * atspi_accessible_get_navigable_at_point:
306 * @root: a pointer to the #AtspiAccessible to start search from.
307 * @x: a #gint specifying the x coordinate of the point in question.
308 * @y: a #gint specifying the y coordinate of the point in question.
309 * @ctype: the coordinate system of the point (@x, @y)
310 * (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN).
312 * Finds the accessible element closest to user (highest in z-order), at a given coordinate within an #AtspiAccessible.
313 * This should be the element, that should be picked, when doing mouse click or finger tap at given coordinates.
315 * Returns: (nullable) (transfer full): a pointer to an
316 * #AtspiAccessible descendant (of any depth) of the specified component which
317 * contains the point (@x, @y), or NULL if no descendant contains
321 atspi_accessible_get_navigable_at_point (AtspiAccessible *root,
324 AtspiCoordType ctype, GError **error)
326 dbus_int32_t d_x = x, d_y = y;
327 dbus_uint32_t d_ctype = ctype;
329 AtspiAccessible *return_value = NULL;
330 unsigned char recurse = 0;
331 DBusMessageIter iter;
332 AtspiAccessible *deputy = NULL;
334 g_return_val_if_fail (root != NULL, NULL);
336 reply = _atspi_dbus_call_partial (root, atspi_interface_accessible, "GetNavigableAtPoint", error, "iiu", d_x, d_y, d_ctype);
337 // call failed, error is set, so we bail out
339 if (deputy) g_object_unref(deputy);
340 if (return_value) g_object_unref(return_value);
343 _ATSPI_DBUS_CHECK_SIG (reply, "(so)y(so)", NULL, NULL);
345 dbus_message_iter_init (reply, &iter);
346 AtspiAccessible *tmp = _atspi_dbus_return_accessible_from_iter (&iter);
348 unsigned char value = 0;
349 dbus_message_iter_get_basic (&iter, &value);
350 dbus_message_iter_next (&iter);
351 recurse = (value != 0);
353 /* keep deputy if tmp has deputy */
355 deputy = _atspi_dbus_return_accessible_from_iter (&iter);
357 dbus_message_unref(reply);
361 /* TODO: need to check deputy works for return value */
363 g_object_unref(return_value);
370 g_object_unref(return_value);
371 return_value = root = tmp;
377 * atspi_accessible_get_reading_material:
378 * @obj: a pointer to the #AtspiAccessible object on which to operate.
380 * Gets reading material
382 * Returns: reading material to be used screen-reader side. This is not stable.
383 * You have to handle all alocated memory as below on screen-reader side.
385 * AtspiAccessibleReadingMaterial *rm
386 * g_object_unref(rm->parent);
387 * g_object_unref(rm->described_by_accessible);
388 * g_hash_table_unref(rm->attributes);
390 * free(rm->labeled_by_name);
391 * free(rm->text_interface_name);
392 * free(rm->localized_role_name);
393 * free(rm->description);
396 AtspiAccessibleReadingMaterial *
397 atspi_accessible_get_reading_material (AtspiAccessible *obj, GError **error)
399 AtspiAccessible *parent;
400 AtspiAccessibleReadingMaterial *reading_material = NULL;
402 double current_value;
406 DBusMessageIter iter;
407 DBusMessageIter iter_array;
409 dbus_uint32_t *states;
410 dbus_int32_t index_in_parent;
411 dbus_int32_t child_count;
412 dbus_bool_t is_selected;
414 g_return_val_if_fail (obj != NULL, NULL);
416 reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetReadingMaterial", error, "");
418 _ATSPI_DBUS_CHECK_SIG (reply, "a{ss}sssuausiddddsibbii(so)auiui(so)", NULL, NULL);
420 reading_material = calloc(1, sizeof(AtspiAccessibleReadingMaterial));
421 if (!reading_material)
423 return reading_material;
426 dbus_message_iter_init (reply, &iter);
429 reading_material->attributes = _atspi_dbus_hash_from_iter (&iter);
430 dbus_message_iter_next (&iter);
433 dbus_message_iter_get_basic (&iter, &name);
434 reading_material->name = g_strdup (name);
435 dbus_message_iter_next (&iter);
437 /* get name of relation LABELED_BY */
438 dbus_message_iter_get_basic (&iter, &name);
439 reading_material->labeled_by_name = g_strdup (name);
440 dbus_message_iter_next (&iter);
442 /* get name of text interface */
443 dbus_message_iter_get_basic (&iter, &name);
444 reading_material->text_interface_name = g_strdup (name);
445 dbus_message_iter_next (&iter);
448 dbus_message_iter_get_basic (&iter, &role);
449 reading_material->role = role;
450 dbus_message_iter_next (&iter);
453 dbus_message_iter_recurse (&iter, &iter_array);
454 dbus_message_iter_get_fixed_array (&iter_array, &states, &count);
455 val = ((guint64)states [1]) << 32;
457 reading_material->states = val;
458 dbus_message_iter_next (&iter);
460 /* get localized role name */
461 dbus_message_iter_get_basic (&iter, &name);
462 reading_material->localized_role_name = g_strdup (name);
463 dbus_message_iter_next (&iter);
465 /* get child count */
466 dbus_message_iter_get_basic (&iter, &child_count);
467 reading_material->child_count = child_count;
468 dbus_message_iter_next (&iter);
470 /* get current value */
471 dbus_message_iter_get_basic (&iter, ¤t_value);
472 reading_material->value = current_value;
473 dbus_message_iter_next (&iter);
475 /* get minimum increment */
476 dbus_message_iter_get_basic (&iter, ¤t_value);
477 reading_material->increment = current_value;
478 dbus_message_iter_next (&iter);
480 /* get maximum value */
481 dbus_message_iter_get_basic (&iter, ¤t_value);
482 reading_material->upper = current_value;
483 dbus_message_iter_next (&iter);
485 /* get minimum value */
486 dbus_message_iter_get_basic (&iter, ¤t_value);
487 reading_material->lower = current_value;
488 dbus_message_iter_next (&iter);
490 /* get description */
491 dbus_message_iter_get_basic (&iter, &name);
492 reading_material->description = g_strdup (name);
493 dbus_message_iter_next (&iter);
495 /* get index in parent */
496 dbus_message_iter_get_basic (&iter, &index_in_parent);
497 reading_material->index_in_parent = index_in_parent;
498 dbus_message_iter_next (&iter);
500 /* get selected in parent */
501 dbus_message_iter_get_basic (&iter, &is_selected);
502 reading_material->is_selected_in_parent = is_selected;
503 dbus_message_iter_next (&iter);
505 /* get has checkbox child */
506 dbus_message_iter_get_basic (&iter, &is_selected);
507 reading_material->has_checkbox_child = is_selected;
508 dbus_message_iter_next (&iter);
510 /* get list children count */
511 dbus_message_iter_get_basic (&iter, &child_count);
512 reading_material->list_children_count = child_count;
513 dbus_message_iter_next (&iter);
515 /* get first selected child index */
516 dbus_message_iter_get_basic (&iter, &index_in_parent);
517 reading_material->first_selected_child_index = index_in_parent;
518 dbus_message_iter_next (&iter);
522 parent = _atspi_dbus_return_accessible_from_iter (&iter);
523 reading_material->parent = parent;
526 dbus_message_iter_recurse (&iter, &iter_array);
527 dbus_message_iter_get_fixed_array (&iter_array, &states, &count);
528 val = ((guint64)states [1]) << 32;
530 reading_material->parent_states = val;
531 dbus_message_iter_next (&iter);
533 /* get parent child count */
534 dbus_message_iter_get_basic (&iter, &child_count);
535 reading_material->parent_child_count = child_count;
536 dbus_message_iter_next (&iter);
538 /* get parent role */
539 dbus_message_iter_get_basic (&iter, &role);
540 reading_material->parent_role = role;
541 dbus_message_iter_next (&iter);
543 /* get parent selected child count */
544 dbus_message_iter_get_basic (&iter, &child_count);
545 reading_material->parent_selected_child_count = child_count;
546 dbus_message_iter_next (&iter);
548 ////////////////////////////////////////
549 /* get relation object - DESCRIBED_BY */
550 parent = _atspi_dbus_return_accessible_from_iter (&iter);
551 reading_material->described_by_accessible = parent;
553 return reading_material;
557 * atspi_accessible_get_default_label_info:
558 * @obj: a pointer to the #AtspiAccessible object would be window.
560 * Gets default label information
562 * Returns: default label information to be used screen-reader side.
563 * This is not stable. And this depends on toolkit side UI definition.
564 * The candidate of default label object could be changed by UI definition.
565 * You have to handle all alocated memory as below on screen-reader side.
567 * AtspiAccessibleDefaultLabelInfo *dli
568 * g_hash_table_unref(dli->attributes);
570 * g_object_unref(dli->obj);
573 AtspiAccessibleDefaultLabelInfo *
574 atspi_accessible_get_default_label_info (AtspiAccessible *obj, GError **error)
576 AtspiAccessibleDefaultLabelInfo *default_label_info = NULL;
577 AtspiAccessible *default_label_object;
580 DBusMessageIter iter;
582 g_return_val_if_fail (obj != NULL, NULL);
584 reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetDefaultLabelInfo", error, "");
586 _ATSPI_DBUS_CHECK_SIG (reply, "(so)ua{ss}", NULL, NULL);
588 default_label_info = calloc(1, sizeof(AtspiAccessibleDefaultLabelInfo));
589 if (!default_label_info)
591 return default_label_info;
594 dbus_message_iter_init (reply, &iter);
596 default_label_object = _atspi_dbus_return_accessible_from_iter (&iter);
597 default_label_info->obj = default_label_object;
599 dbus_message_iter_get_basic (&iter, &role);
600 default_label_info->role = role;
601 dbus_message_iter_next (&iter);
603 default_label_info->attributes = _atspi_dbus_hash_from_iter (&iter);
604 dbus_message_iter_next (&iter);
606 return default_label_info;
609 static unsigned char are_objects_on_the_same_bus(AtspiAccessible *obj1, AtspiAccessible *obj2)
611 const char *bus_name_1 = obj1->parent.app->bus_name;
612 const char *bus_name_2 = obj2->parent.app->bus_name;
613 return strcmp(bus_name_1, bus_name_2) == 0;
616 static unsigned char object_is_valid(AtspiAccessible *obj)
620 AtspiStateSet *ss = atspi_accessible_get_state_set(obj);
623 unsigned char valid = atspi_state_set_contains(ss, ATSPI_STATE_DEFUNCT) == 0;
629 NEIGHBOR_SEARCH_MODE_NORMAL = 0,
630 NEIGHBOR_SEARCH_MODE_RECURSE_FROM_ROOT = 1,
631 NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING = 2,
632 NEIGHBOR_SEARCH_MODE_RECURSE_TO_OUTSIDE = 3,
633 } GetNeighborSearchMode;
635 * atspi_accessible_get_neighbor:
636 * @root: a pointer to a #AtspiAccessible, which represents current root of subtree to search
637 * @start: a pointer to the #AtspiAccessible to start search from (can be null, which means start from root)
638 * @direction: direction, in which search (forward or backward)
640 * Calculates next (or previous) accessible element in logical order or null if none found.
642 * Returns: (nullable) (transfer full): a pointer to an
643 * #AtspiAccessible element, which is next (previous) in logical order or null if none found.
646 atspi_accessible_get_neighbor (AtspiAccessible *root,
647 AtspiAccessible *start,
648 AtspiNeighborSearchDirection direction,
651 g_return_val_if_fail (object_is_valid(root), NULL);
652 if (!object_is_valid(start))
654 const char *root_path = ATSPI_OBJECT(root)->path;
655 AtspiAccessible *return_value = NULL;
657 unsigned char recurse;
658 GetNeighborSearchMode search_mode = NEIGHBOR_SEARCH_MODE_NORMAL;
659 GQueue *children_root_stack = g_queue_new();
660 DBusMessageIter iter;
663 const char *path = are_objects_on_the_same_bus(root, start) ? root_path : "";
664 DBusMessage *reply = _atspi_dbus_call_partial (start, atspi_interface_accessible, "GetNeighbor", error, "sii", path, (int)direction, (int)search_mode);
665 // call failed, error is set, so we bail out
668 _ATSPI_DBUS_CHECK_SIG (reply, "(so)y", error, NULL);
669 dbus_message_iter_init (reply, &iter);
670 AtspiAccessible *ret = _atspi_dbus_return_accessible_from_iter (&iter);
672 unsigned char value = 0;
673 dbus_message_iter_get_basic (&iter, &value);
674 dbus_message_iter_next (&iter);
675 recurse = (value != 0);
677 dbus_message_unref(reply);
679 // got return value and request for recursive search, it means ret is on another bridge, than start
680 // thus we're recursing. should the recurse failed to find anything it will end with
681 if (ret && recurse) {
682 g_object_unref(G_OBJECT(start));
685 if (are_objects_on_the_same_bus(root, ret))
687 search_mode = NEIGHBOR_SEARCH_MODE_RECURSE_TO_OUTSIDE;
691 g_queue_push_tail(children_root_stack, ret);
692 search_mode = NEIGHBOR_SEARCH_MODE_RECURSE_FROM_ROOT;
696 // found the one we've been looking for
698 g_object_unref(G_OBJECT(start));
703 // we've stepped into different bridges previously and now we're going back to the last one
704 // and continuing search where we left
705 if (!g_queue_is_empty(children_root_stack)) {
706 g_object_unref(G_OBJECT(start));
707 start = g_queue_pop_tail(children_root_stack);
709 search_mode = NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING;
712 // there's no more bridges to check, but we might have started from one
713 // in that case there might be bridges "below" start, which we yet have to visit
714 if (!are_objects_on_the_same_bus(root, start)) {
715 unsigned char continue_loop = 1;
716 while(continue_loop) {
717 AtspiAccessible *parent = atspi_accessible_get_parent(start, NULL);
718 continue_loop = parent ? are_objects_on_the_same_bus(start, parent) : 0;
719 g_object_unref(G_OBJECT(start));
723 // going up thru parents put us in weird place (we didnt meet root on the way)
728 // start object now points to different bridge and must be treated as "resume after recursing"
729 search_mode = NEIGHBOR_SEARCH_MODE_CONTINUE_AFTER_FAILED_RECURSING;
734 g_object_unref(start);
737 while(!g_queue_is_empty(children_root_stack))
738 g_object_unref(g_queue_pop_tail(children_root_stack));
739 g_queue_free(children_root_stack);
745 * atspi_accessible_get_description:
746 * @obj: a pointer to the #AtspiAccessible object on which to operate.
748 * Gets the description of an #AtspiAccessible object.
750 * Returns: a UTF-8 string describing the #AtspiAccessible object
751 * or NULL on exception.
754 atspi_accessible_get_description (AtspiAccessible *obj, GError **error)
756 g_return_val_if_fail (obj != NULL, g_strdup (""));
758 if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_DESCRIPTION))
760 if (!_atspi_dbus_get_property (obj, atspi_interface_accessible,
761 "Description", error, "s",
763 return g_strdup ("");
764 _atspi_accessible_add_cache (obj, ATSPI_CACHE_DESCRIPTION);
766 return g_strdup (obj->description);
769 const char *str_parent = "Parent";
772 * atspi_accessible_get_parent:
773 * @obj: a pointer to the #AtspiAccessible object to query.
775 * Gets an #AtspiAccessible object's parent container.
777 * Returns: (nullable) (transfer full): a pointer to the
778 * #AtspiAccessible object which contains the given
779 * #AtspiAccessible instance, or NULL if the @obj has no
784 atspi_accessible_get_parent (AtspiAccessible *obj, GError **error)
786 g_return_val_if_fail (obj != NULL, NULL);
788 if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_PARENT))
790 DBusMessage *message, *reply;
791 DBusMessageIter iter, iter_variant;
792 if (!obj->parent.app)
794 message = dbus_message_new_method_call (obj->parent.app->bus_name,
796 DBUS_INTERFACE_PROPERTIES, "Get");
799 dbus_message_append_args (message, DBUS_TYPE_STRING, &atspi_interface_accessible,
800 DBUS_TYPE_STRING, &str_parent,
802 reply = _atspi_dbus_send_with_reply_and_block (message, error);
805 if (strcmp (dbus_message_get_signature (reply), "v") != 0)
807 dbus_message_unref (reply);
810 dbus_message_iter_init (reply, &iter);
811 dbus_message_iter_recurse (&iter, &iter_variant);
812 obj->accessible_parent = _atspi_dbus_return_accessible_from_iter (&iter_variant);
813 dbus_message_unref (reply);
814 _atspi_accessible_add_cache (obj, ATSPI_CACHE_PARENT);
816 if (!obj->accessible_parent)
818 return g_object_ref (obj->accessible_parent);
822 * atspi_accessible_get_child_count:
823 * @obj: a pointer to the #AtspiAccessible object on which to operate.
825 * Gets the number of children contained by an #AtspiAccessible object.
827 * Returns: a #long indicating the number of #AtspiAccessible children
828 * contained by an #AtspiAccessible object or -1 on exception.
832 atspi_accessible_get_child_count (AtspiAccessible *obj, GError **error)
834 g_return_val_if_fail (obj != NULL, -1);
836 if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_CHILDREN))
839 if (!_atspi_dbus_get_property (obj, atspi_interface_accessible,
840 "ChildCount", error, "i", &ret))
846 return 0; /* assume it's disposed */
848 return obj->children->len;
852 * atspi_accessible_get_child_at_index:
853 * @obj: a pointer to the #AtspiAccessible object on which to operate.
854 * @child_index: a #long indicating which child is specified.
856 * Gets the #AtspiAccessible child of an #AtspiAccessible object at a given index.
858 * Returns: (transfer full): a pointer to the #AtspiAccessible child object at
859 * index @child_index or NULL on exception.
862 atspi_accessible_get_child_at_index (AtspiAccessible *obj,
866 AtspiAccessible *child;
869 g_return_val_if_fail (obj != NULL, NULL);
871 if (_atspi_accessible_test_cache (obj, ATSPI_CACHE_CHILDREN))
874 return NULL; /* assume disposed */
876 child = g_ptr_array_index (obj->children, child_index);
878 return g_object_ref (child);
881 reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible,
882 "GetChildAtIndex", error, "i", child_index);
883 child = _atspi_dbus_return_accessible_from_message (reply);
888 if (_atspi_accessible_test_cache (obj, ATSPI_CACHE_CHILDREN))
890 if (child_index >= obj->children->len)
891 g_ptr_array_set_size (obj->children, child_index + 1);
892 g_ptr_array_index (obj->children, child_index) = g_object_ref (child);
898 * atspi_accessible_get_index_in_parent:
899 * @obj: a pointer to the #AtspiAccessible object on which to operate.
901 * Gets the index of an #AtspiAccessible object within its parent's
902 * #AtspiAccessible children list.
904 * Returns: a #glong indicating the index of the #AtspiAccessible object
906 * or -1 if @obj has no containing parent or on exception.
909 atspi_accessible_get_index_in_parent (AtspiAccessible *obj, GError **error)
912 dbus_int32_t ret = -1;
914 g_return_val_if_fail (obj != NULL, -1);
915 if (_atspi_accessible_test_cache (obj, ATSPI_CACHE_PARENT))
917 if (!obj->accessible_parent)
920 if (!_atspi_accessible_test_cache (obj->accessible_parent, ATSPI_CACHE_CHILDREN) || !obj->accessible_parent->children)
923 for (i = 0; i < obj->accessible_parent->children->len; i++)
924 if (g_ptr_array_index (obj->accessible_parent->children, i) == obj)
929 _atspi_dbus_call (obj, atspi_interface_accessible,
930 "GetIndexInParent", NULL, "=>i", &ret);
938 } Accessibility_Relation;
941 * atspi_accessible_get_relation_set:
942 * @obj: a pointer to the #AtspiAccessible object on which to operate.
944 * Gets the set of #AtspiRelation objects which describes this #AtspiAccessible object's
945 * relationships with other #AtspiAccessible objects.
947 * Returns: (element-type AtspiRelation*) (transfer full): a #GArray of
948 * #AtspiRelation pointers or NULL on exception.
951 atspi_accessible_get_relation_set (AtspiAccessible *obj, GError **error)
954 DBusMessageIter iter, iter_array;
957 g_return_val_if_fail (obj != NULL, NULL);
959 reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetRelationSet", error, "");
962 _ATSPI_DBUS_CHECK_SIG (reply, "a(ua(so))", error, NULL);
964 ret = g_array_new (TRUE, TRUE, sizeof (AtspiRelation *));
965 dbus_message_iter_init (reply, &iter);
966 dbus_message_iter_recurse (&iter, &iter_array);
967 while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
969 AtspiRelation *relation;
970 relation = _atspi_relation_new_from_iter (&iter_array);
971 ret = g_array_append_val (ret, relation);
972 dbus_message_iter_next (&iter_array);
974 dbus_message_unref (reply);
979 * atspi_accessible_get_role:
980 * @obj: a pointer to the #AtspiAccessible object on which to operate.
982 * Gets the UI role played by an #AtspiAccessible object.
983 * This role's name can be obtained via atspi_accessible_get_role_name ().
985 * Returns: the #AtspiRole of an #AtspiAccessible object.
989 atspi_accessible_get_role (AtspiAccessible *obj, GError **error)
991 g_return_val_if_fail (obj != NULL, ATSPI_ROLE_INVALID);
993 if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_ROLE))
996 /* TODO: Make this a property */
997 if (_atspi_dbus_call (obj, atspi_interface_accessible, "GetRole", error, "=>u", &role))
1000 _atspi_accessible_add_cache (obj, ATSPI_CACHE_ROLE);
1007 * atspi_accessible_get_role_name:
1008 * @obj: a pointer to the #AtspiAccessible object on which to operate.
1010 * Gets a UTF-8 string corresponding to the name of the role played by an object.
1011 * This method will return useful values for roles that fall outside the
1012 * enumeration used in atspi_accessible_get_role ().
1014 * Returns: a UTF-8 string specifying the type of UI role played by an
1015 * #AtspiAccessible object.
1019 atspi_accessible_get_role_name (AtspiAccessible *obj, GError **error)
1021 gchar *retval = NULL;
1024 g_return_val_if_fail (obj != NULL, NULL);
1026 role = atspi_accessible_get_role (obj, error);
1027 if (role >= 0 && role < ATSPI_ROLE_COUNT && role != ATSPI_ROLE_EXTENDED)
1028 return atspi_role_get_name (role);
1030 _atspi_dbus_call (obj, atspi_interface_accessible, "GetRoleName", error, "=>s", &retval);
1033 retval = g_strdup ("");
1039 * atspi_accessible_get_localized_role_name:
1040 * @obj: a pointer to the #AtspiAccessible object on which to operate.
1042 * Gets a UTF-8 string corresponding to the name of the role played by an
1043 * object, translated to the current locale.
1044 * This method will return useful values for roles that fall outside the
1045 * enumeration used in atspi_accessible_getRole ().
1047 * Returns: a localized, UTF-8 string specifying the type of UI role played
1048 * by an #AtspiAccessible object.
1052 atspi_accessible_get_localized_role_name (AtspiAccessible *obj, GError **error)
1054 char *retval = NULL;
1056 g_return_val_if_fail (obj != NULL, NULL);
1058 _atspi_dbus_call (obj, atspi_interface_accessible, "GetLocalizedRoleName", error, "=>s", &retval);
1061 return g_strdup ("");
1066 static AtspiStateSet *
1069 AtspiStateSet *set = atspi_state_set_new (NULL);
1070 atspi_state_set_add (set, ATSPI_STATE_DEFUNCT);
1075 * atspi_accessible_get_state_set:
1076 * @obj: a pointer to the #AtspiAccessible object on which to operate.
1078 * Gets the states currently held by an object.
1080 * Returns: (transfer full): a pointer to an #AtspiStateSet representing an
1081 * object's current state set.
1084 atspi_accessible_get_state_set (AtspiAccessible *obj)
1086 /* TODO: Should take a GError **, but would be an API break */
1087 if (!obj->parent.app || !obj->parent.app->bus)
1088 return defunct_set ();
1090 if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_STATES))
1093 DBusMessageIter iter;
1094 reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible,
1095 "GetState", NULL, "");
1096 _ATSPI_DBUS_CHECK_SIG (reply, "au", NULL, defunct_set ());
1097 dbus_message_iter_init (reply, &iter);
1098 _atspi_dbus_set_state (obj, &iter);
1099 dbus_message_unref (reply);
1100 _atspi_accessible_add_cache (obj, ATSPI_CACHE_STATES);
1102 return g_object_ref (obj->states);
1106 * atspi_accessible_get_attributes:
1107 * @obj: The #AtspiAccessible being queried.
1109 * Gets the #AttributeSet representing any assigned
1110 * name-value pair attributes or annotations for this object.
1111 * For typographic, textual, or textually-semantic attributes, see
1112 * atspi_text_get_attributes instead.
1114 * Returns: (element-type gchar* gchar*) (transfer full): The name-value-pair
1115 * attributes assigned to this object.
1118 atspi_accessible_get_attributes (AtspiAccessible *obj, GError **error)
1120 DBusMessage *message;
1122 g_return_val_if_fail (obj != NULL, NULL);
1124 if (obj->priv->cache)
1126 GValue *val = g_hash_table_lookup (obj->priv->cache, "Attributes");
1128 return g_value_dup_boxed (val);
1131 if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_ATTRIBUTES))
1133 message = _atspi_dbus_call_partial (obj, atspi_interface_accessible,
1134 "GetAttributes", error, "");
1135 obj->attributes = _atspi_dbus_return_hash_from_message (message);
1136 _atspi_accessible_add_cache (obj, ATSPI_CACHE_ATTRIBUTES);
1139 if (!obj->attributes)
1141 return g_hash_table_ref (obj->attributes);
1145 add_to_attribute_array (gpointer key, gpointer value, gpointer data)
1147 GArray **array = (GArray **)data;
1148 gchar *str = g_strconcat (key, ":", value, NULL);
1149 *array = g_array_append_val (*array, str);
1153 * atspi_accessible_get_attributes_as_array:
1154 * @obj: The #AtspiAccessible being queried.
1156 * Gets a #GArray representing any assigned
1157 * name-value pair attributes or annotations for this object.
1158 * For typographic, textual, or textually-semantic attributes, see
1159 * atspi_text_get_attributes_as_array instead.
1161 * Returns: (element-type gchar*) (transfer full): The name-value-pair
1162 * attributes assigned to this object.
1165 atspi_accessible_get_attributes_as_array (AtspiAccessible *obj, GError **error)
1167 DBusMessage *message;
1169 g_return_val_if_fail (obj != NULL, NULL);
1171 if (obj->priv->cache)
1173 GValue *val = g_hash_table_lookup (obj->priv->cache, "Attributes");
1176 GArray *array = g_array_new (TRUE, TRUE, sizeof (gchar *));
1177 GHashTable *attributes = g_value_get_boxed (val);
1178 g_hash_table_foreach (attributes, add_to_attribute_array, &array);
1183 message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetAttributes", error, "");
1184 return _atspi_dbus_return_attribute_array_from_message (message);
1188 * atspi_accessible_get_application:
1189 * @obj: The #AtspiAccessible being queried.
1191 * Gets the containing #AtspiApplication for an object.
1193 * Returns: (transfer full): the containing #AtspiApplication instance for
1197 atspi_accessible_get_application (AtspiAccessible *obj, GError **error)
1199 AtspiAccessible *parent;
1204 parent = atspi_accessible_get_parent (obj, NULL);
1205 if (!parent && obj->parent.app &&
1206 atspi_accessible_get_role (obj, NULL) != ATSPI_ROLE_APPLICATION)
1208 AtspiAccessible *root = g_object_ref (obj->parent.app->root);
1211 g_object_unref (obj);
1212 if (atspi_accessible_get_role (root, NULL) == ATSPI_ROLE_DESKTOP_FRAME)
1214 g_object_unref (root);
1220 if (!parent || parent == obj ||
1221 atspi_accessible_get_role (parent, NULL) == ATSPI_ROLE_DESKTOP_FRAME)
1224 g_object_unref (parent);
1227 g_object_unref (obj);
1232 /* Application-specific methods */
1235 * atspi_accessible_get_toolkit_name:
1236 * @obj: a pointer to the #AtspiAccessible object on which to operate.
1238 * Gets the toolkit name for an #AtspiAccessible object.
1239 * Only works on application root objects.
1241 * Returns: a UTF-8 string indicating the toolkit name for the #AtspiAccessible object or NULL on exception.
1244 atspi_accessible_get_toolkit_name (AtspiAccessible *obj, GError **error)
1246 g_return_val_if_fail (obj != NULL, NULL);
1248 if (!obj->parent.app)
1251 if (!obj->parent.app->toolkit_name)
1252 _atspi_dbus_get_property (obj, atspi_interface_application, "ToolkitName",
1253 error, "s", &obj->parent.app->toolkit_name);
1255 return g_strdup (obj->parent.app->toolkit_name);
1259 * atspi_accessible_get_toolkit_version:
1260 * @obj: a pointer to the #AtspiAccessible object on which to operate.
1262 * Gets the toolkit version for an #AtspiAccessible object.
1263 * Only works on application root objects.
1265 * Returns: a UTF-8 string indicating the toolkit version for the #AtspiAccessible object or NULL on exception.
1268 atspi_accessible_get_toolkit_version (AtspiAccessible *obj, GError **error)
1270 g_return_val_if_fail (obj != NULL, NULL);
1272 if (!obj->parent.app)
1275 if (!obj->parent.app->toolkit_version)
1276 _atspi_dbus_get_property (obj, atspi_interface_application, "Version",
1277 error, "s", &obj->parent.app->toolkit_version);
1279 return g_strdup (obj->parent.app->toolkit_version);
1283 * atspi_accessible_get_atspi_version:
1284 * @obj: a pointer to the #AtspiAccessible object on which to operate.
1286 * Gets the AT-SPI IPC specification version supported by the application
1287 * pointed to by the #AtspiAccessible object.
1288 * Only works on application root objects.
1290 * Returns: a UTF-8 string indicating the AT-SPI version for the #AtspiAccessible object or NULL on exception.
1293 atspi_accessible_get_atspi_version (AtspiAccessible *obj, GError **error)
1295 g_return_val_if_fail (obj != NULL, NULL);
1297 if (!obj->parent.app)
1300 if (!obj->parent.app->atspi_version)
1301 _atspi_dbus_get_property (obj, atspi_interface_application, "AtspiVersion",
1302 error, "s", &obj->parent.app->atspi_version);
1304 return g_strdup (obj->parent.app->atspi_version);
1308 * atspi_accessible_get_id:
1309 * @obj: a pointer to the #AtspiAccessible object on which to operate.
1311 * Gets the application id for a #AtspiAccessible object.
1312 * Only works on application root objects.
1314 * Returns: a positive #gint indicating the id for the #AtspiAccessible object
1315 * or -1 on exception.
1318 atspi_accessible_get_id (AtspiAccessible *obj, GError **error)
1322 g_return_val_if_fail (obj != NULL, -1);
1324 if (!_atspi_dbus_get_property (obj, atspi_interface_application, "Id", error, "i", &ret))
1330 /* Interface query methods */
1333 _atspi_accessible_is_a (AtspiAccessible *accessible,
1334 const char *interface_name)
1338 if (accessible == NULL)
1343 if (!_atspi_accessible_test_cache (accessible, ATSPI_CACHE_INTERFACES))
1346 DBusMessageIter iter;
1347 reply = _atspi_dbus_call_partial (accessible, atspi_interface_accessible,
1348 "GetInterfaces", NULL, "");
1349 _ATSPI_DBUS_CHECK_SIG (reply, "as", NULL, FALSE);
1350 dbus_message_iter_init (reply, &iter);
1351 _atspi_dbus_set_interfaces (accessible, &iter);
1352 dbus_message_unref (reply);
1353 _atspi_accessible_add_cache (accessible, ATSPI_CACHE_INTERFACES);
1356 n = _atspi_get_iface_num (interface_name);
1357 if (n == -1) return FALSE;
1358 return (gboolean) ((accessible->interfaces & (1 << n))? TRUE: FALSE);
1362 * atspi_accessible_is_action:
1363 * @obj: a pointer to the #AtspiAccessible instance to query.
1365 * Query whether the specified #AtspiAccessible implements the
1366 * #AtspiAction interface.
1368 * Returns: #TRUE if @obj implements the #AtspiAction interface,
1372 atspi_accessible_is_action (AtspiAccessible *obj)
1374 return _atspi_accessible_is_a (obj,
1375 atspi_interface_action);
1379 * atspi_accessible_is_application:
1380 * @obj: a pointer to the #AtspiAccessible instance to query.
1382 * Query whether the specified #AtspiAccessible implements the
1383 * #AtspiApplication interface.
1385 * Returns: #TRUE if @obj implements the #AtspiApplication interface,
1389 atspi_accessible_is_application (AtspiAccessible *obj)
1391 return _atspi_accessible_is_a (obj,
1392 atspi_interface_application);
1396 * atspi_accessible_is_collection:
1397 * @obj: a pointer to the #AtspiAccessible instance to query.
1399 * Query whether the specified #AtspiAccessible implements the
1400 * #AtspiCollection interface.
1402 * Returns: #TRUE if @obj implements the #AtspiCollection interface,
1406 atspi_accessible_is_collection (AtspiAccessible *obj)
1408 return _atspi_accessible_is_a (obj,
1409 atspi_interface_collection);
1413 * atspi_accessible_is_component:
1414 * @obj: a pointer to the #AtspiAccessible instance to query.
1416 * Query whether the specified #AtspiAccessible implements #AtspiComponent.
1418 * Returns: #TRUE if @obj implements the #AtspiComponent interface,
1422 atspi_accessible_is_component (AtspiAccessible *obj)
1424 return _atspi_accessible_is_a (obj,
1425 atspi_interface_component);
1429 * atspi_accessible_is_document:
1430 * @obj: a pointer to the #AtspiAccessible instance to query.
1432 * Query whether the specified #AtspiAccessible implements the
1433 * #AtspiDocument interface.
1435 * Returns: #TRUE if @obj implements the #AtspiDocument interface,
1439 atspi_accessible_is_document (AtspiAccessible *obj)
1441 return _atspi_accessible_is_a (obj,
1442 atspi_interface_document);
1446 * atspi_accessible_is_editable_text:
1447 * @obj: a pointer to the #AtspiAccessible instance to query.
1449 * Query whether the specified #AtspiAccessible implements the
1450 * #AtspiEditableText interface.
1452 * Returns: #TRUE if @obj implements the #AtspiEditableText interface,
1456 atspi_accessible_is_editable_text (AtspiAccessible *obj)
1458 return _atspi_accessible_is_a (obj,
1459 atspi_interface_editable_text);
1463 * atspi_accessible_is_hypertext:
1464 * @obj: a pointer to the #AtspiAccessible instance to query.
1466 * Query whether the specified #AtspiAccessible implements the
1467 * #AtspiHypertext interface.
1469 * Returns: #TRUE if @obj implements the #AtspiHypertext interface,
1473 atspi_accessible_is_hypertext (AtspiAccessible *obj)
1475 return _atspi_accessible_is_a (obj,
1476 atspi_interface_hypertext);
1480 * atspi_accessible_is_hyperlink:
1481 * @obj: a pointer to the #AtspiAccessible instance to query.
1483 * Query whether the specified #AtspiAccessible implements the
1484 * #AtspiHyperlink interface.
1486 * Returns: #TRUE if @obj implements the #AtspiHypertext interface,
1490 atspi_accessible_is_hyperlink (AtspiAccessible *obj)
1492 return _atspi_accessible_is_a (obj,
1493 atspi_interface_hyperlink);
1497 * atspi_accessible_is_image:
1498 * @obj: a pointer to the #AtspiAccessible instance to query.
1500 * Query whether the specified #AtspiAccessible implements the
1501 * #AtspiImage interface.
1503 * Returns: #TRUE if @obj implements the #AtspiImage interface,
1507 atspi_accessible_is_image (AtspiAccessible *obj)
1509 return _atspi_accessible_is_a (obj,
1510 atspi_interface_image);
1514 * atspi_accessible_is_selection:
1515 * @obj: a pointer to the #AtspiAccessible instance to query.
1517 * Query whether the specified #AtspiAccessible implements the
1518 * #AtspiSelection interface.
1520 * Returns: #TRUE if @obj implements the #AtspiSelection interface,
1524 atspi_accessible_is_selection (AtspiAccessible *obj)
1526 return _atspi_accessible_is_a (obj,
1527 atspi_interface_selection);
1531 * atspi_accessible_is_table:
1532 * @obj: a pointer to the #AtspiAccessible instance to query.
1534 * Query whether the specified #AtspiAccessible implements the
1535 * #AtspiTable interface.
1537 * Returns: #TRUE if @obj implements the #AtspiTable interface,
1541 atspi_accessible_is_table (AtspiAccessible *obj)
1543 return _atspi_accessible_is_a (obj,
1544 atspi_interface_table);
1548 * atspi_accessible_is_table_cell:
1549 * @obj: a pointer to the #AtspiAccessible instance to query.
1551 * Query whether the specified #AtspiAccessible implements the
1552 * #AtspiTableCell interface.
1554 * Returns: #TRUE if @obj implements the #AtspiTable interface,
1558 atspi_accessible_is_table_cell (AtspiAccessible *obj)
1560 return _atspi_accessible_is_a (obj,
1561 atspi_interface_table_cell);
1565 * atspi_accessible_is_streamable_content:
1566 * @obj: a pointer to the #AtspiAccessible instance to query.
1568 * Query whether the specified #AtspiAccessible implements the
1569 * #AtspiStreamableContent interface.
1571 * Returns: #TRUE if @obj implements the #AtspiStreamableContent interface,
1575 atspi_accessible_is_streamable_content (AtspiAccessible *obj)
1578 return _atspi_accessible_is_a (obj,
1579 atspi_interface_streamable_content);
1581 g_warning ("Streamable content not implemented");
1587 * atspi_accessible_is_text:
1588 * @obj: a pointer to the #AtspiAccessible instance to query.
1590 * Query whether the specified #AtspiAccessible implements the
1591 * #AtspiText interface.
1593 * Returns: #TRUE if @obj implements the #AtspiText interface,
1597 atspi_accessible_is_text (AtspiAccessible *obj)
1599 return _atspi_accessible_is_a (obj,
1600 atspi_interface_text);
1604 * atspi_accessible_is_value:
1605 * @obj: a pointer to the #AtspiAccessible instance to query.
1607 * Query whether the specified #AtspiAccessible implements the
1608 * #AtspiValue interface.
1610 * Returns: #TRUE if @obj implements the #AtspiValue interface,
1614 atspi_accessible_is_value (AtspiAccessible *obj)
1616 return _atspi_accessible_is_a (obj,
1617 atspi_interface_value);
1621 * atspi_accessible_get_action: (rename-to atspi_accessible_get_action_iface)
1622 * @obj: a pointer to the #AtspiAccessible instance to query.
1624 * Gets the #AtspiAction interface for an #AtspiAccessible.
1626 * Returns: (transfer full): a pointer to an #AtspiAction interface
1627 * instance, or NULL if @obj does not implement #AtspiAction.
1629 * Deprecated: 2.10: Use atspi_accessible_get_action_iface instead.
1632 atspi_accessible_get_action (AtspiAccessible *accessible)
1634 return (_atspi_accessible_is_a (accessible, atspi_interface_action) ?
1635 g_object_ref (ATSPI_ACTION (accessible)) : NULL);
1639 * atspi_accessible_get_action_iface:
1640 * @obj: a pointer to the #AtspiAccessible instance to query.
1642 * Gets the #AtspiAction interface for an #AtspiAccessible.
1644 * Returns: (transfer full): a pointer to an #AtspiAction interface
1645 * instance, or NULL if @obj does not implement #AtspiAction.
1648 atspi_accessible_get_action_iface (AtspiAccessible *accessible)
1650 return (_atspi_accessible_is_a (accessible, atspi_interface_action) ?
1651 g_object_ref (ATSPI_ACTION (accessible)) : NULL);
1655 * atspi_accessible_get_collection: (rename-to atspi_accessible_get_collection_iface)
1656 * @obj: a pointer to the #AtspiAccessible instance to query.
1658 * Gets the #AtspiCollection interface for an #AtspiAccessible.
1660 * Returns: (transfer full): a pointer to an #AtspiCollection interface
1661 * instance, or NULL if @obj does not implement #AtspiCollection.
1663 * Deprecated: 2.10: Use atspi_accessible_get_collection_iface instead.
1666 atspi_accessible_get_collection (AtspiAccessible *accessible)
1668 return (_atspi_accessible_is_a (accessible, atspi_interface_collection) ?
1669 g_object_ref (ATSPI_COLLECTION (accessible)) : NULL);
1673 * atspi_accessible_get_collection_iface:
1674 * @obj: a pointer to the #AtspiAccessible instance to query.
1676 * Gets the #AtspiCollection interface for an #AtspiAccessible.
1678 * Returns: (transfer full): a pointer to an #AtspiCollection interface
1679 * instance, or NULL if @obj does not implement #AtspiCollection.
1682 atspi_accessible_get_collection_iface (AtspiAccessible *accessible)
1684 return (_atspi_accessible_is_a (accessible, atspi_interface_collection) ?
1685 g_object_ref (ATSPI_COLLECTION (accessible)) : NULL);
1689 * atspi_accessible_get_component: (rename-to atspi_accessible_get_component_iface)
1690 * @obj: a pointer to the #AtspiAccessible instance to query.
1692 * Gets the #AtspiComponent interface for an #AtspiAccessible.
1694 * Returns: (transfer full): a pointer to an #AtspiComponent interface
1695 * instance, or NULL if @obj does not implement #AtspiComponent.
1697 * Deprecated: 2.10: Use atspi_accessible_get_component_iface instead.
1700 atspi_accessible_get_component (AtspiAccessible *obj)
1702 return (_atspi_accessible_is_a (obj, atspi_interface_component) ?
1703 g_object_ref (ATSPI_COMPONENT (obj)) : NULL);
1707 * atspi_accessible_get_component_iface:
1708 * @obj: a pointer to the #AtspiAccessible instance to query.
1710 * Gets the #AtspiComponent interface for an #AtspiAccessible.
1712 * Returns: (transfer full): a pointer to an #AtspiComponent interface
1713 * instance, or NULL if @obj does not implement #AtspiComponent.
1716 atspi_accessible_get_component_iface (AtspiAccessible *obj)
1718 return (_atspi_accessible_is_a (obj, atspi_interface_component) ?
1719 g_object_ref (ATSPI_COMPONENT (obj)) : NULL);
1723 * atspi_accessible_get_document: (rename-to atspi_accessible_get_document_iface)
1724 * @obj: a pointer to the #AtspiAccessible instance to query.
1726 * Gets the #AtspiDocument interface for an #AtspiAccessible.
1728 * Returns: (transfer full): a pointer to an #AtspiDocument interface
1729 * instance, or NULL if @obj does not implement #AtspiDocument.
1731 * Deprecated: 2.10: Use atspi_accessible_get_document_iface instead.
1734 atspi_accessible_get_document (AtspiAccessible *accessible)
1736 return (_atspi_accessible_is_a (accessible, atspi_interface_document) ?
1737 g_object_ref (ATSPI_DOCUMENT (accessible)) : NULL);
1741 * atspi_accessible_get_document_iface:
1742 * @obj: a pointer to the #AtspiAccessible instance to query.
1744 * Gets the #AtspiDocument interface for an #AtspiAccessible.
1746 * Returns: (transfer full): a pointer to an #AtspiDocument interface
1747 * instance, or NULL if @obj does not implement #AtspiDocument.
1750 atspi_accessible_get_document_iface (AtspiAccessible *accessible)
1752 return (_atspi_accessible_is_a (accessible, atspi_interface_document) ?
1753 g_object_ref (ATSPI_DOCUMENT (accessible)) : NULL);
1757 * atspi_accessible_get_editable_text: (rename-to atspi_accessible_get_editable_text_iface)
1758 * @obj: a pointer to the #AtspiAccessible instance to query.
1760 * Gets the #AtspiEditableText interface for an #AtspiAccessible.
1762 * Returns: (transfer full): a pointer to an #AtspiEditableText interface
1763 * instance, or NULL if @obj does not implement #AtspiEditableText.
1765 * Deprecated: 2.10: Use atspi_accessible_get_editable_text_iface instead.
1768 atspi_accessible_get_editable_text (AtspiAccessible *accessible)
1770 return (_atspi_accessible_is_a (accessible, atspi_interface_editable_text) ?
1771 g_object_ref (ATSPI_EDITABLE_TEXT (accessible)) : NULL);
1775 * atspi_accessible_get_editable_text_iface:
1776 * @obj: a pointer to the #AtspiAccessible instance to query.
1778 * Gets the #AtspiEditableText interface for an #AtspiAccessible.
1780 * Returns: (transfer full): a pointer to an #AtspiEditableText interface
1781 * instance, or NULL if @obj does not implement #AtspiEditableText.
1784 atspi_accessible_get_editable_text_iface (AtspiAccessible *accessible)
1786 return (_atspi_accessible_is_a (accessible, atspi_interface_editable_text) ?
1787 g_object_ref (ATSPI_EDITABLE_TEXT (accessible)) : NULL);
1791 * atspi_accessible_get_hyperlink:
1792 * @obj: a pointer to the #AtspiAccessible object on which to operate.
1794 * Gets the #AtspiHyperlink interface for an #AtspiAccessible.
1796 * Returns: (transfer full): the #AtspiHyperlink object associated with
1797 * the given #AtspiAccessible, or NULL if not supported.
1800 atspi_accessible_get_hyperlink (AtspiAccessible *accessible)
1802 return (_atspi_accessible_is_a (accessible, atspi_interface_hyperlink) ?
1803 _atspi_hyperlink_new (accessible->parent.app, accessible->parent.path) : NULL);
1807 * atspi_accessible_get_hypertext: (rename-to atspi_accessible_get_hypertext_iface)
1808 * @obj: a pointer to the #AtspiAccessible instance to query.
1810 * Gets the #AtspiHypertext interface for an #AtspiAccessible.
1812 * Returns: (transfer full): a pointer to an #AtspiHypertext interface
1813 * instance, or NULL if @obj does not implement #AtspiHypertext.
1815 * Deprecated: 2.10: Use atspi_accessible_get_hypertext_iface instead.
1818 atspi_accessible_get_hypertext (AtspiAccessible *accessible)
1820 return (_atspi_accessible_is_a (accessible, atspi_interface_hypertext) ?
1821 g_object_ref (ATSPI_HYPERTEXT (accessible)) : NULL);
1825 * atspi_accessible_get_hypertext_iface:
1826 * @obj: a pointer to the #AtspiAccessible instance to query.
1828 * Gets the #AtspiHypertext interface for an #AtspiAccessible.
1830 * Returns: (transfer full): a pointer to an #AtspiHypertext interface
1831 * instance, or NULL if @obj does not implement #AtspiHypertext.
1834 atspi_accessible_get_hypertext_iface (AtspiAccessible *accessible)
1836 return (_atspi_accessible_is_a (accessible, atspi_interface_hypertext) ?
1837 g_object_ref (ATSPI_HYPERTEXT (accessible)) : NULL);
1841 * atspi_accessible_get_image: (rename-to atspi_accessible_get_image_iface)
1842 * @obj: a pointer to the #AtspiAccessible instance to query.
1844 * Gets the #AtspiImage interface for an #AtspiAccessible.
1846 * Returns: (transfer full): a pointer to an #AtspiImage interface instance, or
1847 * NULL if @obj does not implement #AtspiImage.
1849 * Deprecated: 2.10: Use atspi_accessible_get_image_iface instead.
1852 atspi_accessible_get_image (AtspiAccessible *accessible)
1854 return (_atspi_accessible_is_a (accessible, atspi_interface_image) ?
1855 g_object_ref (ATSPI_IMAGE (accessible)) : NULL);
1859 * atspi_accessible_get_image_iface:
1860 * @obj: a pointer to the #AtspiAccessible instance to query.
1862 * Gets the #AtspiImage interface for an #AtspiAccessible.
1864 * Returns: (transfer full): a pointer to an #AtspiImage interface instance, or
1865 * NULL if @obj does not implement #AtspiImage.
1868 atspi_accessible_get_image_iface (AtspiAccessible *accessible)
1870 return (_atspi_accessible_is_a (accessible, atspi_interface_image) ?
1871 g_object_ref (ATSPI_IMAGE (accessible)) : NULL);
1875 * atspi_accessible_get_selection: (rename-to atspi_accessible_get_selection_iface)
1876 * @obj: a pointer to the #AtspiAccessible instance to query.
1878 * Gets the #AtspiSelection interface for an #AtspiAccessible.
1880 * Returns: (transfer full): a pointer to an #AtspiSelection interface
1881 * instance, or NULL if @obj does not implement #AtspiSelection.
1883 * Deprecated: 2.10: Use atspi_accessible_get_selection_iface instead.
1886 atspi_accessible_get_selection (AtspiAccessible *accessible)
1888 return (_atspi_accessible_is_a (accessible, atspi_interface_selection) ?
1889 g_object_ref (ATSPI_SELECTION (accessible)) : NULL);
1893 * atspi_accessible_get_selection_iface:
1894 * @obj: a pointer to the #AtspiAccessible instance to query.
1896 * Gets the #AtspiSelection interface for an #AtspiAccessible.
1898 * Returns: (transfer full): a pointer to an #AtspiSelection interface
1899 * instance, or NULL if @obj does not implement #AtspiSelection.
1902 atspi_accessible_get_selection_iface (AtspiAccessible *accessible)
1904 return (_atspi_accessible_is_a (accessible, atspi_interface_selection) ?
1905 g_object_ref (ATSPI_SELECTION (accessible)) : NULL);
1910 * atspi_accessible_get_streamable_content:
1911 * @obj: a pointer to the #AtspiAccessible instance to query.
1913 * Gets the #AtspiStreamableContent interface for an #AtspiAccessible.
1915 * Returns: (transfer full): a pointer to an #AtspiStreamableContent interface
1916 * instance, or NULL if @obj does not implement #AtspiStreamableContent.
1918 AtspiStreamableContent *
1919 atspi_accessible_get_streamable_content (AtspiAccessible *accessible)
1921 return (_atspi_accessible_is_a (accessible, atspi_interface_streamable_content) ?
1927 * atspi_accessible_get_table: (rename-to atspi_accessible_get_table_iface)
1928 * @obj: a pointer to the #AtspiAccessible instance to query.
1930 * Gets the #AtspiTable interface for an #AtspiAccessible.
1932 * Returns: (transfer full): a pointer to an #AtspiTable interface instance, or
1933 * NULL if @obj does not implement #AtspiTable.
1935 * Deprecated: 2.10: Use atspi_accessible_get_table_iface instead.
1938 atspi_accessible_get_table (AtspiAccessible *obj)
1940 return (_atspi_accessible_is_a (obj, atspi_interface_table) ?
1941 g_object_ref (ATSPI_TABLE (obj)) : NULL);
1945 * atspi_accessible_get_table_iface:
1946 * @obj: a pointer to the #AtspiAccessible instance to query.
1948 * Gets the #AtspiTable interface for an #AtspiAccessible.
1950 * Returns: (transfer full): a pointer to an #AtspiTable interface instance, or
1951 * NULL if @obj does not implement #AtspiTable.
1954 atspi_accessible_get_table_iface (AtspiAccessible *obj)
1956 return (_atspi_accessible_is_a (obj, atspi_interface_table) ?
1957 g_object_ref (ATSPI_TABLE (obj)) : NULL);
1961 * atspi_accessible_get_table_cell:
1962 * @obj: a pointer to the #AtspiAccessible instance to query.
1964 * Gets the #AtspiTableCell interface for an #AtspiAccessible.
1966 * Returns: (transfer full): a pointer to an #AtspiTableCell interface instance,
1967 * or NULL if @obj does not implement #AtspiTable.
1970 atspi_accessible_get_table_cell (AtspiAccessible *obj)
1972 return (_atspi_accessible_is_a (obj, atspi_interface_table_cell) ?
1973 g_object_ref (ATSPI_TABLE_CELL (obj)) : NULL);
1977 * atspi_accessible_get_text: (rename-to atspi_accessible_get_text_iface)
1978 * @obj: a pointer to the #AtspiAccessible instance to query.
1980 * Gets the #AtspiTable interface for an #AtspiAccessible.
1982 * Returns: (transfer full): a pointer to an #AtspiText interface instance, or
1983 * NULL if @obj does not implement #AtspiText.
1985 * Deprecated: 2.10: Use atspi_accessible_get_text_iface instead.
1988 atspi_accessible_get_text (AtspiAccessible *obj)
1990 return (_atspi_accessible_is_a (obj, atspi_interface_text) ?
1991 g_object_ref (ATSPI_TEXT (obj)) : NULL);
1995 * atspi_accessible_get_text_iface:
1996 * @obj: a pointer to the #AtspiAccessible instance to query.
1998 * Gets the #AtspiTable interface for an #AtspiAccessible.
2000 * Returns: (transfer full): a pointer to an #AtspiText interface instance, or
2001 * NULL if @obj does not implement #AtspiText.
2004 atspi_accessible_get_text_iface (AtspiAccessible *obj)
2006 return (_atspi_accessible_is_a (obj, atspi_interface_text) ?
2007 g_object_ref (ATSPI_TEXT (obj)) : NULL);
2011 * atspi_accessible_get_value: (rename-to atspi_accessible_get_value_iface)
2012 * @obj: a pointer to the #AtspiAccessible instance to query.
2014 * Gets the #AtspiTable interface for an #AtspiAccessible.
2016 * Returns: (transfer full): a pointer to an #AtspiValue interface instance, or
2017 * NULL if @obj does not implement #AtspiValue.
2019 * Deprecated: 2.10: Use atspi_accessible_get_value_iface instead.
2022 atspi_accessible_get_value (AtspiAccessible *accessible)
2024 return (_atspi_accessible_is_a (accessible, atspi_interface_value) ?
2025 g_object_ref (ATSPI_VALUE (accessible)) : NULL);
2029 * atspi_accessible_get_value_iface:
2030 * @obj: a pointer to the #AtspiAccessible instance to query.
2032 * Gets the #AtspiTable interface for an #AtspiAccessible.
2034 * Returns: (transfer full): a pointer to an #AtspiValue interface instance, or
2035 * NULL if @obj does not implement #AtspiValue.
2038 atspi_accessible_get_value_iface (AtspiAccessible *accessible)
2040 return (_atspi_accessible_is_a (accessible, atspi_interface_value) ?
2041 g_object_ref (ATSPI_VALUE (accessible)) : NULL);
2045 append_const_val (GArray *array, const gchar *val)
2047 gchar *dup = g_strdup (val);
2050 g_array_append_val (array, dup);
2054 * atspi_accessible_get_interfaces:
2055 * @obj: The #AtspiAccessible to query.
2057 * A set of pointers to all interfaces supported by an #AtspiAccessible.
2059 * Returns: (element-type gchar*) (transfer full): A #GArray of strings
2060 * describing the interfaces supported by the object. Interfaces are
2061 * denoted in short-hand (i.e. "Component", "Text" etc.).
2064 atspi_accessible_get_interfaces (AtspiAccessible *obj)
2068 g_return_val_if_fail (obj != NULL, NULL);
2070 ret = g_array_new (TRUE, TRUE, sizeof (gchar *));
2072 append_const_val (ret, "Accessible");
2073 if (atspi_accessible_is_action (obj))
2074 append_const_val (ret, "Action");
2075 if (atspi_accessible_is_collection (obj))
2076 append_const_val (ret, "Collection");
2077 if (atspi_accessible_is_component (obj))
2078 append_const_val (ret, "Component");
2079 if (atspi_accessible_is_document (obj))
2080 append_const_val (ret, "Document");
2081 if (atspi_accessible_is_editable_text (obj))
2082 append_const_val (ret, "EditableText");
2083 if (atspi_accessible_is_hypertext (obj))
2084 append_const_val (ret, "Hypertext");
2085 if (atspi_accessible_is_hyperlink (obj))
2086 append_const_val (ret, "Hyperlink");
2087 if (atspi_accessible_is_image (obj))
2088 append_const_val (ret, "Image");
2089 if (atspi_accessible_is_selection (obj))
2090 append_const_val (ret, "Selection");
2091 if (atspi_accessible_is_table (obj))
2092 append_const_val (ret, "Table");
2093 if (atspi_accessible_is_table_cell (obj))
2094 append_const_val (ret, "TableCell");
2095 if (atspi_accessible_is_text (obj))
2096 append_const_val (ret, "Text");
2097 if (atspi_accessible_is_value (obj))
2098 append_const_val (ret, "Value");
2104 _atspi_accessible_new (AtspiApplication *app, const gchar *path)
2106 AtspiAccessible *accessible;
2108 accessible = g_object_new (ATSPI_TYPE_ACCESSIBLE, NULL);
2109 g_return_val_if_fail (accessible != NULL, NULL);
2111 accessible->parent.app = g_object_ref (app);
2112 accessible->parent.path = g_strdup (path);
2118 * atspi_accessible_set_cache_mask:
2119 * @accessible: The #AtspiAccessible to operate on. Must be the desktop or
2120 * the root of an application.
2121 * @mask: An #AtspiCache specifying a bit mask of the types of data to cache.
2123 * Sets the type of data to cache for accessibles.
2124 * If this is not set for an application or is reset to ATSPI_CACHE_UNDEFINED,
2125 * then the desktop's cache flag will be used.
2126 * If the desktop's cache flag is also undefined, then all possible data will
2128 * This function is intended to work around bugs in toolkits where the proper
2129 * events are not raised / to aid in testing for such bugs.
2132 atspi_accessible_set_cache_mask (AtspiAccessible *accessible, AtspiCache mask)
2134 g_return_if_fail (accessible != NULL);
2135 g_return_if_fail (accessible->parent.app != NULL);
2136 g_return_if_fail (accessible == accessible->parent.app->root);
2137 accessible->parent.app->cache = mask;
2138 enable_caching = TRUE;
2142 * atspi_accessible_clear_cache:
2143 * @obj: The #AtspiAccessible whose cache to clear.
2145 * Clears the cached information for the given accessible and all of its
2149 atspi_accessible_clear_cache (AtspiAccessible *obj)
2155 obj->cached_properties = ATSPI_CACHE_NONE;
2157 for (i = 0; i < obj->children->len; i++)
2158 atspi_accessible_clear_cache (g_ptr_array_index (obj->children, i));
2163 * atspi_accessible_get_process_id:
2164 * @accessible: The #AtspiAccessible to query.
2165 * @error: a pointer to a %NULL #GError pointer
2167 * Returns the process id associated with the given accessible. Mainly
2168 * added for debugging; it is a shortcut to explicitly querying the
2169 * accessible's app->bus_name and then calling GetConnectionUnixProcessID.
2171 * Returns: The process ID or undetermined value if @error is set.
2174 atspi_accessible_get_process_id (AtspiAccessible *accessible, GError **error)
2176 DBusMessage *message, *reply;
2177 DBusConnection *bus = _atspi_bus ();
2178 dbus_uint32_t pid = -1;
2181 if (!accessible->parent.app || !accessible->parent.app->bus_name)
2183 g_set_error_literal(error, ATSPI_ERROR, ATSPI_ERROR_IPC, "Process is defunct");
2187 message = dbus_message_new_method_call ("org.freedesktop.DBus",
2188 "/org/freedesktop/DBus",
2189 "org.freedesktop.DBus",
2190 "GetConnectionUnixProcessID");
2191 dbus_message_append_args (message, DBUS_TYPE_STRING,
2192 &accessible->parent.app->bus_name,
2194 dbus_error_init (&d_error);
2195 reply = dbus_connection_send_with_reply_and_block (bus, message, -1, &d_error);
2196 dbus_message_unref (message);
2199 if (!strcmp (dbus_message_get_signature (reply), "u"))
2200 dbus_message_get_args (reply, NULL, DBUS_TYPE_UINT32, &pid, DBUS_TYPE_INVALID);
2201 dbus_message_unref (reply);
2203 if (dbus_error_is_set (&d_error))
2205 g_set_error_literal(error, ATSPI_ERROR, ATSPI_ERROR_IPC, "Process is defunct");
2206 dbus_error_free (&d_error);
2212 _atspi_accessible_get_cache_mask (AtspiAccessible *accessible)
2216 if (!accessible->parent.app)
2217 return ATSPI_CACHE_NONE;
2219 mask = accessible->parent.app->cache;
2220 if (mask == ATSPI_CACHE_UNDEFINED &&
2221 accessible->parent.app->root &&
2222 accessible->parent.app->root->accessible_parent)
2224 AtspiAccessible *desktop = atspi_get_desktop (0);
2225 mask = desktop->parent.app->cache;
2226 g_object_unref (desktop);
2229 if (mask == ATSPI_CACHE_UNDEFINED)
2230 mask = ATSPI_CACHE_DEFAULT;
2236 _atspi_accessible_test_cache (AtspiAccessible *accessible, AtspiCache flag)
2238 AtspiCache mask = _atspi_accessible_get_cache_mask (accessible);
2239 AtspiCache result = accessible->cached_properties & mask & flag;
2240 if (accessible->states && atspi_state_set_contains (accessible->states, ATSPI_STATE_TRANSIENT))
2242 return (result != 0 && (atspi_main_loop || enable_caching ||
2243 flag == ATSPI_CACHE_INTERFACES) &&
2248 _atspi_accessible_add_cache (AtspiAccessible *accessible, AtspiCache flag)
2250 AtspiCache mask = _atspi_accessible_get_cache_mask (accessible);
2252 accessible->cached_properties |= flag & mask;
2256 * atspi_accessible_get_locale:
2257 * @accessible: an #AtspiAccessible
2259 * Gets a UTF-8 string indicating the POSIX-style LC_MESSAGES locale
2264 * Returns: a UTF-8 string indicating the POSIX-style LC_MESSAGES
2265 * locale of @accessible.
2268 atspi_accessible_get_object_locale (AtspiAccessible *accessible, GError **error)
2272 g_return_val_if_fail (accessible != NULL, NULL);
2274 locale = g_object_get_qdata (G_OBJECT (accessible), quark_locale);
2277 if (!_atspi_dbus_get_property (accessible, atspi_interface_accessible,
2278 "Locale", error, "s", &locale))
2281 g_object_set_qdata_full (G_OBJECT (accessible), quark_locale, locale,
2288 free_value (gpointer data)
2290 GValue *value = data;
2292 g_value_unset (value);
2297 _atspi_accessible_ref_cache (AtspiAccessible *accessible)
2299 AtspiAccessiblePrivate *priv = accessible->priv;
2301 priv->cache_ref_count++;
2303 return g_hash_table_ref (priv->cache);
2304 priv->cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
2310 _atspi_accessible_unref_cache (AtspiAccessible *accessible)
2312 AtspiAccessiblePrivate *priv = accessible->priv;
2316 g_hash_table_unref (priv->cache);
2317 if (--priv->cache_ref_count == 0)