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>
28 #include "common/spi-dbus.h"
29 #include "common/spi-stateset.h"
31 #include "introspection.h"
34 impl_get_Name (DBusMessageIter * iter, void *user_data)
36 AtkObject *object = (AtkObject *) user_data;
38 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
40 return droute_return_v_string (iter, atk_object_get_name (object));
44 impl_set_Name (DBusMessageIter * iter, void *user_data)
46 AtkObject *object = (AtkObject *) user_data;
47 const char *name = droute_get_v_string (iter);
49 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
51 atk_object_set_name (object, name);
56 impl_get_Description (DBusMessageIter * iter, void *user_data)
58 AtkObject *object = (AtkObject *) user_data;
60 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
62 return droute_return_v_string (iter, atk_object_get_description (object));
66 impl_set_Description (DBusMessageIter * iter, void *user_data)
68 AtkObject *object = (AtkObject *) user_data;
69 const char *description = droute_get_v_string (iter);
71 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
73 atk_object_set_description (object, description);
78 impl_get_Parent (DBusMessageIter * iter, void *user_data)
80 AtkObject *obj = (AtkObject *) user_data;
82 DBusMessageIter iter_variant;
85 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
87 role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));
89 dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "(so)",
92 parent = atk_object_get_parent (obj);
95 /* TODO, move in to a 'Plug' wrapper. */
96 if (ATK_IS_PLUG (obj))
98 char *id = g_object_get_data (G_OBJECT (obj), "dbus-plug-parent");
104 bus_parent = g_strdup (id);
105 if (bus_parent && (path_parent = g_utf8_strchr (bus_parent + 1, -1, ':')))
107 DBusMessageIter iter_parent;
108 *(path_parent++) = '\0';
109 dbus_message_iter_open_container (&iter_variant, DBUS_TYPE_STRUCT, NULL,
111 dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_STRING, &bus_parent);
112 dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_OBJECT_PATH, &path_parent);
113 dbus_message_iter_close_container (&iter_variant, &iter_parent);
117 spi_object_append_null_reference (&iter_variant);
122 spi_object_append_null_reference (&iter_variant);
125 else if (role != Accessibility_ROLE_APPLICATION)
126 spi_object_append_null_reference (&iter_variant);
128 spi_object_append_desktop_reference (&iter_variant);
132 spi_object_append_reference (&iter_variant, parent);
136 dbus_message_iter_close_container (iter, &iter_variant);
141 impl_get_ChildCount (DBusMessageIter * iter, void *user_data)
143 AtkObject *object = (AtkObject *) user_data;
145 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
147 return droute_return_v_int32 (iter,
148 atk_object_get_n_accessible_children
153 impl_GetChildAtIndex (DBusConnection * bus,
154 DBusMessage * message, void *user_data)
156 AtkObject *object = (AtkObject *) user_data;
161 dbus_error_init (&error);
162 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
163 droute_not_yet_handled_error (message));
164 if (!dbus_message_get_args
165 (message, &error, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID))
167 return droute_invalid_arguments_error (message);
169 child = atk_object_ref_accessible_child (object, i);
170 return spi_object_return_reference (message, child);
174 impl_GetChildren (DBusConnection * bus,
175 DBusMessage * message, void *user_data)
177 AtkObject *object = (AtkObject *) user_data;
181 DBusMessageIter iter, iter_array;
183 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
184 droute_not_yet_handled_error (message));
185 count = atk_object_get_n_accessible_children (object);
186 reply = dbus_message_new_method_return (message);
189 dbus_message_iter_init_append (reply, &iter);
190 if (!dbus_message_iter_open_container
191 (&iter, DBUS_TYPE_ARRAY, "(so)", &iter_array))
193 for (i = 0; i < count; i++)
195 AtkObject *child = atk_object_ref_accessible_child (object, i);
196 spi_object_append_reference (&iter_array, child);
198 g_object_unref (child);
200 if (!dbus_message_iter_close_container (&iter, &iter_array))
204 // TODO: handle out-of-memory
209 impl_GetIndexInParent (DBusConnection * bus,
210 DBusMessage * message, void *user_data)
212 AtkObject *object = (AtkObject *) user_data;
216 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
217 droute_not_yet_handled_error (message));
219 rv = atk_object_get_index_in_parent (object);
220 reply = dbus_message_new_method_return (message);
221 dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv, DBUS_TYPE_INVALID);
226 spi_init_relation_type_table (Accessibility_RelationType * types)
230 for (i = 0; i < ATK_RELATION_LAST_DEFINED; i++)
231 types[i] = Accessibility_RELATION_NULL;
233 types[ATK_RELATION_CONTROLLED_BY] = Accessibility_RELATION_CONTROLLED_BY;
234 types[ATK_RELATION_CONTROLLER_FOR] = Accessibility_RELATION_CONTROLLER_FOR;
235 types[ATK_RELATION_LABEL_FOR] = Accessibility_RELATION_LABEL_FOR;
236 types[ATK_RELATION_LABELLED_BY] = Accessibility_RELATION_LABELLED_BY;
237 types[ATK_RELATION_MEMBER_OF] = Accessibility_RELATION_MEMBER_OF;
238 types[ATK_RELATION_NODE_CHILD_OF] = Accessibility_RELATION_NODE_CHILD_OF;
239 types[ATK_RELATION_FLOWS_TO] = Accessibility_RELATION_FLOWS_TO;
240 types[ATK_RELATION_FLOWS_FROM] = Accessibility_RELATION_FLOWS_FROM;
241 types[ATK_RELATION_SUBWINDOW_OF] = Accessibility_RELATION_SUBWINDOW_OF;
242 types[ATK_RELATION_EMBEDS] = Accessibility_RELATION_EMBEDS;
243 types[ATK_RELATION_EMBEDDED_BY] = Accessibility_RELATION_EMBEDDED_BY;
244 types[ATK_RELATION_POPUP_FOR] = Accessibility_RELATION_POPUP_FOR;
245 types[ATK_RELATION_PARENT_WINDOW_OF] =
246 Accessibility_RELATION_PARENT_WINDOW_OF;
247 types[ATK_RELATION_DESCRIPTION_FOR] =
248 Accessibility_RELATION_DESCRIPTION_FOR;
249 types[ATK_RELATION_DESCRIBED_BY] = Accessibility_RELATION_DESCRIBED_BY;
254 static Accessibility_RelationType
255 spi_relation_type_from_atk_relation_type (AtkRelationType type)
257 static gboolean is_initialized = FALSE;
258 static Accessibility_RelationType
259 spi_relation_type_table[ATK_RELATION_LAST_DEFINED];
260 Accessibility_RelationType spi_type;
263 is_initialized = spi_init_relation_type_table (spi_relation_type_table);
265 if (type > ATK_RELATION_NULL && type < ATK_RELATION_LAST_DEFINED)
266 spi_type = spi_relation_type_table[type];
268 spi_type = Accessibility_RELATION_EXTENDED;
273 impl_GetRelationSet (DBusConnection * bus,
274 DBusMessage * message, void *user_data)
276 AtkObject *object = (AtkObject *) user_data;
279 DBusMessageIter iter, iter_array, iter_struct, iter_targets;
283 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
284 droute_not_yet_handled_error (message));
285 reply = dbus_message_new_method_return (message);
288 set = atk_object_ref_relation_set (object);
289 dbus_message_iter_init_append (reply, &iter);
290 if (!dbus_message_iter_open_container
291 (&iter, DBUS_TYPE_ARRAY, "(ua(so))", &iter_array))
297 count = atk_relation_set_get_n_relations (set);
298 for (i = 0; i < count; i++)
300 AtkRelation *r = atk_relation_set_get_relation (set, i);
306 rt = atk_relation_get_relation_type (r);
307 type = spi_relation_type_from_atk_relation_type (rt);
308 target = atk_relation_get_target (r);
309 if (!dbus_message_iter_open_container
310 (&iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct))
314 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &type);
315 if (!dbus_message_iter_open_container
316 (&iter_struct, DBUS_TYPE_ARRAY, "(so)", &iter_targets))
320 for (j = 0; j < target->len; j++)
322 AtkObject *obj = target->pdata[j];
326 spi_object_append_reference (&iter_targets, obj);
328 dbus_message_iter_close_container (&iter_struct, &iter_targets);
329 dbus_message_iter_close_container (&iter_array, &iter_struct);
331 dbus_message_iter_close_container (&iter, &iter_array);
333 // TODO: handle out of memory */
338 impl_GetRole (DBusConnection * bus, DBusMessage * message, void *user_data)
340 AtkObject *object = (AtkObject *) user_data;
345 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
346 droute_not_yet_handled_error (message));
347 role = atk_object_get_role (object);
348 rv = spi_accessible_role_from_atk_role (role);
349 reply = dbus_message_new_method_return (message);
352 dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
359 impl_get_role_str (void *datum)
361 g_return_val_if_fail (ATK_IS_OBJECT (datum), g_strdup (""));
362 return g_strdup_printf ("%d",
363 spi_accessible_role_from_atk_role
364 (atk_object_get_role ((AtkObject *) datum)));
368 impl_GetRoleName (DBusConnection * bus,
369 DBusMessage * message, void *user_data)
371 AtkObject *object = (AtkObject *) user_data;
373 const char *role_name;
376 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
377 droute_not_yet_handled_error (message));
378 role = atk_object_get_role (object);
379 role_name = atk_role_get_name (role);
382 reply = dbus_message_new_method_return (message);
385 dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
392 impl_GetLocalizedRoleName (DBusConnection * bus,
393 DBusMessage * message, void *user_data)
395 AtkObject *object = (AtkObject *) user_data;
397 const char *role_name;
400 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
401 droute_not_yet_handled_error (message));
402 role = atk_object_get_role (object);
403 role_name = atk_role_get_localized_name (role);
406 reply = dbus_message_new_method_return (message);
409 dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
416 impl_GetState (DBusConnection * bus, DBusMessage * message, void *user_data)
418 AtkObject *object = (AtkObject *) user_data;
420 DBusMessage *reply = NULL;
421 DBusMessageIter iter, iter_array;
423 dbus_uint32_t states[2];
427 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
428 droute_not_yet_handled_error (message));
430 reply = dbus_message_new_method_return (message);
431 dbus_message_iter_init_append (reply, &iter);
433 spi_atk_state_to_dbus_array (object, states);
434 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "u", &iter_array);
435 for (count = 0; count < 2; count++)
437 dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_UINT32,
440 dbus_message_iter_close_container (&iter, &iter_array);
445 impl_GetAttributes (DBusConnection * bus,
446 DBusMessage * message, void *user_data)
448 AtkObject *object = (AtkObject *) user_data;
449 AtkAttributeSet *attributes;
450 DBusMessage *reply = NULL;
451 DBusMessageIter iter;
453 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
454 droute_not_yet_handled_error (message));
456 attributes = atk_object_get_attributes (object);
458 reply = dbus_message_new_method_return (message);
459 dbus_message_iter_init_append (reply, &iter);
460 spi_object_append_attribute_set (&iter, attributes);
462 atk_attribute_set_free (attributes);
468 impl_GetApplication (DBusConnection * bus,
469 DBusMessage * message, void *user_data)
471 AtkObject *root = g_object_ref (atk_get_root ());
472 return spi_object_return_reference (message, root);
476 impl_GetInterfaces (DBusConnection * bus,
477 DBusMessage * message, void *user_data)
479 AtkObject *object = (AtkObject *) user_data;
481 const char *role_name;
483 DBusMessageIter iter, iter_array;
485 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
486 droute_not_yet_handled_error (message));
487 reply = dbus_message_new_method_return (message);
490 dbus_message_iter_init_append (reply, &iter);
491 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s",
493 spi_object_append_interfaces (&iter_array, object);
494 dbus_message_iter_close_container (&iter, &iter_array);
500 impl_Embedded (DBusConnection *bus,
501 DBusMessage *message,
504 AtkObject *object = (AtkObject *) user_data;
508 if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID))
510 return droute_invalid_arguments_error (message);
512 id = g_object_get_data (G_OBJECT (object), "dbus-plug-parent");
515 id = g_strconcat (dbus_message_get_sender (message), ":", path, NULL);
516 g_object_set_data (G_OBJECT (object), "dbus-plug-parent", id);
517 return dbus_message_new_method_return (message);
520 static DRouteMethod methods[] = {
521 {impl_GetChildAtIndex, "GetChildAtIndex"},
522 {impl_GetChildren, "GetChildren"},
523 {impl_GetIndexInParent, "GetIndexInParent"},
524 {impl_GetRelationSet, "GetRelationSet"},
525 {impl_GetRole, "GetRole"},
526 {impl_GetRoleName, "GetRoleName"},
527 {impl_GetLocalizedRoleName, "GetLocalizedRoleName"},
528 {impl_GetState, "GetState"},
529 {impl_GetAttributes, "GetAttributes"},
530 {impl_GetApplication, "GetApplication"},
531 {impl_GetInterfaces, "GetInterfaces"},
532 {impl_Embedded, "Embedded"},
536 static DRouteProperty properties[] = {
537 {impl_get_Name, impl_set_Name, "Name"},
538 {impl_get_Description, impl_set_Description, "Description"},
539 {impl_get_Parent, NULL, "Parent"},
540 {impl_get_ChildCount, NULL, "ChildCount"},
545 spi_initialize_accessible (DRoutePath * path)
547 droute_path_add_interface (path,
548 SPI_DBUS_INTERFACE_ACCESSIBLE,
549 spi_org_a11y_atspi_Accessible,
550 methods, properties);