2009-08-28 Mike Gorse <mgorse@novell.com>
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / accessible-adaptor.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2008 Novell, Inc.
6  * Copyright 2001, 2002 Sun Microsystems Inc.,
7  * Copyright 2001, 2002 Ximian, Inc.
8  *
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.
13  *
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.
18  *
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.
23  */
24
25 #include <atk/atk.h>
26 #include <droute/droute.h>
27
28 #include "common/spi-dbus.h"
29 #include "common/spi-stateset.h"
30 #include "accessible-marshaller.h"
31 #include "accessible-register.h"
32
33 static dbus_bool_t
34 impl_get_name (DBusMessageIter *iter, void *user_data)
35 {
36   AtkObject *object = (AtkObject *) user_data;
37
38   g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
39
40   return droute_return_v_string (iter, atk_object_get_name (object));
41 }
42
43 static dbus_bool_t
44 impl_set_name (DBusMessageIter *iter, void *user_data)
45 {
46   AtkObject *object = (AtkObject *) user_data;
47   const char *name = droute_get_v_string (iter);
48
49   g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
50
51   atk_object_set_name (object, name);
52   return TRUE;
53 }
54
55 static dbus_bool_t
56 impl_get_description (DBusMessageIter *iter, void *user_data)
57 {
58   AtkObject *object = (AtkObject *) user_data;
59
60   g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
61
62   return droute_return_v_string (iter, atk_object_get_description (object));
63 }
64
65 static dbus_bool_t
66 impl_set_description (DBusMessageIter *iter, void *user_data)
67 {
68   AtkObject *object = (AtkObject *) user_data;
69   const char *description = droute_get_v_string (iter);
70
71   g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
72
73   atk_object_set_description (object, description);
74   return TRUE;
75 }
76
77 static dbus_bool_t
78 impl_get_parent (DBusMessageIter *iter, void *user_data)
79 {
80   AtkObject *object = (AtkObject *) user_data;
81
82   g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
83
84   return spi_dbus_return_v_object (iter,
85                                    atk_object_get_parent (object),
86                                    FALSE);
87 }
88
89 static dbus_bool_t
90 impl_get_childCount (DBusMessageIter *iter, void *user_data)
91 {
92   AtkObject *object = (AtkObject *) user_data;
93
94   g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
95
96   return droute_return_v_int32 (iter,
97                                 atk_object_get_n_accessible_children
98                                 (object));
99 }
100
101 static DBusMessage *
102 impl_getChildAtIndex (DBusConnection *bus,
103                       DBusMessage *message,
104                       void *user_data)
105 {
106   AtkObject *object = (AtkObject *) user_data;
107   DBusError error;
108   dbus_int32_t i;
109   AtkObject *child;
110
111   dbus_error_init (&error);
112   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
113                         droute_not_yet_handled_error (message));
114   if (!dbus_message_get_args (message, &error, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID))
115       return spi_dbus_general_error (message);
116   child = atk_object_ref_accessible_child (object, i);
117   return spi_dbus_return_object (message, child, FALSE, FALSE);
118 }
119
120 static DBusMessage *
121 impl_getChildren (DBusConnection *bus,
122                   DBusMessage *message,
123                   void *user_data)
124 {
125   AtkObject *object = (AtkObject *) user_data;
126   gint i;
127   gint count;
128   DBusMessage *reply;
129   DBusMessageIter iter, iter_array;
130
131   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
132                         droute_not_yet_handled_error (message));
133   count = atk_object_get_n_accessible_children (object);
134   reply = dbus_message_new_method_return (message);
135   if (!reply) goto oom;
136   dbus_message_iter_init_append (reply, &iter);
137   if (!dbus_message_iter_open_container
138       (&iter, DBUS_TYPE_ARRAY, "o", &iter_array))
139     goto oom;
140   for (i = 0; i < count; i++)
141     {
142       AtkObject *child = atk_object_ref_accessible_child (object, i);
143       char *path = atk_dbus_object_to_path (child, FALSE);
144       if (path)
145         {
146           dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_OBJECT_PATH,
147                                           &path);
148           g_free (path);
149         }
150       if (child)
151         g_object_unref (child);
152     }
153   if (!dbus_message_iter_close_container (&iter, &iter_array))
154     goto oom;
155   return reply;
156 oom:
157   // TODO: handle out-of-memory
158   return reply;
159 }
160
161 static DBusMessage *
162 impl_getIndexInParent (DBusConnection *bus,
163                        DBusMessage *message,
164                        void *user_data)
165 {
166   AtkObject *object = (AtkObject *) user_data;
167   dbus_uint32_t rv;
168   DBusMessage *reply;
169
170   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
171                         droute_not_yet_handled_error (message));
172   rv = atk_object_get_index_in_parent (object);
173   reply = dbus_message_new_method_return (message);
174   if (reply)
175     {
176       dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
177                                 DBUS_TYPE_INVALID);
178     }
179   return reply;
180 }
181
182 static gboolean
183 spi_init_relation_type_table (Accessibility_RelationType *types)
184 {
185   gint i;
186
187   for (i = 0; i < ATK_RELATION_LAST_DEFINED; i++)
188     types[i] = Accessibility_RELATION_NULL;
189
190   types[ATK_RELATION_CONTROLLED_BY] = Accessibility_RELATION_CONTROLLED_BY;
191   types[ATK_RELATION_CONTROLLER_FOR] = Accessibility_RELATION_CONTROLLER_FOR;
192   types[ATK_RELATION_LABEL_FOR] = Accessibility_RELATION_LABEL_FOR;
193   types[ATK_RELATION_LABELLED_BY] = Accessibility_RELATION_LABELLED_BY;
194   types[ATK_RELATION_MEMBER_OF] = Accessibility_RELATION_MEMBER_OF;
195   types[ATK_RELATION_NODE_CHILD_OF] = Accessibility_RELATION_NODE_CHILD_OF;
196   types[ATK_RELATION_FLOWS_TO] = Accessibility_RELATION_FLOWS_TO;
197   types[ATK_RELATION_FLOWS_FROM] = Accessibility_RELATION_FLOWS_FROM;
198   types[ATK_RELATION_SUBWINDOW_OF] = Accessibility_RELATION_SUBWINDOW_OF;
199   types[ATK_RELATION_EMBEDS] = Accessibility_RELATION_EMBEDS;
200   types[ATK_RELATION_EMBEDDED_BY] = Accessibility_RELATION_EMBEDDED_BY;
201   types[ATK_RELATION_POPUP_FOR] = Accessibility_RELATION_POPUP_FOR;
202   types[ATK_RELATION_PARENT_WINDOW_OF] = Accessibility_RELATION_PARENT_WINDOW_OF;
203   types[ATK_RELATION_DESCRIPTION_FOR] = Accessibility_RELATION_DESCRIPTION_FOR;
204   types[ATK_RELATION_DESCRIBED_BY] = Accessibility_RELATION_DESCRIBED_BY;
205
206   return TRUE;
207 }
208
209 static Accessibility_RelationType
210 spi_relation_type_from_atk_relation_type (AtkRelationType type)
211 {
212   static gboolean is_initialized = FALSE;
213   static Accessibility_RelationType spi_relation_type_table [ATK_RELATION_LAST_DEFINED];
214   Accessibility_RelationType spi_type;
215
216   if (!is_initialized)
217     is_initialized = spi_init_relation_type_table (spi_relation_type_table);       
218
219   if (type > ATK_RELATION_NULL && type < ATK_RELATION_LAST_DEFINED)
220     spi_type = spi_relation_type_table[type];
221   else
222     spi_type = Accessibility_RELATION_EXTENDED;
223   return spi_type;
224 }
225
226 static DBusMessage *
227 impl_getRelationSet (DBusConnection *bus,
228                      DBusMessage *message,
229                      void *user_data)
230 {
231   AtkObject *object = (AtkObject *) user_data;
232   DBusMessage *reply;
233   AtkRelationSet *set;
234   DBusMessageIter iter, iter_array, iter_struct, iter_targets;
235   gint count;
236   gint i, j;
237
238   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
239                         droute_not_yet_handled_error (message));
240   reply = dbus_message_new_method_return (message);
241   if (!reply) return NULL;
242   set = atk_object_ref_relation_set (object);
243   dbus_message_iter_init_append (reply, &iter);
244   if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(uao)", &iter_array))
245   {
246     goto oom;
247   }
248   count = atk_relation_set_get_n_relations (set);
249   for (i = 0; i < count; i++)
250   {
251     AtkRelation *r = atk_relation_set_get_relation (set, i);
252     AtkRelationType rt;
253     GPtrArray *target;
254     dbus_uint32_t type;
255     if (!r) continue;
256     rt= atk_relation_get_relation_type (r);
257     type = spi_relation_type_from_atk_relation_type (rt);
258     target = atk_relation_get_target (r);
259     if (!dbus_message_iter_open_container (&iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct))
260     {
261       goto oom;
262     }
263     dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &type);
264     if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "o", &iter_targets))
265     {
266       goto oom;
267     }
268     for (j = 0; j < target->len; j++)
269     {
270       AtkObject *obj = target->pdata[j];
271       char *path;
272       if (!obj) continue;
273       path = atk_dbus_object_to_path (obj, FALSE);
274       if (!path)
275       {
276         g_warning ("Unknown object in relation type %d\n", type);
277         continue;
278       }
279       dbus_message_iter_append_basic (&iter_targets, DBUS_TYPE_OBJECT_PATH, &path);
280     }
281     dbus_message_iter_close_container (&iter_struct, &iter_targets);
282     dbus_message_iter_close_container (&iter_array, &iter_struct);
283   }
284   dbus_message_iter_close_container (&iter, &iter_array);
285 oom:
286   // TODO: handle out of memory */
287   return reply;
288 }
289
290 static gboolean
291 spi_init_role_lookup_table (Accessibility_Role * role_table)
292 {
293   int i;
294   /* if it's not in the list below, dunno what it is */
295   for (i = 0; i < ATK_ROLE_LAST_DEFINED; ++i)
296     {
297       role_table[i] = Accessibility_ROLE_UNKNOWN;
298     }
299
300   role_table[ATK_ROLE_INVALID] = Accessibility_ROLE_INVALID;
301   role_table[ATK_ROLE_ACCEL_LABEL] = Accessibility_ROLE_ACCELERATOR_LABEL;
302   role_table[ATK_ROLE_ALERT] = Accessibility_ROLE_ALERT;
303   role_table[ATK_ROLE_ANIMATION] = Accessibility_ROLE_ANIMATION;
304   role_table[ATK_ROLE_ARROW] = Accessibility_ROLE_ARROW;
305   role_table[ATK_ROLE_CALENDAR] = Accessibility_ROLE_CALENDAR;
306   role_table[ATK_ROLE_CANVAS] = Accessibility_ROLE_CANVAS;
307   role_table[ATK_ROLE_CHECK_BOX] = Accessibility_ROLE_CHECK_BOX;
308   role_table[ATK_ROLE_CHECK_MENU_ITEM] = Accessibility_ROLE_CHECK_MENU_ITEM;
309   role_table[ATK_ROLE_COLOR_CHOOSER] = Accessibility_ROLE_COLOR_CHOOSER;
310   role_table[ATK_ROLE_COLUMN_HEADER] = Accessibility_ROLE_COLUMN_HEADER;
311   role_table[ATK_ROLE_COMBO_BOX] = Accessibility_ROLE_COMBO_BOX;
312   role_table[ATK_ROLE_DATE_EDITOR] = Accessibility_ROLE_DATE_EDITOR;
313   role_table[ATK_ROLE_DESKTOP_ICON] = Accessibility_ROLE_DESKTOP_ICON;
314   role_table[ATK_ROLE_DESKTOP_FRAME] = Accessibility_ROLE_DESKTOP_FRAME;
315   role_table[ATK_ROLE_DIAL] = Accessibility_ROLE_DIAL;
316   role_table[ATK_ROLE_DIALOG] = Accessibility_ROLE_DIALOG;
317   role_table[ATK_ROLE_DIRECTORY_PANE] = Accessibility_ROLE_DIRECTORY_PANE;
318   role_table[ATK_ROLE_DRAWING_AREA] = Accessibility_ROLE_DRAWING_AREA;
319   role_table[ATK_ROLE_FILE_CHOOSER] = Accessibility_ROLE_FILE_CHOOSER;
320   role_table[ATK_ROLE_FILLER] = Accessibility_ROLE_FILLER;
321   role_table[ATK_ROLE_FONT_CHOOSER] = Accessibility_ROLE_FONT_CHOOSER;
322   role_table[ATK_ROLE_FRAME] = Accessibility_ROLE_FRAME;
323   role_table[ATK_ROLE_GLASS_PANE] = Accessibility_ROLE_GLASS_PANE;
324   role_table[ATK_ROLE_HTML_CONTAINER] = Accessibility_ROLE_HTML_CONTAINER;
325   role_table[ATK_ROLE_ICON] = Accessibility_ROLE_ICON;
326   role_table[ATK_ROLE_IMAGE] = Accessibility_ROLE_IMAGE;
327   role_table[ATK_ROLE_INTERNAL_FRAME] = Accessibility_ROLE_INTERNAL_FRAME;
328   role_table[ATK_ROLE_LABEL] = Accessibility_ROLE_LABEL;
329   role_table[ATK_ROLE_LAYERED_PANE] = Accessibility_ROLE_LAYERED_PANE;
330   role_table[ATK_ROLE_LIST] = Accessibility_ROLE_LIST;
331   role_table[ATK_ROLE_LIST_ITEM] = Accessibility_ROLE_LIST_ITEM;
332   role_table[ATK_ROLE_MENU] = Accessibility_ROLE_MENU;
333   role_table[ATK_ROLE_MENU_BAR] = Accessibility_ROLE_MENU_BAR;
334   role_table[ATK_ROLE_MENU_ITEM] = Accessibility_ROLE_MENU_ITEM;
335   role_table[ATK_ROLE_OPTION_PANE] = Accessibility_ROLE_OPTION_PANE;
336   role_table[ATK_ROLE_PAGE_TAB] = Accessibility_ROLE_PAGE_TAB;
337   role_table[ATK_ROLE_PAGE_TAB_LIST] = Accessibility_ROLE_PAGE_TAB_LIST;
338   role_table[ATK_ROLE_PANEL] = Accessibility_ROLE_PANEL;
339   role_table[ATK_ROLE_PASSWORD_TEXT] = Accessibility_ROLE_PASSWORD_TEXT;
340   role_table[ATK_ROLE_POPUP_MENU] = Accessibility_ROLE_POPUP_MENU;
341   role_table[ATK_ROLE_PROGRESS_BAR] = Accessibility_ROLE_PROGRESS_BAR;
342   role_table[ATK_ROLE_PUSH_BUTTON] = Accessibility_ROLE_PUSH_BUTTON;
343   role_table[ATK_ROLE_RADIO_BUTTON] = Accessibility_ROLE_RADIO_BUTTON;
344   role_table[ATK_ROLE_RADIO_MENU_ITEM] = Accessibility_ROLE_RADIO_MENU_ITEM;
345   role_table[ATK_ROLE_ROOT_PANE] = Accessibility_ROLE_ROOT_PANE;
346   role_table[ATK_ROLE_ROW_HEADER] = Accessibility_ROLE_ROW_HEADER;
347   role_table[ATK_ROLE_SCROLL_BAR] = Accessibility_ROLE_SCROLL_BAR;
348   role_table[ATK_ROLE_SCROLL_PANE] = Accessibility_ROLE_SCROLL_PANE;
349   role_table[ATK_ROLE_SEPARATOR] = Accessibility_ROLE_SEPARATOR;
350   role_table[ATK_ROLE_SLIDER] = Accessibility_ROLE_SLIDER;
351   role_table[ATK_ROLE_SPIN_BUTTON] = Accessibility_ROLE_SPIN_BUTTON;
352   role_table[ATK_ROLE_SPLIT_PANE] = Accessibility_ROLE_SPLIT_PANE;
353   role_table[ATK_ROLE_STATUSBAR] = Accessibility_ROLE_STATUS_BAR;
354   role_table[ATK_ROLE_TABLE] = Accessibility_ROLE_TABLE;
355   role_table[ATK_ROLE_TABLE_CELL] = Accessibility_ROLE_TABLE_CELL;
356   role_table[ATK_ROLE_TABLE_COLUMN_HEADER] =
357     Accessibility_ROLE_TABLE_COLUMN_HEADER;
358   role_table[ATK_ROLE_TABLE_ROW_HEADER] = Accessibility_ROLE_TABLE_ROW_HEADER;
359   role_table[ATK_ROLE_TEAR_OFF_MENU_ITEM] =
360     Accessibility_ROLE_TEAROFF_MENU_ITEM;
361   role_table[ATK_ROLE_TERMINAL] = Accessibility_ROLE_TERMINAL;
362   role_table[ATK_ROLE_TEXT] = Accessibility_ROLE_TEXT;
363   role_table[ATK_ROLE_TOGGLE_BUTTON] = Accessibility_ROLE_TOGGLE_BUTTON;
364   role_table[ATK_ROLE_TOOL_BAR] = Accessibility_ROLE_TOOL_BAR;
365   role_table[ATK_ROLE_TOOL_TIP] = Accessibility_ROLE_TOOL_TIP;
366   role_table[ATK_ROLE_TREE] = Accessibility_ROLE_TREE;
367   role_table[ATK_ROLE_TREE_TABLE] = Accessibility_ROLE_TREE_TABLE;
368   role_table[ATK_ROLE_UNKNOWN] = Accessibility_ROLE_UNKNOWN;
369   role_table[ATK_ROLE_VIEWPORT] = Accessibility_ROLE_VIEWPORT;
370   role_table[ATK_ROLE_WINDOW] = Accessibility_ROLE_WINDOW;
371   role_table[ATK_ROLE_HEADER] = Accessibility_ROLE_HEADER;
372   role_table[ATK_ROLE_FOOTER] = Accessibility_ROLE_FOOTER;
373   role_table[ATK_ROLE_PARAGRAPH] = Accessibility_ROLE_PARAGRAPH;
374   role_table[ATK_ROLE_RULER] = Accessibility_ROLE_RULER;
375   role_table[ATK_ROLE_APPLICATION] = Accessibility_ROLE_APPLICATION;
376   role_table[ATK_ROLE_AUTOCOMPLETE] = Accessibility_ROLE_AUTOCOMPLETE;
377   role_table[ATK_ROLE_EDITBAR] = Accessibility_ROLE_EDITBAR;
378   role_table[ATK_ROLE_EMBEDDED] = Accessibility_ROLE_EMBEDDED;
379   role_table[ATK_ROLE_ENTRY] = Accessibility_ROLE_ENTRY;
380   role_table[ATK_ROLE_CHART] = Accessibility_ROLE_CHART;
381   role_table[ATK_ROLE_CAPTION] = Accessibility_ROLE_CAPTION;
382   role_table[ATK_ROLE_DOCUMENT_FRAME] = Accessibility_ROLE_DOCUMENT_FRAME;
383   role_table[ATK_ROLE_HEADING] = Accessibility_ROLE_HEADING;
384   role_table[ATK_ROLE_PAGE] = Accessibility_ROLE_PAGE;
385   role_table[ATK_ROLE_SECTION] = Accessibility_ROLE_SECTION;
386   role_table[ATK_ROLE_FORM] = Accessibility_ROLE_FORM;
387   role_table[ATK_ROLE_REDUNDANT_OBJECT] = Accessibility_ROLE_REDUNDANT_OBJECT;
388   role_table[ATK_ROLE_LINK] = Accessibility_ROLE_LINK;
389   role_table[ATK_ROLE_INPUT_METHOD_WINDOW] =
390     Accessibility_ROLE_INPUT_METHOD_WINDOW;
391   return TRUE;
392 }
393
394 Accessibility_Role
395 spi_accessible_role_from_atk_role (AtkRole role)
396 {
397   static gboolean is_initialized = FALSE;
398   static Accessibility_Role spi_role_table[ATK_ROLE_LAST_DEFINED];
399   Accessibility_Role spi_role;
400
401   if (!is_initialized)
402     {
403       is_initialized = spi_init_role_lookup_table (spi_role_table);
404     }
405
406   if (role >= 0 && role < ATK_ROLE_LAST_DEFINED)
407     {
408       spi_role = spi_role_table[role];
409     }
410   else
411     {
412       spi_role = Accessibility_ROLE_EXTENDED;
413     }
414   return spi_role;
415 }
416
417 static DBusMessage *
418 impl_getRole (DBusConnection *bus, DBusMessage *message, void *user_data)
419 {
420   AtkObject *object = (AtkObject *) user_data;
421   gint role;
422   dbus_uint32_t rv;
423   DBusMessage *reply;
424
425   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
426                         droute_not_yet_handled_error (message));
427   role = atk_object_get_role (object);
428   rv = spi_accessible_role_from_atk_role (role);
429   reply = dbus_message_new_method_return (message);
430   if (reply)
431     {
432       dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
433                                 DBUS_TYPE_INVALID);
434     }
435   return reply;
436 }
437
438 static char *
439 impl_get_role_str (void *datum)
440 {
441   g_return_val_if_fail (ATK_IS_OBJECT (datum), g_strdup (""));
442   return g_strdup_printf ("%d",
443                           spi_accessible_role_from_atk_role
444                           (atk_object_get_role ((AtkObject *) datum)));
445 }
446
447 static DBusMessage *
448 impl_getRoleName (DBusConnection *bus,
449                   DBusMessage *message,
450                   void *user_data)
451 {
452   AtkObject *object = (AtkObject *) user_data;
453   gint role;
454   const char *role_name;
455   DBusMessage *reply;
456
457   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
458                         droute_not_yet_handled_error (message));
459   role = atk_object_get_role (object);
460   role_name = atk_role_get_name (role);
461   if (!role_name)
462     role_name = "";
463   reply = dbus_message_new_method_return (message);
464   if (reply)
465     {
466       dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
467                                 DBUS_TYPE_INVALID);
468     }
469   return reply;
470 }
471
472 static DBusMessage *
473 impl_getLocalizedRoleName (DBusConnection *bus,
474                            DBusMessage *message,
475                            void *user_data)
476 {
477   AtkObject *object = (AtkObject *) user_data;
478   gint role;
479   const char *role_name;
480   DBusMessage *reply;
481
482   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
483                         droute_not_yet_handled_error (message));
484   role = atk_object_get_role (object);
485   role_name = atk_role_get_localized_name (role);
486   if (!role_name)
487     role_name = "";
488   reply = dbus_message_new_method_return (message);
489   if (reply)
490     {
491       dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
492                                 DBUS_TYPE_INVALID);
493     }
494   return reply;
495 }
496
497 static DBusMessage *
498 impl_getState (DBusConnection *bus,
499                DBusMessage *message,
500                void *user_data)
501 {
502   AtkObject *object = (AtkObject *) user_data;
503   dbus_uint32_t rv[2];
504   dbus_uint32_t *array = rv;
505   DBusMessage *reply;
506
507   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
508                         droute_not_yet_handled_error (message));
509   spi_atk_state_to_dbus_array (object, rv);
510   reply = dbus_message_new_method_return (message);
511   if (reply)
512     {
513       dbus_message_append_args (reply, DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &array,
514                                 2, DBUS_TYPE_INVALID);
515     }
516   return reply;
517 }
518
519 static DBusMessage *
520 impl_getAttributes (DBusConnection *bus,
521                     DBusMessage *message,
522                     void *user_data)
523 {
524   AtkObject *object = (AtkObject *) user_data;
525   DBusMessage *reply;
526
527   AtkAttributeSet *attributes;
528   DBusMessageIter iter;
529
530   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
531                         droute_not_yet_handled_error (message));
532
533   attributes = atk_object_get_attributes (object);
534
535   reply = dbus_message_new_method_return (message);
536   dbus_message_iter_init_append (reply, &iter);
537   spi_atk_append_attribute_set (&iter, attributes);
538
539   if (attributes)
540     atk_attribute_set_free (attributes);
541
542   return reply;
543 }
544
545 static DBusMessage *
546 impl_getApplication (DBusConnection *bus,
547                      DBusMessage *message,
548                      void *user_data)
549 {
550   AtkObject *root = atk_get_root ();
551   return spi_dbus_return_object (message, root, FALSE, FALSE);
552 }
553
554 static DBusMessage *
555 impl_getInterfaces (DBusConnection *bus,
556                     DBusMessage *message,
557                     void *user_data)
558 {
559   AtkObject *object = (AtkObject *) user_data;
560   gint role;
561   const char *role_name;
562   DBusMessage *reply;
563   DBusMessageIter iter, iter_array;
564
565   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
566                         droute_not_yet_handled_error (message));
567   reply = dbus_message_new_method_return (message);
568   if (reply)
569     {
570       dbus_message_iter_init_append (reply, &iter);
571       dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &iter_array);
572       append_atk_object_interfaces (object, &iter_array);
573       dbus_message_iter_close_container (&iter, &iter_array);
574     }
575   return reply;
576 }
577
578 static DRouteMethod methods[] = {
579   {impl_getChildAtIndex, "getChildAtIndex"},
580   {impl_getChildren, "getChildren"},
581   {impl_getIndexInParent, "getIndexInParent"},
582   {impl_getRelationSet, "getRelationSet"},
583   {impl_getRole, "getRole"},
584   {impl_getRoleName, "getRoleName"},
585   {impl_getLocalizedRoleName, "getLocalizedRoleName"},
586   {impl_getState, "getState"},
587   {impl_getAttributes, "getAttributes"},
588   {impl_getApplication, "getApplication"},
589   {impl_getInterfaces, "getInterfaces"},
590   {NULL, NULL}
591 };
592
593 static DRouteProperty properties[] = {
594   {impl_get_name, impl_set_name, "name"},
595   {impl_get_description, impl_set_description, "description"},
596   {impl_get_parent, NULL, "parent"},
597   {impl_get_childCount, NULL, "childCount"},
598   {NULL, NULL, NULL}
599 };
600
601 void
602 spi_initialize_accessible (DRoutePath *path)
603 {
604   droute_path_add_interface (path,
605                              SPI_DBUS_INTERFACE_ACCESSIBLE,
606                              methods,
607                              properties);
608 };