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