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