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 Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 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 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
26 #include <droute/droute.h>
29 #include "atspi/atspi.h"
31 #include "accessible-stateset.h"
33 #include "introspection.h"
37 impl_get_Name (DBusMessageIter * iter, void *user_data)
39 AtkObject *object = (AtkObject *) user_data;
41 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
43 return droute_return_v_string (iter, atk_object_get_name (object));
47 impl_get_Description (DBusMessageIter * iter, void *user_data)
49 AtkObject *object = (AtkObject *) user_data;
51 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
53 return droute_return_v_string (iter, atk_object_get_description (object));
57 impl_get_Locale (DBusMessageIter * iter, void *user_data)
59 AtkObject *object = (AtkObject *) user_data;
61 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
63 return droute_return_v_string (iter, atk_object_get_object_locale (object));
67 impl_get_Parent (DBusMessageIter * iter, void *user_data)
69 AtkObject *obj = (AtkObject *) user_data;
71 DBusMessageIter iter_variant;
74 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
76 role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));
78 dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "(so)",
81 parent = atk_object_get_parent (obj);
84 /* TODO, move in to a 'Plug' wrapper. */
85 if (ATK_IS_PLUG (obj))
87 char *id = g_object_get_data (G_OBJECT (obj), "dbus-plug-parent");
93 bus_parent = g_strdup (id);
94 if (bus_parent && (path_parent = g_utf8_strchr (bus_parent + 1, -1, ':')))
96 DBusMessageIter iter_parent;
97 *(path_parent++) = '\0';
98 dbus_message_iter_open_container (&iter_variant, DBUS_TYPE_STRUCT, NULL,
100 dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_STRING, &bus_parent);
101 dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_OBJECT_PATH, &path_parent);
102 dbus_message_iter_close_container (&iter_variant, &iter_parent);
106 spi_object_append_null_reference (&iter_variant);
111 spi_object_append_null_reference (&iter_variant);
114 else if (role != ATSPI_ROLE_APPLICATION)
115 spi_object_append_null_reference (&iter_variant);
117 spi_object_append_desktop_reference (&iter_variant);
121 spi_object_append_reference (&iter_variant, parent);
125 dbus_message_iter_close_container (iter, &iter_variant);
130 impl_get_ChildCount (DBusMessageIter * iter, void *user_data)
132 AtkObject *object = (AtkObject *) user_data;
135 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
137 childCount = (ATK_IS_SOCKET (object) && atk_socket_is_occupied (ATK_SOCKET (object)))
139 : atk_object_get_n_accessible_children (object);
140 return droute_return_v_int32 (iter, childCount);
144 impl_GetChildAtIndex (DBusConnection * bus,
145 DBusMessage * message, void *user_data)
147 AtkObject *object = (AtkObject *) user_data;
152 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
153 droute_not_yet_handled_error (message));
154 if (!dbus_message_get_args
155 (message, NULL, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID))
157 return droute_invalid_arguments_error (message);
160 if (ATK_IS_SOCKET (object) && atk_socket_is_occupied (ATK_SOCKET (object)) && i == 0)
162 AtkSocket *socket = ATK_SOCKET (object);
163 gchar *child_name, *child_path;
164 child_name = g_strdup (socket->embedded_plug_id);
165 child_path = g_utf8_strchr (child_name + 1, -1, ':');
168 DBusMessageIter iter, iter_socket;
169 *(child_path++) = '\0';
170 reply = dbus_message_new_method_return (message);
173 dbus_message_iter_init_append (reply, &iter);
174 dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL,
176 dbus_message_iter_append_basic (&iter_socket, DBUS_TYPE_STRING, &child_name);
177 dbus_message_iter_append_basic (&iter_socket, DBUS_TYPE_OBJECT_PATH, &child_path);
178 dbus_message_iter_close_container (&iter, &iter_socket);
183 child = atk_object_ref_accessible_child (object, i);
184 reply = spi_object_return_reference (message, child);
186 g_object_unref (child);
192 impl_GetChildren (DBusConnection * bus,
193 DBusMessage * message, void *user_data)
195 AtkObject *object = (AtkObject *) user_data;
199 DBusMessageIter iter, iter_array;
201 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
202 droute_not_yet_handled_error (message));
203 count = atk_object_get_n_accessible_children (object);
204 reply = dbus_message_new_method_return (message);
207 dbus_message_iter_init_append (reply, &iter);
208 if (!dbus_message_iter_open_container
209 (&iter, DBUS_TYPE_ARRAY, "(so)", &iter_array))
211 for (i = 0; i < count; i++)
213 AtkObject *child = atk_object_ref_accessible_child (object, i);
214 spi_object_append_reference (&iter_array, child);
216 g_object_unref (child);
218 if (!dbus_message_iter_close_container (&iter, &iter_array))
222 // TODO: handle out-of-memory
227 impl_GetIndexInParent (DBusConnection * bus,
228 DBusMessage * message, void *user_data)
230 AtkObject *object = (AtkObject *) user_data;
234 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
235 droute_not_yet_handled_error (message));
237 rv = atk_object_get_index_in_parent (object);
238 reply = dbus_message_new_method_return (message);
239 dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv, DBUS_TYPE_INVALID);
244 spi_init_relation_type_table (AtspiRelationType * types)
248 for (i = 0; i < ATK_RELATION_LAST_DEFINED; i++)
249 types[i] = ATSPI_RELATION_NULL;
251 types[ATK_RELATION_CONTROLLED_BY] = ATSPI_RELATION_CONTROLLED_BY;
252 types[ATK_RELATION_CONTROLLER_FOR] = ATSPI_RELATION_CONTROLLER_FOR;
253 types[ATK_RELATION_LABEL_FOR] = ATSPI_RELATION_LABEL_FOR;
254 types[ATK_RELATION_LABELLED_BY] = ATSPI_RELATION_LABELLED_BY;
255 types[ATK_RELATION_MEMBER_OF] = ATSPI_RELATION_MEMBER_OF;
256 types[ATK_RELATION_NODE_CHILD_OF] = ATSPI_RELATION_NODE_CHILD_OF;
257 types[ATK_RELATION_FLOWS_TO] = ATSPI_RELATION_FLOWS_TO;
258 types[ATK_RELATION_FLOWS_FROM] = ATSPI_RELATION_FLOWS_FROM;
259 types[ATK_RELATION_SUBWINDOW_OF] = ATSPI_RELATION_SUBWINDOW_OF;
260 types[ATK_RELATION_EMBEDS] = ATSPI_RELATION_EMBEDS;
261 types[ATK_RELATION_EMBEDDED_BY] = ATSPI_RELATION_EMBEDDED_BY;
262 types[ATK_RELATION_POPUP_FOR] = ATSPI_RELATION_POPUP_FOR;
263 types[ATK_RELATION_PARENT_WINDOW_OF] =
264 ATSPI_RELATION_PARENT_WINDOW_OF;
265 types[ATK_RELATION_DESCRIPTION_FOR] =
266 ATSPI_RELATION_DESCRIPTION_FOR;
267 types[ATK_RELATION_DESCRIBED_BY] = ATSPI_RELATION_DESCRIBED_BY;
268 types[ATK_RELATION_DETAILS] = ATSPI_RELATION_DETAILS;
269 types[ATK_RELATION_DETAILS_FOR] = ATSPI_RELATION_DETAILS_FOR;
270 types[ATK_RELATION_ERROR_MESSAGE] = ATSPI_RELATION_ERROR_MESSAGE;
271 types[ATK_RELATION_ERROR_FOR] = ATSPI_RELATION_ERROR_FOR;
272 types[ATK_RELATION_NODE_PARENT_OF] = ATSPI_RELATION_NODE_PARENT_OF;
277 static AtspiRelationType
278 spi_relation_type_from_atk_relation_type (AtkRelationType type)
280 static gboolean is_initialized = FALSE;
281 static AtspiRelationType
282 spi_relation_type_table[ATK_RELATION_LAST_DEFINED];
283 AtspiRelationType spi_type;
286 is_initialized = spi_init_relation_type_table (spi_relation_type_table);
288 if (type > ATK_RELATION_NULL && type < ATK_RELATION_LAST_DEFINED)
289 spi_type = spi_relation_type_table[type];
291 spi_type = ATSPI_RELATION_EXTENDED;
296 impl_GetRelationSet (DBusConnection * bus,
297 DBusMessage * message, void *user_data)
299 AtkObject *object = (AtkObject *) user_data;
302 DBusMessageIter iter, iter_array, iter_struct, iter_targets;
306 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
307 droute_not_yet_handled_error (message));
308 reply = dbus_message_new_method_return (message);
311 set = atk_object_ref_relation_set (object);
312 dbus_message_iter_init_append (reply, &iter);
313 if (!dbus_message_iter_open_container
314 (&iter, DBUS_TYPE_ARRAY, "(ua(so))", &iter_array))
320 count = atk_relation_set_get_n_relations (set);
321 for (i = 0; i < count; i++)
323 AtkRelation *r = atk_relation_set_get_relation (set, i);
329 rt = atk_relation_get_relation_type (r);
330 type = spi_relation_type_from_atk_relation_type (rt);
331 target = atk_relation_get_target (r);
332 if (!dbus_message_iter_open_container
333 (&iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct))
337 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &type);
338 if (!dbus_message_iter_open_container
339 (&iter_struct, DBUS_TYPE_ARRAY, "(so)", &iter_targets))
343 for (j = 0; j < target->len; j++)
345 AtkObject *obj = target->pdata[j];
348 spi_object_append_reference (&iter_targets, obj);
350 dbus_message_iter_close_container (&iter_struct, &iter_targets);
351 dbus_message_iter_close_container (&iter_array, &iter_struct);
353 dbus_message_iter_close_container (&iter, &iter_array);
356 g_object_unref (set);
357 // TODO: handle out of memory */
362 impl_GetRole (DBusConnection * bus, DBusMessage * message, void *user_data)
364 AtkObject *object = (AtkObject *) user_data;
369 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
370 droute_not_yet_handled_error (message));
371 role = atk_object_get_role (object);
372 rv = spi_accessible_role_from_atk_role (role);
373 reply = dbus_message_new_method_return (message);
376 dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
383 impl_GetRoleName (DBusConnection * bus,
384 DBusMessage * message, void *user_data)
386 AtkObject *object = (AtkObject *) user_data;
388 const char *role_name;
391 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
392 droute_not_yet_handled_error (message));
393 role = atk_object_get_role (object);
394 role_name = atk_role_get_name (role);
397 reply = dbus_message_new_method_return (message);
400 dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
407 impl_GetLocalizedRoleName (DBusConnection * bus,
408 DBusMessage * message, void *user_data)
410 AtkObject *object = (AtkObject *) user_data;
412 const char *role_name;
415 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
416 droute_not_yet_handled_error (message));
417 role = atk_object_get_role (object);
418 role_name = atk_role_get_localized_name (role);
421 reply = dbus_message_new_method_return (message);
424 dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
431 impl_GetState (DBusConnection * bus, DBusMessage * message, void *user_data)
433 AtkObject *object = (AtkObject *) user_data;
435 DBusMessage *reply = NULL;
436 DBusMessageIter iter, iter_array;
438 dbus_uint32_t states[2];
442 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
443 droute_not_yet_handled_error (message));
445 reply = dbus_message_new_method_return (message);
446 dbus_message_iter_init_append (reply, &iter);
448 spi_atk_state_to_dbus_array (object, states);
449 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "u", &iter_array);
450 for (count = 0; count < 2; count++)
452 dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_UINT32,
455 dbus_message_iter_close_container (&iter, &iter_array);
460 impl_GetAttributes (DBusConnection * bus,
461 DBusMessage * message, void *user_data)
463 AtkObject *object = (AtkObject *) user_data;
464 AtkAttributeSet *attributes;
465 DBusMessage *reply = NULL;
466 DBusMessageIter iter;
468 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
469 droute_not_yet_handled_error (message));
471 attributes = atk_object_get_attributes (object);
473 reply = dbus_message_new_method_return (message);
474 dbus_message_iter_init_append (reply, &iter);
475 spi_object_append_attribute_set (&iter, attributes);
477 atk_attribute_set_free (attributes);
483 impl_get_Attributes (DBusMessageIter * iter, void *user_data)
485 DBusMessageIter iter_variant;
486 AtkObject *object = (AtkObject *) user_data;
487 AtkAttributeSet *attributes;
489 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
491 attributes = atk_object_get_attributes (object);
493 dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "a{ss}", &iter_variant);
494 spi_object_append_attribute_set (&iter_variant, attributes);
495 dbus_message_iter_close_container (iter, &iter_variant);
497 atk_attribute_set_free (attributes);
503 impl_GetApplication (DBusConnection * bus,
504 DBusMessage * message, void *user_data)
506 return spi_object_return_reference (message, atk_get_root ());
510 impl_GetInterfaces (DBusConnection * bus,
511 DBusMessage * message, void *user_data)
513 AtkObject *object = (AtkObject *) user_data;
515 DBusMessageIter iter, iter_array;
517 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
518 droute_not_yet_handled_error (message));
519 reply = dbus_message_new_method_return (message);
522 dbus_message_iter_init_append (reply, &iter);
523 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s",
525 spi_object_append_interfaces (&iter_array, object);
526 dbus_message_iter_close_container (&iter, &iter_array);
532 impl_get_AccessibleId (DBusMessageIter * iter, void *user_data)
534 AtkObject *object = (AtkObject *) user_data;
536 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
538 return droute_return_v_string (iter, atk_object_get_accessible_id (object));
541 static DRouteMethod methods[] = {
542 {impl_GetChildAtIndex, "GetChildAtIndex"},
543 {impl_GetChildren, "GetChildren"},
544 {impl_GetIndexInParent, "GetIndexInParent"},
545 {impl_GetRelationSet, "GetRelationSet"},
546 {impl_GetRole, "GetRole"},
547 {impl_GetRoleName, "GetRoleName"},
548 {impl_GetLocalizedRoleName, "GetLocalizedRoleName"},
549 {impl_GetState, "GetState"},
550 {impl_GetAttributes, "GetAttributes"},
551 {impl_GetApplication, "GetApplication"},
552 {impl_GetInterfaces, "GetInterfaces"},
556 static DRouteProperty properties[] = {
557 {impl_get_Name, NULL, "Name"},
558 {impl_get_Description, NULL, "Description"},
559 {impl_get_Locale, NULL, "Locale"},
560 {impl_get_Parent, NULL, "Parent"},
561 {impl_get_ChildCount, NULL, "ChildCount"},
562 {impl_get_Attributes, NULL, "Attributes"},
563 {impl_get_AccessibleId, NULL, "AccessibleId"},
568 spi_initialize_accessible (DRoutePath * path)
570 spi_atk_add_interface (path,
571 ATSPI_DBUS_INTERFACE_ACCESSIBLE,
572 spi_org_a11y_atspi_Accessible,
573 methods, properties);