State and action fixes
[platform/upstream/at-spi2-core.git] / atspi / atspi-accessible.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2001, 2002 Sun Microsystems Inc.,
6  * Copyright 2001, 2002 Ximian, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include "atspi-private.h"
25 #include <string.h>
26
27 static void
28 atspi_action_interface_init (AtspiAction *action)
29 {
30 }
31
32 static void
33 atspi_component_interface_init (AtspiComponent *component)
34 {
35 }
36
37 atspi_editable_text_interface_init (AtspiEditableText *editable_text)
38 {
39 }
40
41 static void
42 atspi_image_interface_init (AtspiImage *image)
43 {
44 }
45
46 static void
47 atspi_selection_interface_init (AtspiSelection *selection)
48 {
49 }
50
51 static void
52 atspi_table_interface_init (AtspiTable *table)
53 {
54 }
55
56 static void
57 atspi_text_interface_init (AtspiText *text)
58 {
59 }
60
61 static void
62 atspi_value_interface_init (AtspiValue *value)
63 {
64 }
65
66 G_DEFINE_TYPE_WITH_CODE (AtspiAccessible, atspi_accessible, ATSPI_TYPE_OBJECT,
67                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_ACTION, atspi_action_interface_init)
68                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_COMPONENT, atspi_component_interface_init)
69                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_EDITABLE_TEXT, atspi_editable_text_interface_init)
70                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_IMAGE, atspi_image_interface_init)
71                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_SELECTION, atspi_selection_interface_init)
72                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_TABLE, atspi_table_interface_init)
73                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_TEXT, atspi_text_interface_init)
74                          G_IMPLEMENT_INTERFACE (ATSPI_TYPE_VALUE, atspi_value_interface_init))
75
76 static void
77 atspi_accessible_init (AtspiAccessible *accessible)
78 {
79 }
80
81 static void
82 atspi_accessible_finalize (GObject *obj)
83 {
84   /*AtspiAccessible *accessible = ATSPI_ACCESSIBLE (obj); */
85
86   /* TODO: Unref parent/children, etc. */
87 }
88
89 static void
90 atspi_accessible_class_init (AtspiAccessibleClass *klass)
91 {
92   GObjectClass *object_class = G_OBJECT_CLASS (klass);
93
94   object_class->finalize = atspi_accessible_finalize;
95 }
96
97 /* TODO: Generate following from spec? */
98 static const char *role_names [] =
99 {
100   "invalid",
101   "accel-label",
102   "alert",
103   "animation",
104   "arrow",
105   "calendar",
106   "canvas",
107   "check-box",
108   "check-menu-item",
109   "color-chooser",
110   "column-header",
111   "combo-box",
112   "date-editor",
113   "desktop-icon",
114   "desktop-frame",
115   "dial",
116   "dialog",
117   "directory-pane",
118   "drawing-area",
119   "file-chooser",
120   "filler",
121   "font-chooser",
122   "frame",
123   "glass-pane",
124   "html-container",
125   "icon",
126   "image",
127   "internalframe",
128   "label",
129   "layered-pane",
130   "list",
131   "list-item",
132   "menu",
133   "menu-bar",
134   "menu-item",
135   "option-pane",
136   "page-tab",
137   "page-tab-list",
138   "panel",
139   "password-text",
140   "popup-menu",
141   "progress-bar",
142   "push-button",
143   "radio-button",
144   "radio-menu-item",
145   "root-pane",
146   "row-header",
147   "scroll-bar",
148   "scroll-pane",
149   "separator",
150   "slider",
151   "spin-button",
152   "split-pane",
153   "statusbar",
154   "table",
155   "table-cell",
156   "table-column-header",
157   "table-row-header",
158   "tear-off-menu-item",
159   "terminal",
160   "text",
161   "toggle-button",
162   "tool-bar",
163   "tool-tip",
164   "tree",
165   "tree-table",
166   "unknown",
167   "viewport",
168   "window",
169   NULL,
170   "header",
171   "fooler",
172   "paragraph",
173   "ruler",
174   "application",
175   "autocomplete",
176   "editbar",
177   "embedded",
178   "entry",
179   "chart",
180   "caption",
181   "document_frame",
182   "heading",
183   "page",
184   "section",
185   "form",
186   "redundant object",
187   "link",
188   "input method window"
189 };
190
191 #define MAX_ROLES (sizeof (role_names) / sizeof (char *))
192
193 /**
194  * atspi_role_get_name
195  * @role: an #AtspiAccessibleRole object to query.
196  *
197  * Get a localizeable string that indicates the name of an #AtspiAccessibleRole.
198  * <em>DEPRECATED.</em>
199  *
200  * Returns: a localizable string name for an #AtspiAccessibleRole enumerated type.
201  **/
202 gchar *
203 atspi_role_get_name (AtspiRole role)
204 {
205   if (role < MAX_ROLES && role_names [(int) role])
206     {
207       return g_strdup (role_names [(int) role]);
208     }
209   else
210     {
211       return g_strdup ("");
212     }
213 }
214
215 /**
216  * atspi_accessible_get_name:
217  * @obj: a pointer to the #AtspiAccessible object on which to operate.
218  *
219  * Get the name of an #AtspiAccessible object.
220  *
221  * Returns: a UTF-8 string indicating the name of the #AtspiAccessible object.
222  * or NULL on exception
223  **/
224 gchar *
225 atspi_accessible_get_name (AtspiAccessible *obj, GError **error)
226 {
227   g_return_val_if_fail (obj != NULL, NULL);
228   if (!(obj->cached_properties & ATSPI_CACHE_NAME))
229   {
230     if (!_atspi_dbus_get_property (obj, atspi_interface_accessible, "Name", NULL, "s", &obj->name))
231       return NULL;
232     obj->cached_properties |= ATSPI_CACHE_NAME;
233   }
234   return g_strdup (obj->name);
235 }
236
237 /**
238  * atspi_accessible_get_description:
239  * @obj: a pointer to the #AtspiAccessible object on which to operate.
240  *
241  * Get the description of an #AtspiAccessible object.
242  *
243  * Returns: a UTF-8 string describing the #AtspiAccessible object.
244  * or NULL on exception
245  **/
246 gchar *
247 atspi_accessible_get_description (AtspiAccessible *obj, GError **error)
248 {
249   g_return_val_if_fail (obj != NULL, NULL);
250
251   if (!(obj->cached_properties & ATSPI_CACHE_DESCRIPTION))
252   {
253     if (!_atspi_dbus_call (obj, atspi_interface_accessible, "GetDescription", NULL, "=>s", &obj->description))
254       return NULL;
255     obj->cached_properties |= ATSPI_CACHE_DESCRIPTION;
256   }
257   return g_strdup (obj->description);
258 }
259
260 const char *str_parent = "Parent";
261
262 /**
263  * atspi_accessible_get_parent:
264  * @obj: a pointer to the #AtspiAccessible object to query.
265  *
266  * Get an #AtspiAccessible object's parent container.
267  *
268  * Returns: (transfer full): a pointer to the #AtspiAccessible object which
269  *          contains the given #AtspiAccessible instance, or NULL if the @obj
270  *          has no parent container.
271  *
272  **/
273 AtspiAccessible *
274 atspi_accessible_get_parent (AtspiAccessible *obj, GError **error)
275 {
276   g_return_val_if_fail (obj != NULL, NULL);
277
278   if (!(obj->cached_properties & ATSPI_CACHE_PARENT))
279   {
280     DBusMessage *message, *reply;
281     DBusMessageIter iter, iter_variant;
282     message = dbus_message_new_method_call (obj->parent.app->bus_name,
283                                             obj->parent.path,
284                                             DBUS_INTERFACE_PROPERTIES, "Get");
285     if (!message)
286       return NULL;
287     dbus_message_append_args (message, DBUS_TYPE_STRING, &atspi_interface_accessible,
288                                DBUS_TYPE_STRING, &str_parent,
289                               DBUS_TYPE_INVALID);
290     reply = _atspi_dbus_send_with_reply_and_block (message);
291     if (!reply ||
292        (strcmp (dbus_message_get_signature (reply), "v") != 0))
293       return NULL;
294     dbus_message_iter_init (reply, &iter);
295     dbus_message_iter_recurse (&iter, &iter_variant);
296     obj->accessible_parent = _atspi_dbus_return_accessible_from_iter (&iter_variant);
297     dbus_message_unref (reply);
298     obj->cached_properties |= ATSPI_CACHE_PARENT;
299   }
300   if (!obj->accessible_parent)
301     return NULL;
302   return g_object_ref (obj->accessible_parent);
303 }
304
305 /**
306  * atspi_accessible_get_child_count:
307  * @obj: a pointer to the #AtspiAccessible object on which to operate.
308  *
309  * Get the number of children contained by an #AtspiAccessible object.
310  *
311  * Returns: a #long indicating the number of #AtspiAccessible children
312  *          contained by an #AtspiAccessible object. or -1 on exception
313  *
314  **/
315 gint
316 atspi_accessible_get_child_count (AtspiAccessible *obj, GError *error)
317 {
318   g_return_val_if_fail (obj != NULL, -1);
319
320   /* TODO: MANAGES_DESCENDANTS */
321   return g_list_length (obj->children);
322 }
323
324 /**
325  * atspi_accessible_get_child_at_index:
326  * @obj: a pointer to the #AtspiAccessible object on which to operate.
327  * @child_index: a #long indicating which child is specified.
328  *
329  * Get the #AtspiAccessible child of an #AtspiAccessible object at a given index.
330  *
331  * Returns: (transfer full): a pointer to the #AtspiAccessible child object at
332  * index @child_index. or NULL on exception
333  **/
334 AtspiAccessible *
335 atspi_accessible_get_child_at_index (AtspiAccessible *obj,
336                             gint    child_index,
337                             GError **error)
338 {
339   AtspiAccessible *child;
340
341   g_return_val_if_fail (obj != NULL, NULL);
342
343   /* TODO: ManagesDescendants */
344   child = g_list_nth_data (obj->children, child_index);
345   if (!child)
346     return NULL;
347   return g_object_ref (child);
348 }
349
350 /**
351  * atspi_accessible_get_index_in_parent
352  * @obj: a pointer to the #AtspiAccessible object on which to operate.
353  *
354  * Get the index of an #AtspiAccessible object in its containing #AtspiAccessible.
355  *
356  * Returns: a #glong indicating the index of the #AtspiAccessible object
357  *          in its parent (i.e. containing) #AtspiAccessible instance,
358  *          or -1 if @obj has no containing parent or on exception.
359  **/
360 gint
361 atspi_accessible_get_index_in_parent (AtspiAccessible *obj, GError **error)
362 {
363   GList *l;
364   gint i;
365
366   g_return_val_if_fail (obj != NULL, -1);
367   if (!obj->accessible_parent) return -1;
368   l = obj->accessible_parent->children;
369   while (l)
370   {
371     if (l->data == obj) return i;
372     l = g_list_next (l);
373     i++;
374   }
375   return -1;
376 }
377
378 typedef struct
379 {
380   dbus_uint32_t type;
381   GArray *targets;
382 } Accessibility_Relation;
383
384 /**
385  * atspi_accessible_get_relation_set:
386  * @obj: a pointer to the #AtspiAccessible object on which to operate.
387  *
388  * Get the set of #AtspiRelation objects which describe this #AtspiAccessible object's
389  *       relationships with other #AtspiAccessible objects.
390  *
391  * Returns: an array of #AtspiAccessibleRelation pointers. or NULL on exception
392  * TODO:: Annotate array type
393  **/
394 GArray *
395 atspi_accessible_get_relation_set (AtspiAccessible *obj, GError **error)
396 {
397   int i;
398   int n_relations;
399   GArray *relation_set;
400
401   g_return_val_if_fail (obj != NULL, NULL);
402
403   if (!_atspi_dbus_call (obj, atspi_interface_accessible, "GetRelationSet", error, "=>a(uao)", &relation_set))
404     return NULL;
405
406   return relation_set;
407 }
408
409 /**
410  * atspi_accessible_get_role:
411  * @obj: a pointer to the #AtspiAccessible object on which to operate.
412  *
413  * Get the UI role of an #AtspiAccessible object.
414  * A UTF-8 string describing this role can be obtained via atspi_accessible_getRoleName ().
415  *
416  * Returns: the #AtspiRole of the object.
417  *
418  **/
419 AtspiRole
420 atspi_accessible_get_role (AtspiAccessible *obj, GError **error)
421 {
422   g_return_val_if_fail (obj != NULL, ATSPI_ROLE_INVALID);
423
424   if (!(obj->cached_properties & ATSPI_CACHE_ROLE))
425   {
426     dbus_uint32_t role;
427     /* TODO: Make this a property */
428     if (_atspi_dbus_call (obj, atspi_interface_accessible, "GetRole", NULL, "=>u", &role))
429     {
430       obj->cached_properties |= ATSPI_CACHE_ROLE;
431       obj->role = role;
432     }
433   }
434   return obj->role;
435 }
436
437 /**
438  * atspi_accessible_get_role_name:
439  * @obj: a pointer to the #AtspiAccessible object on which to operate.
440  *
441  * Get a UTF-8 string describing the role this object plays in the UI.
442  * This method will return useful values for roles that fall outside the
443  * enumeration used in atspi_accessible_getRole ().
444  *
445  * Returns: a UTF-8 string specifying the role of this #AtspiAccessible object.
446  *
447  **/
448 gchar *
449 atspi_accessible_get_role_name (AtspiAccessible *obj, GError **error)
450 {
451   char *retval = NULL;
452
453   g_return_val_if_fail (obj != NULL, g_strdup ("invalid"));
454
455   _atspi_dbus_call (obj, atspi_interface_accessible, "GetRoleName", error, "=>s", &retval);
456
457   return retval;
458 }
459
460 /**
461  * atspi_accessible_get_localized_role_name:
462  * @obj: a pointer to the #AtspiAccessible object on which to operate.
463  *
464  * Get a UTF-8 string describing the (localized) role this object plays in the UI.
465  * This method will return useful values for roles that fall outside the
466  * enumeration used in atspi_accessible_getRole ().
467  *
468  * Returns: a UTF-8 string specifying the role of this #AtspiAccessible object.
469  *
470  **/
471 gchar *
472 atspi_accessible_get_localized_role_name (AtspiAccessible *obj, GError **error)
473 {
474   char *retval = NULL;
475
476   g_return_val_if_fail (obj != NULL, g_strdup ("invalid"));
477
478   _atspi_dbus_call (obj, atspi_interface_accessible, "GetLocalizedRoleName", error, "=>s", &retval);
479
480   return retval;
481 }
482
483 /**
484  * atspi_accessible_get_state_set:
485  * @obj: a pointer to the #AtspiAccessible object on which to operate.
486  *
487  * Gets the current state of an object.
488  *
489  * Returns: (transfer full): a pointer to an #AtspiStateSet representing the
490  *          object's current state.
491  **/
492 AtspiStateSet *
493 atspi_accessible_get_state_set (AtspiAccessible *obj)
494 {
495   return obj->states;
496 }
497
498 /**
499  * atspi_accessible_get_attributes:
500  * @obj: The #AtspiAccessible being queried.
501  *
502  * Get the #AttributeSet representing any assigned 
503  * name-value pair attributes or annotations for this object.
504  * For typographic, textual, or textually-semantic attributes, see
505  * atspi_text_get_attributes instead.
506  *
507  * Returns: (element-type gchar* gchar*) (transfer full): The name-value-pair
508  *          attributes assigned to this object.
509  */
510 GHashTable *
511 atspi_accessible_get_attributes (AtspiAccessible *obj, GError **error)
512 {
513   DBusMessage *message;
514   GHashTable *ret;
515
516     g_return_val_if_fail (obj != NULL, NULL);
517
518   message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetAttributes", error, "");
519   ret = _atspi_dbus_hash_from_message (message);
520   dbus_message_unref (message);
521   return ret;
522 }
523
524 /**
525  * atspi_accessible_get_attributes_as_array:
526  * @obj: The #AtspiAccessible being queried.
527  *
528  * Get the #AttributeSet representing any assigned 
529  * name-value pair attributes or annotations for this object.
530  * For typographic, textual, or textually-semantic attributes, see
531  * atspi_text_get_attributes_as_array instead.
532  *
533  * Returns: (element-type gchar*) (transfer full): The name-value-pair
534  *          attributes assigned to this object.
535  */
536 GArray *
537 atspi_accessible_get_attributes_as_array (AtspiAccessible *obj, GError **error)
538 {
539   DBusMessage *message;
540   GArray *ret;
541
542     g_return_val_if_fail (obj != NULL, NULL);
543
544   message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetAttributes", error, "");
545   ret = _atspi_dbus_attribute_array_from_message (message);
546   dbus_message_unref (message);
547   return ret;
548 }
549
550 /**
551  * atspi_accessible_get_host_application:
552  * @obj: The #AtspiAccessible being queried.
553  *
554  * Get the containing #AtspiApplication for an object.
555  *
556  * Returns: (transfer full): the containing AtspiApplication instance for
557  *          this object.
558  */
559 AtspiAccessible *
560 atspi_accessible_get_host_application (AtspiAccessible *obj, GError **error)
561 {
562   AtspiAccessible *parent;
563
564   for (;;)
565   {
566     parent = atspi_accessible_get_parent (obj, NULL);
567     if (!parent || parent == obj ||
568         atspi_accessible_get_role (parent, NULL) == ATSPI_ROLE_DESKTOP_FRAME)
569     return obj;
570     obj = parent;
571   }
572 }
573
574 /* Interface query methods */
575
576 /**
577  * atspi_accessible_is_action:
578  * @obj: a pointer to the #AtspiAccessible instance to query.
579  *
580  * Query whether the specified #AtspiAccessible implements #AtspiAction.
581  *
582  * Returns: #TRUE if @obj implements the #AtspiAction interface,
583  *          #FALSE otherwise.
584  **/
585 gboolean
586 atspi_accessible_is_action (AtspiAccessible *obj)
587 {
588   return _atspi_accessible_is_a (obj,
589                               atspi_interface_action);
590 }
591
592 /**
593  * atspi_accessible_is_application:
594  * @obj: a pointer to the #AtspiAccessible instance to query.
595  *
596  * Query whether the specified #AtspiAccessible implements #AtspiApplication.
597  *
598  * Returns: #TRUE if @obj implements the #AtspiApplication interface,
599  *          #FALSE otherwise.
600  **/
601 gboolean
602 atspi_accessible_is_application (AtspiAccessible *obj)
603 {
604   return _atspi_accessible_is_a (obj,
605                               atspi_interface_application);
606 }
607
608 /**                      
609  * atspi_accessible_is_collection:                                                                                                                                                                          * @obj: a pointer to the #AtspiAccessible instance to query.                                                                                                                                          
610  *                          
611  * Query whether the specified #AtspiAccessible implements #AtspiCollection.    
612  * Returns: #TRUE if @obj implements the #AtspiCollection interface,                                                                                                               
613  *          #FALSE otherwise.
614  **/
615 gboolean
616 atspi_accessible_is_collection (AtspiAccessible *obj)
617 {
618 #if 0
619      g_warning ("Collections not implemented");
620      return _atspi_accessible_is_a (obj,
621                               atspi_interface_collection);
622 #else
623      return FALSE;
624 #endif
625 }
626
627 /**
628  * atspi_accessible_is_component:
629  * @obj: a pointer to the #AtspiAccessible instance to query.
630  *
631  * Query whether the specified #AtspiAccessible implements #AtspiComponent.
632  *
633  * Returns: #TRUE if @obj implements the #AtspiComponent interface,
634  *          #FALSE otherwise.
635  **/
636 gboolean
637 atspi_accessible_is_component (AtspiAccessible *obj)
638 {
639   return _atspi_accessible_is_a (obj,
640                               atspi_interface_component);
641 }
642
643 /**
644  * atspi_accessible_is_document:
645  * @obj: a pointer to the #AtspiAccessible instance to query.
646  *
647  * Query whether the specified #AtspiAccessible implements #AtspiDocument.
648  *
649  * Returns: #TRUE if @obj implements the #AtspiDocument interface,
650  *          #FALSE otherwise.
651  **/
652 gboolean
653 atspi_accessible_is_document (AtspiAccessible *obj)
654 {
655   return _atspi_accessible_is_a (obj,
656                               atspi_interface_document);
657 }
658
659 /**
660  * atspi_accessible_is_editable_text:
661  * @obj: a pointer to the #AtspiAccessible instance to query.
662  *
663  * Query whether the specified #AtspiAccessible implements #AtspiEditableText.
664  *
665  * Returns: #TRUE if @obj implements the #AtspiEditableText interface,
666  *          #FALSE otherwise.
667  **/
668 gboolean
669 atspi_accessible_is_editable_text (AtspiAccessible *obj)
670 {
671   return _atspi_accessible_is_a (obj,
672                               atspi_interface_editable_text);
673 }
674                                                                                                                                                                         
675 /**
676  * atspi_accessible_is_hypertext:
677  * @obj: a pointer to the #AtspiAccessible instance to query.
678  *
679  * Query whether the specified #AtspiAccessible implements #AtspiHypertext.
680  *
681  * Returns: #TRUE if @obj implements the #AtspiHypertext interface,
682  *          #FALSE otherwise.
683  **/
684 gboolean
685 atspi_accessible_is_hypertext (AtspiAccessible *obj)
686 {
687   return _atspi_accessible_is_a (obj,
688                               atspi_interface_hypertext);
689 }
690
691 /**
692  * atspi_accessible_is_image:
693  * @obj: a pointer to the #AtspiAccessible instance to query.
694  *
695  * Query whether the specified #AtspiAccessible implements #AtspiImage.
696  *
697  * Returns: #TRUE if @obj implements the #AtspiImage interface,
698  *          #FALSE otherwise.
699 **/
700 gboolean
701 atspi_accessible_is_image (AtspiAccessible *obj)
702 {
703   return _atspi_accessible_is_a (obj,
704                               atspi_interface_image);
705 }
706
707 /**
708  * atspi_accessible_is_selection:
709  * @obj: a pointer to the #AtspiAccessible instance to query.
710  *
711  * Query whether the specified #AtspiAccessible implements #AtspiSelection.
712  *
713  * Returns: #TRUE if @obj implements the #AtspiSelection interface,
714  *          #FALSE otherwise.
715 **/
716 gboolean
717 atspi_accessible_is_selection (AtspiAccessible *obj)
718 {
719   return _atspi_accessible_is_a (obj,
720                               atspi_interface_selection);
721 }
722
723 /**
724  * atspi_accessible_is_table:
725  * @obj: a pointer to the #AtspiAccessible instance to query.
726  *
727  * Query whether the specified #AtspiAccessible implements #AtspiTable.
728  *
729  * Returns: #TRUE if @obj implements the #AtspiTable interface,
730  *          #FALSE otherwise.
731 **/
732 gboolean
733 atspi_accessible_is_table (AtspiAccessible *obj)
734 {
735   return _atspi_accessible_is_a (obj,
736                               atspi_interface_table);
737 }
738
739 /**
740  * atspi_accessible_is_streamable_content:
741  * @obj: a pointer to the #AtspiAccessible instance to query.
742  *
743  * Query whether the specified #AtspiAccessible implements
744  *          #AtspiStreamableContent.
745  *
746  * Returns: #TRUE if @obj implements the #AtspiStreamableContent interface,
747  *          #FALSE otherwise.
748 **/
749 gboolean
750 atspi_accessible_is_streamable_content (AtspiAccessible *obj)
751 {
752 #if 0
753   return _atspi_accessible_is_a (obj,
754                               atspi_interface_streamable_content);
755 #else
756   g_warning ("Streamable content not implemented");
757   return FALSE;
758 #endif
759 }
760
761 /**
762  * atspi_accessible_is_text:
763  * @obj: a pointer to the #AtspiAccessible instance to query.
764  *
765  * Query whether the specified #AtspiAccessible implements #AtspiText.
766  *
767  * Returns: #TRUE if @obj implements the #AtspiText interface,
768  *          #FALSE otherwise.
769 **/
770 gboolean
771 atspi_accessible_is_text (AtspiAccessible *obj)
772 {
773   return _atspi_accessible_is_a (obj,
774                               atspi_interface_text);
775 }
776
777 /**
778  * atspi_accessible_is_value:
779  * @obj: a pointer to the #AtspiAccessible instance to query.
780  *
781  * Query whether the specified #AtspiAccessible implements #AtspiValue.
782  *
783  * Returns: #TRUE if @obj implements the #AtspiValue interface,
784  *          #FALSE otherwise.
785 **/
786 gboolean
787 atspi_accessible_is_value (AtspiAccessible *obj)
788 {
789   return _atspi_accessible_is_a (obj,
790                               atspi_interface_value);
791 }
792
793 /**
794  * atspi_accessible_get_application:
795  * @obj: a pointer to the #AtspiAccessible instance to query.
796  *
797  * Get the #AtspiApplication interface for an #AtspiAccessible.
798  *
799  * Returns: a pointer to an #AtspiApplication interface instance, or
800  *          NULL if @obj does not implement #AtspiApplication.
801  **/
802 AtspiApplication *
803 atspi_accessible_get_application (AtspiAccessible *accessible)
804 {
805   return (_atspi_accessible_is_a (accessible, atspi_interface_application) ?
806           g_object_ref (ATSPI_ACTION (accessible)) : NULL);  
807 }
808
809 /**
810  * atspi_accessible_get_action:
811  * @obj: a pointer to the #AtspiAccessible instance to query.
812  *
813  * Get the #AtspiAction interface for an #AtspiAccessible.
814  *
815  * Returns: (transfer full): a pointer to an #AtspiAction interface
816  *          instance, or NULL if @obj does not implement #AtspiAction.
817  **/
818 AtspiAction *
819 atspi_accessible_get_action (AtspiAccessible *accessible)
820 {
821   return (_atspi_accessible_is_a (accessible, atspi_interface_action) ?
822           g_object_ref (ATSPI_ACTION (accessible)) : NULL);  
823 }
824
825 /**
826  * atspi_accessible_get_collection:
827  * @obj: a pointer to the #AtspiAccessible instance to query.
828  *
829  * Get the #AtspiCollection interface for an #AtspiAccessible.
830  *
831  * Returns: (transfer full): a pointer to an #AtspiCollection interface
832  *          instance, or NULL if @obj does not implement #AtspiCollection.
833  **/
834 AtspiCollection *
835 atspi_accessible_get_collection (AtspiAccessible *accessible)
836 {
837   return (_atspi_accessible_is_a (accessible, atspi_interface_collection) ?
838           g_object_ref (ATSPI_COLLECTION (accessible)) : NULL);  
839 }
840
841 /**
842  * atspi_accessible_get_component:
843  * @obj: a pointer to the #AtspiAccessible instance to query.
844  *
845  * Get the #AtspiComponent interface for an #AtspiAccessible.
846  *
847  * Returns: (transfer full): a pointer to an #AtspiComponent interface
848  *          instance, or NULL if @obj does not implement #AtspiComponent.
849  **/
850 AtspiComponent *
851 atspi_accessible_get_component (AtspiAccessible *obj)
852 {
853   return (_atspi_accessible_is_a (obj, atspi_interface_component) ?
854           g_object_ref (ATSPI_COMPONENT (obj)) : NULL);
855 }
856
857 /**
858  * atspi_accessible_get_document:
859  * @obj: a pointer to the #AtspiAccessible instance to query.
860  *
861  * Get the #AtspiDocument interface for an #AtspiAccessible.
862  *
863  * Returns: (transfer full): a pointer to an #AtspiDocument interface
864  *          instance, or NULL if @obj does not implement #AtspiDocument.
865  **/
866 AtspiDocument *
867 atspi_accessible_get_document (AtspiAccessible *accessible)
868 {
869   return (_atspi_accessible_is_a (accessible, atspi_interface_document) ?
870           g_object_ref (ATSPI_DOCUMENT (accessible)) : NULL);  
871 }
872
873 /**
874  * atspi_accessible_get_editable_text:
875  * @obj: a pointer to the #AtspiAccessible instance to query.
876  *
877  * Get the #AtspiEditableText interface for an #AtspiAccessible.
878  *
879  * Returns: (transfer full): a pointer to an #AtspiEditableText interface
880  *          instance, or NULL if @obj does not implement #AtspiEditableText.
881  **/
882 AtspiEditableText *
883 atspi_accessible_get_editable_text (AtspiAccessible *accessible)
884 {
885   return (_atspi_accessible_is_a (accessible, atspi_interface_editable_text) ?
886           g_object_ref (ATSPI_EDITABLE_TEXT (accessible)) : NULL);  
887 }
888
889 /**
890  * atspi_accessible_get_hypertext:
891  * @obj: a pointer to the #AtspiAccessible instance to query.
892  *
893  * Get the #AtspiHypertext interface for an #AtspiAccessible.
894  *
895  * Returns: (transfer full): a pointer to an #AtspiHypertext interface
896  *          instance, or NULL if @obj does not implement #AtspiHypertext.
897  **/
898 AtspiHypertext *
899 atspi_accessible_get_hypertext (AtspiAccessible *accessible)
900 {
901   return (_atspi_accessible_is_a (accessible, atspi_interface_hypertext) ?
902           g_object_ref (ATSPI_HYPERTEXT (accessible)) : NULL);  
903 }
904
905 /**
906  * atspi_accessible_get_image:
907  * @obj: a pointer to the #AtspiAccessible instance to query.
908  *
909  * Get the #AtspiImage interface for an #AtspiAccessible.
910  *
911  * Returns: (transfer full): a pointer to an #AtspiImage interface instance, or
912  *          NULL if @obj does not implement #AtspiImage.
913  **/
914 AtspiImage *
915 atspi_accessible_get_image (AtspiAccessible *accessible)
916 {
917   return (_atspi_accessible_is_a (accessible, atspi_interface_image) ?
918           g_object_ref (ATSPI_IMAGE (accessible)) : NULL);  
919 }
920
921 /**
922  * atspi_accessible_get_selection:
923  * @obj: a pointer to the #AtspiAccessible instance to query.
924  *
925  * Get the #AtspiSelection interface for an #AtspiAccessible.
926  *
927  * Returns: (transfer full): a pointer to an #AtspiSelection interface
928  *          instance, or NULL if @obj does not implement #AtspiSelection.
929  **/
930 AtspiSelection *
931 atspi_accessible_get_selection (AtspiAccessible *accessible)
932 {
933   return (_atspi_accessible_is_a (accessible, atspi_interface_selection) ?
934           g_object_ref (ATSPI_SELECTION (accessible)) : NULL);  
935 }
936
937 #if 0
938 /**
939  * atspi_accessible_get_streamable_content:
940  * @obj: a pointer to the #AtspiAccessible instance to query.
941  *
942  * Get the #AtspiStreamableContent interface for an #AtspiAccessible.
943  *
944  * Returns: (transfer full): a pointer to an #AtspiStreamableContent interface
945  *          instance, or NULL if @obj does not implement #AtspiStreamableContent.
946  **/
947 AtspiStreamableContent *
948 atspi_accessible_get_streamable_content (AtspiAccessible *accessible)
949 {
950   return (_atspi_accessible_is_a (accessible, atspi_interface_streamable_content) ?
951           accessible : NULL);  
952 }
953 #endif
954
955 /**
956  * atspi_accessible_get_table:
957  * @obj: a pointer to the #AtspiAccessible instance to query.
958  *
959  * Get the #AtspiTable interface for an #AtspiAccessible.
960  *
961  * Returns: (transfer full): a pointer to an #AtspiTable interface instance, or
962  *          NULL if @obj does not implement #AtspiTable.
963  **/
964 AtspiTable *
965 atspi_accessible_get_table (AtspiAccessible *obj)
966 {
967   return (_atspi_accessible_is_a (obj, atspi_interface_table) ?
968           g_object_ref (ATSPI_TABLE (obj)) : NULL);  
969 }
970
971 /**
972  * atspi_accessible_get_text:
973  * @obj: a pointer to the #AtspiAccessible instance to query.
974  *
975  * Get the #AtspiTable interface for an #AtspiAccessible.
976  *
977  * Returns: (transfer full): a pointer to an #AtspiText interface instance, or
978  *          NULL if @obj does not implement #AtspiTable.
979  **/
980 AtspiText *
981 atspi_accessible_get_text (AtspiAccessible *obj)
982 {
983   return (_atspi_accessible_is_a (obj, atspi_interface_text) ?
984           g_object_ref (ATSPI_TEXT (obj)) : NULL);
985 }
986
987 /**
988  * atspi_accessible_get_value:
989  * @obj: a pointer to the #AtspiAccessible instance to query.
990  *
991  * Get the #AtspiTable interface for an #AtspiAccessible.
992  *
993  * Returns: (transfer full): a pointer to an #AtspiValue interface instance, or
994  *          NULL if @obj does not implement #AtspiValue.
995  **/
996 AtspiValue *
997 atspi_accessible_get_value (AtspiAccessible *accessible)
998 {
999   return (_atspi_accessible_is_a (accessible, atspi_interface_value) ?
1000           g_object_ref (ATSPI_VALUE (accessible)) : NULL);  
1001 }
1002
1003 #if 0
1004 static gboolean
1005 cspi_init_relation_type_table (AccessibleRelationType *relation_type_table)
1006 {
1007   int i;
1008   for (i = 0; i < Accessibility_RELATION_LAST_DEFINED; ++i)
1009     {
1010       relation_type_table [i] = SPI_RELATION_NULL;
1011     }
1012   relation_type_table [Accessibility_RELATION_NULL] = SPI_RELATION_NULL;
1013   relation_type_table [Accessibility_RELATION_LABEL_FOR] = SPI_RELATION_LABEL_FOR;
1014   relation_type_table [Accessibility_RELATION_LABELLED_BY] = SPI_RELATION_LABELED_BY;
1015   relation_type_table [Accessibility_RELATION_CONTROLLER_FOR] = SPI_RELATION_CONTROLLER_FOR;
1016   relation_type_table [Accessibility_RELATION_CONTROLLED_BY] = SPI_RELATION_CONTROLLED_BY;
1017   relation_type_table [Accessibility_RELATION_MEMBER_OF] = SPI_RELATION_MEMBER_OF;
1018   relation_type_table [Accessibility_RELATION_TOOLTIP_FOR] = SPI_RELATION_NULL;
1019   relation_type_table [Accessibility_RELATION_NODE_CHILD_OF] = SPI_RELATION_NODE_CHILD_OF;
1020   relation_type_table [Accessibility_RELATION_EXTENDED] = SPI_RELATION_EXTENDED;
1021   relation_type_table [Accessibility_RELATION_FLOWS_TO] = SPI_RELATION_FLOWS_TO;
1022   relation_type_table [Accessibility_RELATION_FLOWS_FROM] = SPI_RELATION_FLOWS_FROM;
1023   relation_type_table [Accessibility_RELATION_SUBWINDOW_OF] = SPI_RELATION_SUBWINDOW_OF;
1024   relation_type_table [Accessibility_RELATION_EMBEDS] = SPI_RELATION_EMBEDS;
1025   relation_type_table [Accessibility_RELATION_EMBEDDED_BY] = SPI_RELATION_EMBEDDED_BY;
1026   relation_type_table [Accessibility_RELATION_POPUP_FOR] = SPI_RELATION_POPUP_FOR;
1027   relation_type_table [Accessibility_RELATION_PARENT_WINDOW_OF] = SPI_RELATION_PARENT_WINDOW_OF;
1028   relation_type_table [Accessibility_RELATION_DESCRIBED_BY] = SPI_RELATION_DESCRIBED_BY;
1029   relation_type_table [Accessibility_RELATION_DESCRIPTION_FOR] = SPI_RELATION_DESCRIPTION_FOR;
1030   return TRUE;
1031 }
1032
1033 static AccessibleRelationType
1034 cspi_relation_type_from_spi_relation_type (Accessibility_RelationType type)
1035 {
1036   /* array is sized according to IDL RelationType because IDL RelationTypes are the index */    
1037   static AccessibleRelationType cspi_relation_type_table [Accessibility_RELATION_LAST_DEFINED];
1038   static gboolean is_initialized = FALSE;
1039   AccessibleRelationType cspi_type;
1040   if (!is_initialized)
1041     {
1042       is_initialized = cspi_init_relation_type_table (cspi_relation_type_table);            
1043     }
1044   if (type >= 0 && type < Accessibility_RELATION_LAST_DEFINED)
1045     {
1046       cspi_type = cspi_relation_type_table [type];          
1047     }
1048   else
1049     {
1050       cspi_type = SPI_RELATION_NULL;
1051     }
1052   return cspi_type; 
1053 }
1054 /**
1055  * AccessibleRelation_getRelationType:
1056  * @obj: a pointer to the #AtspiAccessibleRelation object to query.
1057  *
1058  * Get the type of relationship represented by an #AtspiAccessibleRelation.
1059  *
1060  * Returns: an #AtspiAccessibleRelationType indicating the type of relation
1061  *         encapsulated in this #AtspiAccessibleRelation object.
1062  *
1063  **/
1064 AccessibleRelationType
1065 AccessibleRelation_getRelationType (AccessibleRelation *obj)
1066 {
1067   cspi_return_val_if_fail (obj, SPI_RELATION_NULL);
1068   return cspi_relation_type_from_spi_relation_type (obj->type);
1069 }
1070
1071 /**
1072  * AccessibleRelation_getNTargets:
1073  * @obj: a pointer to the #AtspiAccessibleRelation object to query.
1074  *
1075  * Get the number of objects which this relationship has as its
1076  *       target objects (the subject is the #AtspiAccessible from which this
1077  *       #AtspiAccessibleRelation originated).
1078  *
1079  * Returns: a short integer indicating how many target objects which the
1080  *       originating #AtspiAccessible object has the #AtspiAccessibleRelation
1081  *       relationship with.
1082  **/
1083 int
1084 AccessibleRelation_getNTargets (AccessibleRelation *obj)
1085 {
1086   cspi_return_val_if_fail (obj, -1);
1087   return obj->targets->len;
1088 }
1089
1090 /**
1091  * AccessibleRelation_getTarget:
1092  * @obj: a pointer to the #AtspiAccessibleRelation object to query.
1093  * @i: a (zero-index) integer indicating which (of possibly several) target is requested.
1094  *
1095  * Get the @i-th target of a specified #AtspiAccessibleRelation relationship.
1096  *
1097  * Returns: an #AtspiAccessible which is the @i-th object with which the
1098  *      originating #AtspiAccessible has relationship specified in the
1099  *      #AtspiAccessibleRelation object.
1100  *
1101  **/
1102 Accessible *
1103 AccessibleRelation_getTarget (AccessibleRelation *obj, int i)
1104 {
1105   cspi_return_val_if_fail (obj, NULL);
1106
1107   if (i < 0 || i >= obj->targets->len) return NULL;
1108   return cspi_object_add (
1109                          g_array_index (obj->targets, Accessible *, i));
1110 }
1111
1112 /**
1113  * AccessibleStateSet_ref:
1114  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1115  *
1116  * Increment the reference count for an #AtspiAccessibleStateSet object.
1117  *
1118  **/
1119 void
1120 AccessibleStateSet_ref (AccessibleStateSet *obj)
1121 {
1122   spi_state_set_cache_ref (obj);
1123 }
1124
1125 /**
1126  * AccessibleStateSet_unref:
1127  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1128  *
1129  * Decrement the reference count for an #AtspiAccessibleStateSet object.
1130  *
1131  **/
1132 void
1133 AccessibleStateSet_unref (AccessibleStateSet *obj)
1134 {
1135   spi_state_set_cache_unref (obj);
1136 }
1137
1138 static Accessibility_StateType
1139 spi_state_to_dbus (AccessibleState state)
1140 {
1141 #define MAP_STATE(a) \
1142   case SPI_STATE_##a: \
1143     return Accessibility_STATE_##a
1144
1145   switch (state)
1146     {
1147       MAP_STATE (INVALID);
1148       MAP_STATE (ACTIVE);
1149       MAP_STATE (ARMED);
1150       MAP_STATE (BUSY);
1151       MAP_STATE (CHECKED);
1152       MAP_STATE (DEFUNCT);
1153       MAP_STATE (EDITABLE);
1154       MAP_STATE (ENABLED);
1155       MAP_STATE (EXPANDABLE);
1156       MAP_STATE (EXPANDED);
1157       MAP_STATE (FOCUSABLE);
1158       MAP_STATE (FOCUSED);
1159       MAP_STATE (HORIZONTAL);
1160       MAP_STATE (ICONIFIED);
1161       MAP_STATE (MODAL);
1162       MAP_STATE (MULTI_LINE);
1163       MAP_STATE (MULTISELECTABLE);
1164       MAP_STATE (OPAQUE);
1165       MAP_STATE (PRESSED);
1166       MAP_STATE (RESIZABLE);
1167       MAP_STATE (SELECTABLE);
1168       MAP_STATE (SELECTED);
1169       MAP_STATE (SENSITIVE);
1170       MAP_STATE (SHOWING);
1171       MAP_STATE (SINGLE_LINE);
1172       MAP_STATE (STALE);
1173       MAP_STATE (TRANSIENT);
1174       MAP_STATE (VERTICAL);
1175       MAP_STATE (VISIBLE);
1176       MAP_STATE (MANAGES_DESCENDANTS);
1177       MAP_STATE (INDETERMINATE);
1178       MAP_STATE (TRUNCATED);
1179       MAP_STATE (REQUIRED);
1180       MAP_STATE (INVALID_ENTRY);
1181       MAP_STATE (SUPPORTS_AUTOCOMPLETION);
1182       MAP_STATE (SELECTABLE_TEXT);
1183       MAP_STATE (IS_DEFAULT);
1184       MAP_STATE (VISITED);
1185     default:
1186       return Accessibility_STATE_INVALID;
1187   }
1188 #undef MAP_STATE
1189 }             
1190
1191 /**
1192  * AccessibleStateSet_contains:
1193  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1194  * @state: an #AtspiAccessibleState for which the specified #AtspiAccessibleStateSet
1195  *       will be queried.
1196  *
1197  * Determine whether a given #AtspiAccessibleStateSet includes a given state; that is,
1198  *       whether @state is true for the stateset in question.
1199  *
1200  * Returns: #TRUE if @state is true/included in the given #AtspiAccessibleStateSet,
1201  *          otherwise #FALSE.
1202  *
1203  **/
1204 gboolean
1205 AccessibleStateSet_contains (AccessibleStateSet *obj,
1206                              AccessibleState state)
1207 {
1208   return spi_state_set_cache_contains (obj, spi_state_to_dbus (state));
1209 }
1210
1211 /**
1212  * AccessibleStateSet_add:
1213  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1214  * @state: an #AtspiAccessibleState to be added to the specified #AtspiAccessibleStateSet
1215  *
1216  * Add a particular #AtspiAccessibleState to an #AtspiAccessibleStateSet (i.e. set the
1217  *       given state to #TRUE in the stateset.
1218  *
1219  **/
1220 void
1221 AccessibleStateSet_add (AccessibleStateSet *obj,
1222                         AccessibleState state)
1223 {
1224   spi_state_set_cache_add (obj, spi_state_to_dbus (state));
1225 }
1226
1227 /**
1228  * AccessibleStateSet_remove:
1229  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1230  * @state: an #AtspiAccessibleState to be removed from the specified #AtspiAccessibleStateSet
1231  *
1232  * Remove a particular #AtspiAccessibleState to an #AtspiAccessibleStateSet (i.e. set the
1233  *       given state to #FALSE in the stateset.)
1234  *
1235  **/
1236 void
1237 AccessibleStateSet_remove (AccessibleStateSet *obj,
1238                            AccessibleState state)
1239 {
1240   spi_state_set_cache_remove (obj, spi_state_to_dbus (state));
1241 }
1242
1243 /**
1244  * AccessibleStateSet_equals:
1245  * @obj: a pointer to the first #AtspiAccessibleStateSet object on which to operate.
1246  * @obj2: a pointer to the second #AtspiAccessibleStateSet object on which to operate.
1247  *
1248  * Determine whether two instances of #AtspiAccessibleStateSet are equivalent (i.e.
1249  *         consist of the same #AtspiAccessibleStates).  Useful for checking multiple
1250  *         state variables at once; construct the target state then compare against it.
1251  *
1252  * @see AccessibleStateSet_compare().
1253  *
1254  * Returns: #TRUE if the two #AtspiAccessibleStateSets are equivalent,
1255  *          otherwise #FALSE.
1256  *
1257  **/
1258 gboolean
1259 AccessibleStateSet_equals (AccessibleStateSet *obj,
1260                            AccessibleStateSet *obj2)
1261 {
1262   gboolean   eq;
1263   AtkStateSet *cmp;
1264
1265   if (obj == obj2)
1266     {
1267       return TRUE;
1268     }
1269
1270   cmp = spi_state_set_cache_xor (obj, obj2);
1271   eq = spi_state_set_cache_is_empty (cmp);
1272   spi_state_set_cache_unref (cmp);
1273
1274   return eq;
1275 }
1276
1277 /**
1278  * AccessibleStateSet_compare:
1279  * @obj: a pointer to the first #AtspiAccessibleStateSet object on which to operate.
1280  * @obj2: a pointer to the second #AtspiAccessibleStateSet object on which to operate.
1281  *
1282  * Determine the differences between two instances of #AtspiAccessibleStateSet.
1283  * Not Yet Implemented.
1284  *.
1285  * @see AccessibleStateSet_equals().
1286  *
1287  * Returns: an #AtspiAccessibleStateSet object containing all states contained on one of
1288  *          the two sets but not the other.
1289  *
1290  **/
1291 AccessibleStateSet *
1292 AccessibleStateSet_compare (AccessibleStateSet *obj,
1293                             AccessibleStateSet *obj2)
1294 {
1295   return spi_state_set_cache_xor (obj, obj2);
1296 }
1297
1298 /**
1299  * AccessibleStateSet_isEmpty:
1300  * @obj: a pointer to the #AtspiAccessibleStateSet object on which to operate.
1301  *
1302  * Determine whether a given #AtspiAccessibleStateSet is the empty set.
1303  *
1304  * Returns: #TRUE if the given #AtspiAccessibleStateSet contains no (true) states,
1305  *          otherwise #FALSE.
1306  *
1307  **/
1308 gboolean
1309 AccessibleStateSet_isEmpty (AccessibleStateSet *obj)
1310 {
1311   return spi_state_set_cache_is_empty (obj);
1312 }
1313 #endif
1314
1315 gboolean
1316 _atspi_accessible_is_a (AtspiAccessible *accessible,
1317                       const char *interface_name)
1318 {
1319   int n;
1320
1321   if (accessible == NULL)
1322     {
1323       return FALSE;
1324     }
1325
1326   n = _atspi_get_iface_num (interface_name);
1327   if (n == -1) return FALSE;
1328   return (gboolean) ((accessible->interfaces & (1 << n))? TRUE: FALSE);
1329 }
1330
1331 /* TODO: Move to a finalizer */
1332 static void
1333 cspi_object_destroyed (AtspiAccessible *accessible)
1334 {
1335   gboolean cached;
1336   AtspiEvent e;
1337
1338   /* TODO: Only fire if object not already marked defunct */
1339   memset (&e, 0, sizeof (e));
1340   e.type = "object:state-change:defunct";
1341   e.source = accessible;
1342   e.detail1 = 1;
1343   e.detail2 = 0;
1344   _atspi_send_event (&e);
1345
1346     g_free (accessible->parent.path);
1347
1348     if (accessible->states)
1349       g_object_unref (accessible->states);
1350     g_free (accessible->description);
1351     g_free (accessible->name);
1352 }
1353
1354 AtspiAccessible *
1355 atspi_accessible_new (AtspiApplication *app, const gchar *path)
1356 {
1357   AtspiAccessible *accessible;
1358   
1359   accessible = g_object_new (ATSPI_TYPE_ACCESSIBLE, NULL);
1360   g_return_val_if_fail (accessible != NULL, NULL);
1361
1362   accessible->parent.app = g_object_ref (app);
1363   accessible->parent.path = g_strdup (path);
1364
1365   return accessible;
1366 }