74a15fe72d7cc03a44f5051338549e5efd65574c
[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     {
116       return droute_invalid_arguments_error (message);
117     }
118   child = atk_object_ref_accessible_child (object, i);
119   return spi_dbus_return_object (message, child, TRUE, TRUE);
120 }
121
122 static DBusMessage *
123 impl_GetChildren (DBusConnection *bus,
124                   DBusMessage *message,
125                   void *user_data)
126 {
127   AtkObject *object = (AtkObject *) user_data;
128   gint i;
129   gint count;
130   DBusMessage *reply;
131   DBusMessageIter iter, iter_array;
132
133   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
134                         droute_not_yet_handled_error (message));
135   count = atk_object_get_n_accessible_children (object);
136   reply = dbus_message_new_method_return (message);
137   if (!reply) goto oom;
138   dbus_message_iter_init_append (reply, &iter);
139   if (!dbus_message_iter_open_container
140       (&iter, DBUS_TYPE_ARRAY, "o", &iter_array))
141     goto oom;
142   for (i = 0; i < count; i++)
143     {
144       AtkObject *child = atk_object_ref_accessible_child (object, i);
145       char *path = atk_dbus_object_to_path (child, FALSE);
146       if (path)
147         {
148           dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_OBJECT_PATH,
149                                           &path);
150           g_free (path);
151         }
152       if (child)
153         g_object_unref (child);
154     }
155   if (!dbus_message_iter_close_container (&iter, &iter_array))
156     goto oom;
157   return reply;
158 oom:
159   // TODO: handle out-of-memory
160   return reply;
161 }
162
163 static DBusMessage *
164 impl_GetIndexInParent (DBusConnection *bus,
165                        DBusMessage *message,
166                        void *user_data)
167 {
168   AtkObject *object = (AtkObject *) user_data;
169   dbus_uint32_t rv;
170   DBusMessage *reply;
171
172   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
173                         droute_not_yet_handled_error (message));
174   rv = atk_object_get_index_in_parent (object);
175   reply = dbus_message_new_method_return (message);
176   if (reply)
177     {
178       dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
179                                 DBUS_TYPE_INVALID);
180     }
181   return reply;
182 }
183
184 static gboolean
185 spi_init_relation_type_table (Accessibility_RelationType *types)
186 {
187   gint i;
188
189   for (i = 0; i < ATK_RELATION_LAST_DEFINED; i++)
190     types[i] = Accessibility_RELATION_NULL;
191
192   types[ATK_RELATION_CONTROLLED_BY] = Accessibility_RELATION_CONTROLLED_BY;
193   types[ATK_RELATION_CONTROLLER_FOR] = Accessibility_RELATION_CONTROLLER_FOR;
194   types[ATK_RELATION_LABEL_FOR] = Accessibility_RELATION_LABEL_FOR;
195   types[ATK_RELATION_LABELLED_BY] = Accessibility_RELATION_LABELLED_BY;
196   types[ATK_RELATION_MEMBER_OF] = Accessibility_RELATION_MEMBER_OF;
197   types[ATK_RELATION_NODE_CHILD_OF] = Accessibility_RELATION_NODE_CHILD_OF;
198   types[ATK_RELATION_FLOWS_TO] = Accessibility_RELATION_FLOWS_TO;
199   types[ATK_RELATION_FLOWS_FROM] = Accessibility_RELATION_FLOWS_FROM;
200   types[ATK_RELATION_SUBWINDOW_OF] = Accessibility_RELATION_SUBWINDOW_OF;
201   types[ATK_RELATION_EMBEDS] = Accessibility_RELATION_EMBEDS;
202   types[ATK_RELATION_EMBEDDED_BY] = Accessibility_RELATION_EMBEDDED_BY;
203   types[ATK_RELATION_POPUP_FOR] = Accessibility_RELATION_POPUP_FOR;
204   types[ATK_RELATION_PARENT_WINDOW_OF] = Accessibility_RELATION_PARENT_WINDOW_OF;
205   types[ATK_RELATION_DESCRIPTION_FOR] = Accessibility_RELATION_DESCRIPTION_FOR;
206   types[ATK_RELATION_DESCRIBED_BY] = Accessibility_RELATION_DESCRIBED_BY;
207
208   return TRUE;
209 }
210
211 static Accessibility_RelationType
212 spi_relation_type_from_atk_relation_type (AtkRelationType type)
213 {
214   static gboolean is_initialized = FALSE;
215   static Accessibility_RelationType spi_relation_type_table [ATK_RELATION_LAST_DEFINED];
216   Accessibility_RelationType spi_type;
217
218   if (!is_initialized)
219     is_initialized = spi_init_relation_type_table (spi_relation_type_table);       
220
221   if (type > ATK_RELATION_NULL && type < ATK_RELATION_LAST_DEFINED)
222     spi_type = spi_relation_type_table[type];
223   else
224     spi_type = Accessibility_RELATION_EXTENDED;
225   return spi_type;
226 }
227
228 static DBusMessage *
229 impl_GetRelationSet (DBusConnection *bus,
230                      DBusMessage *message,
231                      void *user_data)
232 {
233   AtkObject *object = (AtkObject *) user_data;
234   DBusMessage *reply;
235   AtkRelationSet *set;
236   DBusMessageIter iter, iter_array, iter_struct, iter_targets;
237   gint count;
238   gint i, j;
239
240   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
241                         droute_not_yet_handled_error (message));
242   reply = dbus_message_new_method_return (message);
243   if (!reply) return NULL;
244   set = atk_object_ref_relation_set (object);
245   dbus_message_iter_init_append (reply, &iter);
246   if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ua(so))", &iter_array))
247   {
248     goto oom;
249   }
250   count = atk_relation_set_get_n_relations (set);
251   for (i = 0; i < count; i++)
252   {
253     AtkRelation *r = atk_relation_set_get_relation (set, i);
254     AtkRelationType rt;
255     GPtrArray *target;
256     dbus_uint32_t type;
257     if (!r) continue;
258     rt= atk_relation_get_relation_type (r);
259     type = spi_relation_type_from_atk_relation_type (rt);
260     target = atk_relation_get_target (r);
261     if (!dbus_message_iter_open_container (&iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct))
262     {
263       goto oom;
264     }
265     dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &type);
266     if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "(so)", &iter_targets))
267     {
268       goto oom;
269     }
270     for (j = 0; j < target->len; j++)
271     {
272       AtkObject *obj = target->pdata[j];
273       char *path;
274       if (!obj) continue;
275       path = atk_dbus_object_to_path (obj, FALSE);
276       if (!path)
277       {
278         g_warning ("Unknown object in relation type %d\n", type);
279         continue;
280       }
281       spi_dbus_append_name_and_path_inner (&iter_targets, NULL, path);
282     }
283     dbus_message_iter_close_container (&iter_struct, &iter_targets);
284     dbus_message_iter_close_container (&iter_array, &iter_struct);
285   }
286   dbus_message_iter_close_container (&iter, &iter_array);
287 oom:
288   // TODO: handle out of memory */
289   return reply;
290 }
291
292 static gboolean
293 spi_init_role_lookup_table (Accessibility_Role * role_table)
294 {
295   int i;
296   /* if it's not in the list below, dunno what it is */
297   for (i = 0; i < ATK_ROLE_LAST_DEFINED; ++i)
298     {
299       role_table[i] = Accessibility_ROLE_UNKNOWN;
300     }
301
302   role_table[ATK_ROLE_INVALID] = Accessibility_ROLE_INVALID;
303   role_table[ATK_ROLE_ACCEL_LABEL] = Accessibility_ROLE_ACCELERATOR_LABEL;
304   role_table[ATK_ROLE_ALERT] = Accessibility_ROLE_ALERT;
305   role_table[ATK_ROLE_ANIMATION] = Accessibility_ROLE_ANIMATION;
306   role_table[ATK_ROLE_ARROW] = Accessibility_ROLE_ARROW;
307   role_table[ATK_ROLE_CALENDAR] = Accessibility_ROLE_CALENDAR;
308   role_table[ATK_ROLE_CANVAS] = Accessibility_ROLE_CANVAS;
309   role_table[ATK_ROLE_CHECK_BOX] = Accessibility_ROLE_CHECK_BOX;
310   role_table[ATK_ROLE_CHECK_MENU_ITEM] = Accessibility_ROLE_CHECK_MENU_ITEM;
311   role_table[ATK_ROLE_COLOR_CHOOSER] = Accessibility_ROLE_COLOR_CHOOSER;
312   role_table[ATK_ROLE_COLUMN_HEADER] = Accessibility_ROLE_COLUMN_HEADER;
313   role_table[ATK_ROLE_COMBO_BOX] = Accessibility_ROLE_COMBO_BOX;
314   role_table[ATK_ROLE_DATE_EDITOR] = Accessibility_ROLE_DATE_EDITOR;
315   role_table[ATK_ROLE_DESKTOP_ICON] = Accessibility_ROLE_DESKTOP_ICON;
316   role_table[ATK_ROLE_DESKTOP_FRAME] = Accessibility_ROLE_DESKTOP_FRAME;
317   role_table[ATK_ROLE_DIAL] = Accessibility_ROLE_DIAL;
318   role_table[ATK_ROLE_DIALOG] = Accessibility_ROLE_DIALOG;
319   role_table[ATK_ROLE_DIRECTORY_PANE] = Accessibility_ROLE_DIRECTORY_PANE;
320   role_table[ATK_ROLE_DRAWING_AREA] = Accessibility_ROLE_DRAWING_AREA;
321   role_table[ATK_ROLE_FILE_CHOOSER] = Accessibility_ROLE_FILE_CHOOSER;
322   role_table[ATK_ROLE_FILLER] = Accessibility_ROLE_FILLER;
323   role_table[ATK_ROLE_FONT_CHOOSER] = Accessibility_ROLE_FONT_CHOOSER;
324   role_table[ATK_ROLE_FRAME] = Accessibility_ROLE_FRAME;
325   role_table[ATK_ROLE_GLASS_PANE] = Accessibility_ROLE_GLASS_PANE;
326   role_table[ATK_ROLE_HTML_CONTAINER] = Accessibility_ROLE_HTML_CONTAINER;
327   role_table[ATK_ROLE_ICON] = Accessibility_ROLE_ICON;
328   role_table[ATK_ROLE_IMAGE] = Accessibility_ROLE_IMAGE;
329   role_table[ATK_ROLE_INTERNAL_FRAME] = Accessibility_ROLE_INTERNAL_FRAME;
330   role_table[ATK_ROLE_LABEL] = Accessibility_ROLE_LABEL;
331   role_table[ATK_ROLE_LAYERED_PANE] = Accessibility_ROLE_LAYERED_PANE;
332   role_table[ATK_ROLE_LIST] = Accessibility_ROLE_LIST;
333   role_table[ATK_ROLE_LIST_ITEM] = Accessibility_ROLE_LIST_ITEM;
334   role_table[ATK_ROLE_MENU] = Accessibility_ROLE_MENU;
335   role_table[ATK_ROLE_MENU_BAR] = Accessibility_ROLE_MENU_BAR;
336   role_table[ATK_ROLE_MENU_ITEM] = Accessibility_ROLE_MENU_ITEM;
337   role_table[ATK_ROLE_OPTION_PANE] = Accessibility_ROLE_OPTION_PANE;
338   role_table[ATK_ROLE_PAGE_TAB] = Accessibility_ROLE_PAGE_TAB;
339   role_table[ATK_ROLE_PAGE_TAB_LIST] = Accessibility_ROLE_PAGE_TAB_LIST;
340   role_table[ATK_ROLE_PANEL] = Accessibility_ROLE_PANEL;
341   role_table[ATK_ROLE_PASSWORD_TEXT] = Accessibility_ROLE_PASSWORD_TEXT;
342   role_table[ATK_ROLE_POPUP_MENU] = Accessibility_ROLE_POPUP_MENU;
343   role_table[ATK_ROLE_PROGRESS_BAR] = Accessibility_ROLE_PROGRESS_BAR;
344   role_table[ATK_ROLE_PUSH_BUTTON] = Accessibility_ROLE_PUSH_BUTTON;
345   role_table[ATK_ROLE_RADIO_BUTTON] = Accessibility_ROLE_RADIO_BUTTON;
346   role_table[ATK_ROLE_RADIO_MENU_ITEM] = Accessibility_ROLE_RADIO_MENU_ITEM;
347   role_table[ATK_ROLE_ROOT_PANE] = Accessibility_ROLE_ROOT_PANE;
348   role_table[ATK_ROLE_ROW_HEADER] = Accessibility_ROLE_ROW_HEADER;
349   role_table[ATK_ROLE_SCROLL_BAR] = Accessibility_ROLE_SCROLL_BAR;
350   role_table[ATK_ROLE_SCROLL_PANE] = Accessibility_ROLE_SCROLL_PANE;
351   role_table[ATK_ROLE_SEPARATOR] = Accessibility_ROLE_SEPARATOR;
352   role_table[ATK_ROLE_SLIDER] = Accessibility_ROLE_SLIDER;
353   role_table[ATK_ROLE_SPIN_BUTTON] = Accessibility_ROLE_SPIN_BUTTON;
354   role_table[ATK_ROLE_SPLIT_PANE] = Accessibility_ROLE_SPLIT_PANE;
355   role_table[ATK_ROLE_STATUSBAR] = Accessibility_ROLE_STATUS_BAR;
356   role_table[ATK_ROLE_TABLE] = Accessibility_ROLE_TABLE;
357   role_table[ATK_ROLE_TABLE_CELL] = Accessibility_ROLE_TABLE_CELL;
358   role_table[ATK_ROLE_TABLE_COLUMN_HEADER] =
359     Accessibility_ROLE_TABLE_COLUMN_HEADER;
360   role_table[ATK_ROLE_TABLE_ROW_HEADER] = Accessibility_ROLE_TABLE_ROW_HEADER;
361   role_table[ATK_ROLE_TEAR_OFF_MENU_ITEM] =
362     Accessibility_ROLE_TEAROFF_MENU_ITEM;
363   role_table[ATK_ROLE_TERMINAL] = Accessibility_ROLE_TERMINAL;
364   role_table[ATK_ROLE_TEXT] = Accessibility_ROLE_TEXT;
365   role_table[ATK_ROLE_TOGGLE_BUTTON] = Accessibility_ROLE_TOGGLE_BUTTON;
366   role_table[ATK_ROLE_TOOL_BAR] = Accessibility_ROLE_TOOL_BAR;
367   role_table[ATK_ROLE_TOOL_TIP] = Accessibility_ROLE_TOOL_TIP;
368   role_table[ATK_ROLE_TREE] = Accessibility_ROLE_TREE;
369   role_table[ATK_ROLE_TREE_TABLE] = Accessibility_ROLE_TREE_TABLE;
370   role_table[ATK_ROLE_UNKNOWN] = Accessibility_ROLE_UNKNOWN;
371   role_table[ATK_ROLE_VIEWPORT] = Accessibility_ROLE_VIEWPORT;
372   role_table[ATK_ROLE_WINDOW] = Accessibility_ROLE_WINDOW;
373   role_table[ATK_ROLE_HEADER] = Accessibility_ROLE_HEADER;
374   role_table[ATK_ROLE_FOOTER] = Accessibility_ROLE_FOOTER;
375   role_table[ATK_ROLE_PARAGRAPH] = Accessibility_ROLE_PARAGRAPH;
376   role_table[ATK_ROLE_RULER] = Accessibility_ROLE_RULER;
377   role_table[ATK_ROLE_APPLICATION] = Accessibility_ROLE_APPLICATION;
378   role_table[ATK_ROLE_AUTOCOMPLETE] = Accessibility_ROLE_AUTOCOMPLETE;
379   role_table[ATK_ROLE_EDITBAR] = Accessibility_ROLE_EDITBAR;
380   role_table[ATK_ROLE_EMBEDDED] = Accessibility_ROLE_EMBEDDED;
381   role_table[ATK_ROLE_ENTRY] = Accessibility_ROLE_ENTRY;
382   role_table[ATK_ROLE_CHART] = Accessibility_ROLE_CHART;
383   role_table[ATK_ROLE_CAPTION] = Accessibility_ROLE_CAPTION;
384   role_table[ATK_ROLE_DOCUMENT_FRAME] = Accessibility_ROLE_DOCUMENT_FRAME;
385   role_table[ATK_ROLE_HEADING] = Accessibility_ROLE_HEADING;
386   role_table[ATK_ROLE_PAGE] = Accessibility_ROLE_PAGE;
387   role_table[ATK_ROLE_SECTION] = Accessibility_ROLE_SECTION;
388   role_table[ATK_ROLE_FORM] = Accessibility_ROLE_FORM;
389   role_table[ATK_ROLE_REDUNDANT_OBJECT] = Accessibility_ROLE_REDUNDANT_OBJECT;
390   role_table[ATK_ROLE_LINK] = Accessibility_ROLE_LINK;
391   role_table[ATK_ROLE_INPUT_METHOD_WINDOW] =
392     Accessibility_ROLE_INPUT_METHOD_WINDOW;
393   return TRUE;
394 }
395
396 Accessibility_Role
397 spi_accessible_role_from_atk_role (AtkRole role)
398 {
399   static gboolean is_initialized = FALSE;
400   static Accessibility_Role spi_role_table[ATK_ROLE_LAST_DEFINED];
401   Accessibility_Role spi_role;
402
403   if (!is_initialized)
404     {
405       is_initialized = spi_init_role_lookup_table (spi_role_table);
406     }
407
408   if (role >= 0 && role < ATK_ROLE_LAST_DEFINED)
409     {
410       spi_role = spi_role_table[role];
411     }
412   else
413     {
414       spi_role = Accessibility_ROLE_EXTENDED;
415     }
416   return spi_role;
417 }
418
419 static DBusMessage *
420 impl_GetRole (DBusConnection *bus, DBusMessage *message, void *user_data)
421 {
422   AtkObject *object = (AtkObject *) user_data;
423   gint role;
424   dbus_uint32_t rv;
425   DBusMessage *reply;
426
427   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
428                         droute_not_yet_handled_error (message));
429   role = atk_object_get_role (object);
430   rv = spi_accessible_role_from_atk_role (role);
431   reply = dbus_message_new_method_return (message);
432   if (reply)
433     {
434       dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
435                                 DBUS_TYPE_INVALID);
436     }
437   return reply;
438 }
439
440 static char *
441 impl_get_role_str (void *datum)
442 {
443   g_return_val_if_fail (ATK_IS_OBJECT (datum), g_strdup (""));
444   return g_strdup_printf ("%d",
445                           spi_accessible_role_from_atk_role
446                           (atk_object_get_role ((AtkObject *) datum)));
447 }
448
449 static DBusMessage *
450 impl_GetRoleName (DBusConnection *bus,
451                   DBusMessage *message,
452                   void *user_data)
453 {
454   AtkObject *object = (AtkObject *) user_data;
455   gint role;
456   const char *role_name;
457   DBusMessage *reply;
458
459   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
460                         droute_not_yet_handled_error (message));
461   role = atk_object_get_role (object);
462   role_name = atk_role_get_name (role);
463   if (!role_name)
464     role_name = "";
465   reply = dbus_message_new_method_return (message);
466   if (reply)
467     {
468       dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
469                                 DBUS_TYPE_INVALID);
470     }
471   return reply;
472 }
473
474 static DBusMessage *
475 impl_GetLocalizedRoleName (DBusConnection *bus,
476                            DBusMessage *message,
477                            void *user_data)
478 {
479   AtkObject *object = (AtkObject *) user_data;
480   gint role;
481   const char *role_name;
482   DBusMessage *reply;
483
484   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
485                         droute_not_yet_handled_error (message));
486   role = atk_object_get_role (object);
487   role_name = atk_role_get_localized_name (role);
488   if (!role_name)
489     role_name = "";
490   reply = dbus_message_new_method_return (message);
491   if (reply)
492     {
493       dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
494                                 DBUS_TYPE_INVALID);
495     }
496   return reply;
497 }
498
499 static DBusMessage *
500 impl_GetState (DBusConnection *bus,
501                DBusMessage *message,
502                void *user_data)
503 {
504   AtkObject *object = (AtkObject *) user_data;
505
506   DBusMessage    *reply = NULL;
507   DBusMessageIter iter, iter_array;
508
509   dbus_uint32_t  states [2];
510
511   guint count;
512
513   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
514                         droute_not_yet_handled_error (message));
515
516   reply = dbus_message_new_method_return (message);
517   dbus_message_iter_init_append (reply, &iter);
518
519   spi_atk_state_to_dbus_array (object, states);
520   dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "u", &iter_array);
521   for (count = 0; count < 2; count++)
522     {
523       dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_UINT32, &states[count]);
524     }
525   dbus_message_iter_close_container (&iter, &iter_array);
526   return reply;
527 }
528
529 static DBusMessage *
530 impl_GetAttributes (DBusConnection *bus,
531                     DBusMessage *message,
532                     void *user_data)
533 {
534   AtkObject *object = (AtkObject *) user_data;
535   DBusMessage *reply = NULL;
536
537   AtkAttributeSet *attributes;
538   DBusMessageIter iter;
539
540   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
541                         droute_not_yet_handled_error (message));
542
543   attributes = atk_object_get_attributes (object);
544
545   reply = dbus_message_new_method_return (message);
546   dbus_message_iter_init_append (reply, &iter);
547   spi_atk_append_attribute_set (&iter, attributes);
548
549   if (attributes)
550     atk_attribute_set_free (attributes);
551
552   return reply;
553 }
554
555 static DBusMessage *
556 impl_GetApplication (DBusConnection *bus,
557                      DBusMessage *message,
558                      void *user_data)
559 {
560   AtkObject *root = atk_get_root ();
561   return spi_dbus_return_object (message, root, FALSE, FALSE);
562 }
563
564 static DBusMessage *
565 impl_GetInterfaces (DBusConnection *bus,
566                     DBusMessage *message,
567                     void *user_data)
568 {
569   AtkObject *object = (AtkObject *) user_data;
570   gint role;
571   const char *role_name;
572   DBusMessage *reply;
573   DBusMessageIter iter, iter_array;
574
575   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
576                         droute_not_yet_handled_error (message));
577   reply = dbus_message_new_method_return (message);
578   if (reply)
579     {
580       dbus_message_iter_init_append (reply, &iter);
581       dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &iter_array);
582       append_atk_object_interfaces (object, &iter_array);
583       dbus_message_iter_close_container (&iter, &iter_array);
584     }
585   return reply;
586 }
587
588 static DBusMessage *
589 impl_Embedded (DBusConnection *bus,
590                     DBusMessage *message,
591                     void *user_data)
592 {
593   AtkObject *object = (AtkObject *) user_data;
594   char *path;
595   gchar *id;
596
597   if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID))
598     {
599       return droute_invalid_arguments_error (message);
600     }
601   id = g_object_get_data (G_OBJECT (object), "dbus-plug-parent");
602   if (id)
603     g_free (id);
604   id = g_strconcat (dbus_message_get_sender (message), ":", path, NULL);
605   g_object_set_data (G_OBJECT (object), "dbus-plug-parent", id);
606   return dbus_message_new_method_return (message);
607 }
608
609 static DRouteMethod methods[] = {
610   {impl_GetChildAtIndex, "GetChildAtIndex"},
611   {impl_GetChildren, "GetChildren"},
612   {impl_GetIndexInParent, "GetIndexInParent"},
613   {impl_GetRelationSet, "GetRelationSet"},
614   {impl_GetRole, "GetRole"},
615   {impl_GetRoleName, "GetRoleName"},
616   {impl_GetLocalizedRoleName, "GetLocalizedRoleName"},
617   {impl_GetState, "GetState"},
618   {impl_GetAttributes, "GetAttributes"},
619   {impl_GetApplication, "GetApplication"},
620   {impl_GetInterfaces, "GetInterfaces"},
621   {impl_Embedded, "Embedded"},
622   {NULL, NULL}
623 };
624
625 static DRouteProperty properties[] = {
626   {impl_get_Name, impl_set_Name, "Name"},
627   {impl_get_Description, impl_set_Description, "Description"},
628   {impl_get_Parent, NULL, "Parent"},
629   {impl_get_ChildCount, NULL, "ChildCount"},
630   {NULL, NULL, NULL}
631 };
632
633 void
634 spi_initialize_accessible (DRoutePath *path)
635 {
636   droute_path_add_interface (path,
637                              SPI_DBUS_INTERFACE_ACCESSIBLE,
638                              methods,
639                              properties);
640 };