2 * AT-SPI - Assistive Technology Service Provider Interface
3 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
5 * Copyright 2008 Novell, Inc.
6 * Copyright 2001, 2002 Sun Microsystems Inc.,
7 * Copyright 2001, 2002 Ximian, Inc.
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.
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.
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.
26 #include <droute/droute.h>
29 #include "spi-common/spi-dbus.h"
32 impl_get_name (DBusMessageIter *iter, void *user_data)
34 AtkObject *object = (AtkObject *) user_data;
36 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
38 return droute_return_v_string (iter, atk_object_get_name (object));
42 impl_set_name (DBusMessageIter *iter, void *user_data)
44 AtkObject *object = (AtkObject *) user_data;
45 const char *name = droute_get_v_string (iter);
47 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
49 atk_object_set_name (object, name);
54 impl_get_description (DBusMessageIter *iter, void *user_data)
56 AtkObject *object = (AtkObject *) user_data;
58 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
60 return droute_return_v_string (iter, atk_object_get_description (object));
64 impl_set_description (DBusMessageIter *iter, void *user_data)
66 AtkObject *object = (AtkObject *) user_data;
67 const char *description = droute_get_v_string (iter);
69 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
71 atk_object_set_description (object, description);
76 impl_get_parent (DBusMessageIter *iter, void *user_data)
78 AtkObject *object = (AtkObject *) user_data;
80 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
82 return spi_dbus_return_v_object (iter,
83 atk_object_get_parent (object),
88 impl_get_childCount (DBusMessageIter *iter, void *user_data)
90 AtkObject *object = (AtkObject *) user_data;
92 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
94 return droute_return_v_int32 (iter,
95 atk_object_get_n_accessible_children
100 impl_getChildAtIndex (DBusConnection *bus,
101 DBusMessage *message,
104 AtkObject *object = (AtkObject *) user_data;
109 dbus_error_init (&error);
110 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
111 droute_not_yet_handled_error (message));
112 if (!dbus_message_get_args (message, &error, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID))
113 return spi_dbus_general_error (message);
114 child = atk_object_ref_accessible_child (object, i);
115 return spi_dbus_return_object (message, child, FALSE);
119 impl_getChildren (DBusConnection *bus,
120 DBusMessage *message,
123 AtkObject *object = (AtkObject *) user_data;
127 DBusMessageIter iter, iter_array;
129 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
130 droute_not_yet_handled_error (message));
131 count = atk_object_get_n_accessible_children (object);
132 reply = dbus_message_new_method_return (message);
133 if (!reply) goto oom;
134 dbus_message_iter_init_append (reply, &iter);
135 if (!dbus_message_iter_open_container
136 (&iter, DBUS_TYPE_ARRAY, "o", &iter_array))
138 for (i = 0; i < count; i++)
140 AtkObject *child = atk_object_ref_accessible_child (object, i);
141 char *path = atk_dbus_get_path (child);
144 dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_OBJECT_PATH,
149 g_object_unref (child);
151 if (!dbus_message_iter_close_container (&iter, &iter_array))
155 // TODO: handle out-of-memory
160 impl_getIndexInParent (DBusConnection *bus,
161 DBusMessage *message,
164 AtkObject *object = (AtkObject *) user_data;
168 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
169 droute_not_yet_handled_error (message));
170 rv = atk_object_get_index_in_parent (object);
171 reply = dbus_message_new_method_return (message);
174 dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
181 spi_init_relation_type_table (Accessibility_RelationType *types)
185 for (i = 0; i < ATK_RELATION_LAST_DEFINED; i++)
186 types[i] = Accessibility_RELATION_NULL;
188 types[ATK_RELATION_CONTROLLED_BY] = Accessibility_RELATION_CONTROLLED_BY;
189 types[ATK_RELATION_CONTROLLER_FOR] = Accessibility_RELATION_CONTROLLER_FOR;
190 types[ATK_RELATION_LABEL_FOR] = Accessibility_RELATION_LABEL_FOR;
191 types[ATK_RELATION_LABELLED_BY] = Accessibility_RELATION_LABELLED_BY;
192 types[ATK_RELATION_MEMBER_OF] = Accessibility_RELATION_MEMBER_OF;
193 types[ATK_RELATION_NODE_CHILD_OF] = Accessibility_RELATION_NODE_CHILD_OF;
194 types[ATK_RELATION_FLOWS_TO] = Accessibility_RELATION_FLOWS_TO;
195 types[ATK_RELATION_FLOWS_FROM] = Accessibility_RELATION_FLOWS_FROM;
196 types[ATK_RELATION_SUBWINDOW_OF] = Accessibility_RELATION_SUBWINDOW_OF;
197 types[ATK_RELATION_EMBEDS] = Accessibility_RELATION_EMBEDS;
198 types[ATK_RELATION_EMBEDDED_BY] = Accessibility_RELATION_EMBEDDED_BY;
199 types[ATK_RELATION_POPUP_FOR] = Accessibility_RELATION_POPUP_FOR;
200 types[ATK_RELATION_PARENT_WINDOW_OF] = Accessibility_RELATION_PARENT_WINDOW_OF;
201 types[ATK_RELATION_DESCRIPTION_FOR] = Accessibility_RELATION_DESCRIPTION_FOR;
202 types[ATK_RELATION_DESCRIBED_BY] = Accessibility_RELATION_DESCRIBED_BY;
207 static Accessibility_RelationType
208 spi_relation_type_from_atk_relation_type (AtkRelationType type)
210 static gboolean is_initialized = FALSE;
211 static Accessibility_RelationType spi_relation_type_table [ATK_RELATION_LAST_DEFINED];
212 Accessibility_RelationType spi_type;
215 is_initialized = spi_init_relation_type_table (spi_relation_type_table);
217 if (type > ATK_RELATION_NULL && type < ATK_RELATION_LAST_DEFINED)
218 spi_type = spi_relation_type_table[type];
220 spi_type = Accessibility_RELATION_EXTENDED;
225 impl_getRelationSet (DBusConnection *bus,
226 DBusMessage *message,
229 AtkObject *object = (AtkObject *) user_data;
232 DBusMessageIter iter, iter_array, iter_struct, iter_targets;
236 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
237 droute_not_yet_handled_error (message));
238 reply = dbus_message_new_method_return (message);
239 if (!reply) return NULL;
240 set = atk_object_ref_relation_set (object);
241 dbus_message_iter_init_append (reply, &iter);
242 if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(uao)", &iter_array))
246 count = atk_relation_set_get_n_relations (set);
247 for (i = 0; i < count; i++)
249 AtkRelation *r = atk_relation_set_get_relation (set, i);
254 rt= atk_relation_get_relation_type (r);
255 type = spi_relation_type_from_atk_relation_type (rt);
256 target = atk_relation_get_target (r);
257 if (!dbus_message_iter_open_container (&iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct))
261 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &type);
262 if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "o", &iter_targets))
266 for (j = 0; j < target->len; j++)
268 AtkObject *obj = target->pdata[j];
271 path = atk_dbus_get_path (obj);
272 dbus_message_iter_append_basic (&iter_targets, DBUS_TYPE_OBJECT_PATH, &path);
274 dbus_message_iter_close_container (&iter_struct, &iter_targets);
275 dbus_message_iter_close_container (&iter_array, &iter_struct);
277 dbus_message_iter_close_container (&iter, &iter_array);
279 // TODO: handle out of memory */
284 spi_init_role_lookup_table (Accessibility_Role * role_table)
287 /* if it's not in the list below, dunno what it is */
288 for (i = 0; i < ATK_ROLE_LAST_DEFINED; ++i)
290 role_table[i] = Accessibility_ROLE_UNKNOWN;
293 role_table[ATK_ROLE_INVALID] = Accessibility_ROLE_INVALID;
294 role_table[ATK_ROLE_ACCEL_LABEL] = Accessibility_ROLE_ACCELERATOR_LABEL;
295 role_table[ATK_ROLE_ALERT] = Accessibility_ROLE_ALERT;
296 role_table[ATK_ROLE_ANIMATION] = Accessibility_ROLE_ANIMATION;
297 role_table[ATK_ROLE_ARROW] = Accessibility_ROLE_ARROW;
298 role_table[ATK_ROLE_CALENDAR] = Accessibility_ROLE_CALENDAR;
299 role_table[ATK_ROLE_CANVAS] = Accessibility_ROLE_CANVAS;
300 role_table[ATK_ROLE_CHECK_BOX] = Accessibility_ROLE_CHECK_BOX;
301 role_table[ATK_ROLE_CHECK_MENU_ITEM] = Accessibility_ROLE_CHECK_MENU_ITEM;
302 role_table[ATK_ROLE_COLOR_CHOOSER] = Accessibility_ROLE_COLOR_CHOOSER;
303 role_table[ATK_ROLE_COLUMN_HEADER] = Accessibility_ROLE_COLUMN_HEADER;
304 role_table[ATK_ROLE_COMBO_BOX] = Accessibility_ROLE_COMBO_BOX;
305 role_table[ATK_ROLE_DATE_EDITOR] = Accessibility_ROLE_DATE_EDITOR;
306 role_table[ATK_ROLE_DESKTOP_ICON] = Accessibility_ROLE_DESKTOP_ICON;
307 role_table[ATK_ROLE_DESKTOP_FRAME] = Accessibility_ROLE_DESKTOP_FRAME;
308 role_table[ATK_ROLE_DIAL] = Accessibility_ROLE_DIAL;
309 role_table[ATK_ROLE_DIALOG] = Accessibility_ROLE_DIALOG;
310 role_table[ATK_ROLE_DIRECTORY_PANE] = Accessibility_ROLE_DIRECTORY_PANE;
311 role_table[ATK_ROLE_DRAWING_AREA] = Accessibility_ROLE_DRAWING_AREA;
312 role_table[ATK_ROLE_FILE_CHOOSER] = Accessibility_ROLE_FILE_CHOOSER;
313 role_table[ATK_ROLE_FILLER] = Accessibility_ROLE_FILLER;
314 role_table[ATK_ROLE_FONT_CHOOSER] = Accessibility_ROLE_FONT_CHOOSER;
315 role_table[ATK_ROLE_FRAME] = Accessibility_ROLE_FRAME;
316 role_table[ATK_ROLE_GLASS_PANE] = Accessibility_ROLE_GLASS_PANE;
317 role_table[ATK_ROLE_HTML_CONTAINER] = Accessibility_ROLE_HTML_CONTAINER;
318 role_table[ATK_ROLE_ICON] = Accessibility_ROLE_ICON;
319 role_table[ATK_ROLE_IMAGE] = Accessibility_ROLE_IMAGE;
320 role_table[ATK_ROLE_INTERNAL_FRAME] = Accessibility_ROLE_INTERNAL_FRAME;
321 role_table[ATK_ROLE_LABEL] = Accessibility_ROLE_LABEL;
322 role_table[ATK_ROLE_LAYERED_PANE] = Accessibility_ROLE_LAYERED_PANE;
323 role_table[ATK_ROLE_LIST] = Accessibility_ROLE_LIST;
324 role_table[ATK_ROLE_LIST_ITEM] = Accessibility_ROLE_LIST_ITEM;
325 role_table[ATK_ROLE_MENU] = Accessibility_ROLE_MENU;
326 role_table[ATK_ROLE_MENU_BAR] = Accessibility_ROLE_MENU_BAR;
327 role_table[ATK_ROLE_MENU_ITEM] = Accessibility_ROLE_MENU_ITEM;
328 role_table[ATK_ROLE_OPTION_PANE] = Accessibility_ROLE_OPTION_PANE;
329 role_table[ATK_ROLE_PAGE_TAB] = Accessibility_ROLE_PAGE_TAB;
330 role_table[ATK_ROLE_PAGE_TAB_LIST] = Accessibility_ROLE_PAGE_TAB_LIST;
331 role_table[ATK_ROLE_PANEL] = Accessibility_ROLE_PANEL;
332 role_table[ATK_ROLE_PASSWORD_TEXT] = Accessibility_ROLE_PASSWORD_TEXT;
333 role_table[ATK_ROLE_POPUP_MENU] = Accessibility_ROLE_POPUP_MENU;
334 role_table[ATK_ROLE_PROGRESS_BAR] = Accessibility_ROLE_PROGRESS_BAR;
335 role_table[ATK_ROLE_PUSH_BUTTON] = Accessibility_ROLE_PUSH_BUTTON;
336 role_table[ATK_ROLE_RADIO_BUTTON] = Accessibility_ROLE_RADIO_BUTTON;
337 role_table[ATK_ROLE_RADIO_MENU_ITEM] = Accessibility_ROLE_RADIO_MENU_ITEM;
338 role_table[ATK_ROLE_ROOT_PANE] = Accessibility_ROLE_ROOT_PANE;
339 role_table[ATK_ROLE_ROW_HEADER] = Accessibility_ROLE_ROW_HEADER;
340 role_table[ATK_ROLE_SCROLL_BAR] = Accessibility_ROLE_SCROLL_BAR;
341 role_table[ATK_ROLE_SCROLL_PANE] = Accessibility_ROLE_SCROLL_PANE;
342 role_table[ATK_ROLE_SEPARATOR] = Accessibility_ROLE_SEPARATOR;
343 role_table[ATK_ROLE_SLIDER] = Accessibility_ROLE_SLIDER;
344 role_table[ATK_ROLE_SPIN_BUTTON] = Accessibility_ROLE_SPIN_BUTTON;
345 role_table[ATK_ROLE_SPLIT_PANE] = Accessibility_ROLE_SPLIT_PANE;
346 role_table[ATK_ROLE_STATUSBAR] = Accessibility_ROLE_STATUS_BAR;
347 role_table[ATK_ROLE_TABLE] = Accessibility_ROLE_TABLE;
348 role_table[ATK_ROLE_TABLE_CELL] = Accessibility_ROLE_TABLE_CELL;
349 role_table[ATK_ROLE_TABLE_COLUMN_HEADER] =
350 Accessibility_ROLE_TABLE_COLUMN_HEADER;
351 role_table[ATK_ROLE_TABLE_ROW_HEADER] = Accessibility_ROLE_TABLE_ROW_HEADER;
352 role_table[ATK_ROLE_TEAR_OFF_MENU_ITEM] =
353 Accessibility_ROLE_TEAROFF_MENU_ITEM;
354 role_table[ATK_ROLE_TERMINAL] = Accessibility_ROLE_TERMINAL;
355 role_table[ATK_ROLE_TEXT] = Accessibility_ROLE_TEXT;
356 role_table[ATK_ROLE_TOGGLE_BUTTON] = Accessibility_ROLE_TOGGLE_BUTTON;
357 role_table[ATK_ROLE_TOOL_BAR] = Accessibility_ROLE_TOOL_BAR;
358 role_table[ATK_ROLE_TOOL_TIP] = Accessibility_ROLE_TOOL_TIP;
359 role_table[ATK_ROLE_TREE] = Accessibility_ROLE_TREE;
360 role_table[ATK_ROLE_TREE_TABLE] = Accessibility_ROLE_TREE_TABLE;
361 role_table[ATK_ROLE_UNKNOWN] = Accessibility_ROLE_UNKNOWN;
362 role_table[ATK_ROLE_VIEWPORT] = Accessibility_ROLE_VIEWPORT;
363 role_table[ATK_ROLE_WINDOW] = Accessibility_ROLE_WINDOW;
364 role_table[ATK_ROLE_HEADER] = Accessibility_ROLE_HEADER;
365 role_table[ATK_ROLE_FOOTER] = Accessibility_ROLE_FOOTER;
366 role_table[ATK_ROLE_PARAGRAPH] = Accessibility_ROLE_PARAGRAPH;
367 role_table[ATK_ROLE_RULER] = Accessibility_ROLE_RULER;
368 role_table[ATK_ROLE_APPLICATION] = Accessibility_ROLE_APPLICATION;
369 role_table[ATK_ROLE_AUTOCOMPLETE] = Accessibility_ROLE_AUTOCOMPLETE;
370 role_table[ATK_ROLE_EDITBAR] = Accessibility_ROLE_EDITBAR;
371 role_table[ATK_ROLE_EMBEDDED] = Accessibility_ROLE_EMBEDDED;
372 role_table[ATK_ROLE_ENTRY] = Accessibility_ROLE_ENTRY;
373 role_table[ATK_ROLE_CHART] = Accessibility_ROLE_CHART;
374 role_table[ATK_ROLE_CAPTION] = Accessibility_ROLE_CAPTION;
375 role_table[ATK_ROLE_DOCUMENT_FRAME] = Accessibility_ROLE_DOCUMENT_FRAME;
376 role_table[ATK_ROLE_HEADING] = Accessibility_ROLE_HEADING;
377 role_table[ATK_ROLE_PAGE] = Accessibility_ROLE_PAGE;
378 role_table[ATK_ROLE_SECTION] = Accessibility_ROLE_SECTION;
379 role_table[ATK_ROLE_FORM] = Accessibility_ROLE_FORM;
380 role_table[ATK_ROLE_REDUNDANT_OBJECT] = Accessibility_ROLE_REDUNDANT_OBJECT;
381 role_table[ATK_ROLE_LINK] = Accessibility_ROLE_LINK;
382 role_table[ATK_ROLE_INPUT_METHOD_WINDOW] =
383 Accessibility_ROLE_INPUT_METHOD_WINDOW;
388 spi_accessible_role_from_atk_role (AtkRole role)
390 static gboolean is_initialized = FALSE;
391 static Accessibility_Role spi_role_table[ATK_ROLE_LAST_DEFINED];
392 Accessibility_Role spi_role;
396 is_initialized = spi_init_role_lookup_table (spi_role_table);
399 if (role >= 0 && role < ATK_ROLE_LAST_DEFINED)
401 spi_role = spi_role_table[role];
405 spi_role = Accessibility_ROLE_EXTENDED;
411 impl_getRole (DBusConnection *bus, DBusMessage *message, void *user_data)
413 AtkObject *object = (AtkObject *) user_data;
418 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
419 droute_not_yet_handled_error (message));
420 role = atk_object_get_role (object);
421 rv = spi_accessible_role_from_atk_role (role);
422 reply = dbus_message_new_method_return (message);
425 dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
432 impl_get_role_str (void *datum)
434 g_assert (ATK_IS_OBJECT (datum));
435 return g_strdup_printf ("%d",
436 spi_accessible_role_from_atk_role
437 (atk_object_get_role ((AtkObject *) datum)));
441 impl_getRoleName (DBusConnection *bus,
442 DBusMessage *message,
445 AtkObject *object = (AtkObject *) user_data;
447 const char *role_name;
450 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
451 droute_not_yet_handled_error (message));
452 role = atk_object_get_role (object);
453 role_name = atk_role_get_name (role);
456 reply = dbus_message_new_method_return (message);
459 dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
466 impl_getLocalizedRoleName (DBusConnection *bus,
467 DBusMessage *message,
470 AtkObject *object = (AtkObject *) user_data;
472 const char *role_name;
475 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
476 droute_not_yet_handled_error (message));
477 role = atk_object_get_role (object);
478 role_name = atk_role_get_localized_name (role);
481 reply = dbus_message_new_method_return (message);
484 dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
491 impl_getState (DBusConnection *bus,
492 DBusMessage *message,
495 AtkObject *object = (AtkObject *) user_data;
497 dbus_uint32_t *array = rv;
500 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
501 droute_not_yet_handled_error (message));
502 spi_atk_state_to_dbus_array (object, rv);
503 reply = dbus_message_new_method_return (message);
506 dbus_message_append_args (reply, DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &array,
507 2, DBUS_TYPE_INVALID);
513 impl_getAttributes (DBusConnection *bus,
514 DBusMessage *message,
517 AtkObject *object = (AtkObject *) user_data;
519 AtkAttributeSet *attributes;
520 AtkAttribute *attr = NULL;
522 gint n_attributes = 0;
525 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
526 droute_not_yet_handled_error (message));
528 attributes = atk_object_get_attributes (object);
530 n_attributes = g_slist_length (attributes);
532 retval = (char **) g_malloc (n_attributes * sizeof (char *));
534 for (i = 0; i < n_attributes; ++i)
536 attr = g_slist_nth_data (attributes, i);
537 retval[i] = g_strconcat (attr->name, ":", attr->value, NULL);
540 atk_attribute_set_free (attributes);
541 reply = dbus_message_new_method_return (message);
544 dbus_message_append_args (reply, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
545 &retval, n_attributes, DBUS_TYPE_INVALID);
547 for (i = 0; i < n_attributes; i++)
554 impl_getApplication (DBusConnection *bus,
555 DBusMessage *message,
558 AtkObject *root = atk_get_root ();
559 return spi_dbus_return_object (message, root, FALSE);
562 static DRouteMethod methods[] = {
563 {impl_getChildAtIndex, "getChildAtIndex"},
564 {impl_getChildren, "getChildren"},
565 {impl_getIndexInParent, "getIndexInParent"},
566 {impl_getRelationSet, "getRelationSet"},
567 {impl_getRole, "getRole"},
568 {impl_getRoleName, "getRoleName"},
569 {impl_getLocalizedRoleName, "getLocalizedRoleName"},
570 {impl_getState, "getState"},
571 {impl_getAttributes, "getAttributes"},
572 {impl_getApplication, "getApplication"},
576 static DRouteProperty properties[] = {
577 {impl_get_name, impl_set_name, "name"},
578 {impl_get_description, impl_set_description, "description"},
579 {impl_get_parent, NULL, "parent"},
580 {impl_get_childCount, NULL, "childCount"},
585 spi_initialize_accessible (DRoutePath *path)
587 droute_path_add_interface (path,
588 SPI_DBUS_INTERFACE_ACCESSIBLE,