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"
33 impl_get_Name (DBusMessageIter * iter, void *user_data)
35 AtkObject *object = (AtkObject *) user_data;
37 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
39 return droute_return_v_string (iter, atk_object_get_name (object));
43 impl_set_Name (DBusMessageIter * iter, void *user_data)
45 AtkObject *object = (AtkObject *) user_data;
46 const char *name = droute_get_v_string (iter);
48 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
50 atk_object_set_name (object, name);
55 impl_get_Description (DBusMessageIter * iter, void *user_data)
57 AtkObject *object = (AtkObject *) user_data;
59 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
61 return droute_return_v_string (iter, atk_object_get_description (object));
65 impl_set_Description (DBusMessageIter * iter, void *user_data)
67 AtkObject *object = (AtkObject *) user_data;
68 const char *description = droute_get_v_string (iter);
70 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
72 atk_object_set_description (object, description);
77 impl_get_Parent (DBusMessageIter * iter, void *user_data)
79 AtkObject *obj = (AtkObject *) user_data;
81 DBusMessageIter iter_variant;
84 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
86 role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));
88 dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "(so)",
91 parent = atk_object_get_parent (obj);
94 /* TODO, move in to a 'Plug' wrapper. */
95 if (ATK_IS_PLUG (obj))
97 char *id = g_object_get_data (G_OBJECT (obj), "dbus-plug-parent");
103 bus_parent = g_strdup (id);
104 if (bus_parent && (path_parent = g_utf8_strchr (bus_parent + 1, -1, ':')))
106 DBusMessageIter iter_parent;
107 *(path_parent++) = '\0';
108 dbus_message_iter_open_container (&iter_variant, DBUS_TYPE_STRUCT, NULL,
110 dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_STRING, &bus_parent);
111 dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_OBJECT_PATH, &path_parent);
112 dbus_message_iter_close_container (&iter_variant, &iter_parent);
116 spi_object_append_null_reference (&iter_variant);
121 spi_object_append_null_reference (&iter_variant);
124 else if (role != Accessibility_ROLE_APPLICATION)
125 spi_object_append_null_reference (&iter_variant);
127 spi_object_append_desktop_reference (&iter_variant);
131 spi_object_append_reference (&iter_variant, parent);
135 dbus_message_iter_close_container (iter, &iter_variant);
140 impl_get_ChildCount (DBusMessageIter * iter, void *user_data)
142 AtkObject *object = (AtkObject *) user_data;
144 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
146 return droute_return_v_int32 (iter,
147 atk_object_get_n_accessible_children
152 impl_GetChildAtIndex (DBusConnection * bus,
153 DBusMessage * message, void *user_data)
155 AtkObject *object = (AtkObject *) user_data;
160 dbus_error_init (&error);
161 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
162 droute_not_yet_handled_error (message));
163 if (!dbus_message_get_args
164 (message, &error, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID))
166 return droute_invalid_arguments_error (message);
168 child = atk_object_ref_accessible_child (object, i);
169 return spi_object_return_reference (message, child);
173 impl_GetChildren (DBusConnection * bus,
174 DBusMessage * message, void *user_data)
176 AtkObject *object = (AtkObject *) user_data;
180 DBusMessageIter iter, iter_array;
182 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
183 droute_not_yet_handled_error (message));
184 count = atk_object_get_n_accessible_children (object);
185 reply = dbus_message_new_method_return (message);
188 dbus_message_iter_init_append (reply, &iter);
189 if (!dbus_message_iter_open_container
190 (&iter, DBUS_TYPE_ARRAY, "(so)", &iter_array))
192 for (i = 0; i < count; i++)
194 AtkObject *child = atk_object_ref_accessible_child (object, i);
195 spi_object_append_reference (&iter_array, child);
197 g_object_unref (child);
199 if (!dbus_message_iter_close_container (&iter, &iter_array))
203 // TODO: handle out-of-memory
208 impl_GetIndexInParent (DBusConnection * bus,
209 DBusMessage * message, void *user_data)
211 AtkObject *object = (AtkObject *) user_data;
215 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
216 droute_not_yet_handled_error (message));
218 rv = atk_object_get_index_in_parent (object);
219 reply = dbus_message_new_method_return (message);
220 dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv, DBUS_TYPE_INVALID);
225 spi_init_relation_type_table (Accessibility_RelationType * types)
229 for (i = 0; i < ATK_RELATION_LAST_DEFINED; i++)
230 types[i] = Accessibility_RELATION_NULL;
232 types[ATK_RELATION_CONTROLLED_BY] = Accessibility_RELATION_CONTROLLED_BY;
233 types[ATK_RELATION_CONTROLLER_FOR] = Accessibility_RELATION_CONTROLLER_FOR;
234 types[ATK_RELATION_LABEL_FOR] = Accessibility_RELATION_LABEL_FOR;
235 types[ATK_RELATION_LABELLED_BY] = Accessibility_RELATION_LABELLED_BY;
236 types[ATK_RELATION_MEMBER_OF] = Accessibility_RELATION_MEMBER_OF;
237 types[ATK_RELATION_NODE_CHILD_OF] = Accessibility_RELATION_NODE_CHILD_OF;
238 types[ATK_RELATION_FLOWS_TO] = Accessibility_RELATION_FLOWS_TO;
239 types[ATK_RELATION_FLOWS_FROM] = Accessibility_RELATION_FLOWS_FROM;
240 types[ATK_RELATION_SUBWINDOW_OF] = Accessibility_RELATION_SUBWINDOW_OF;
241 types[ATK_RELATION_EMBEDS] = Accessibility_RELATION_EMBEDS;
242 types[ATK_RELATION_EMBEDDED_BY] = Accessibility_RELATION_EMBEDDED_BY;
243 types[ATK_RELATION_POPUP_FOR] = Accessibility_RELATION_POPUP_FOR;
244 types[ATK_RELATION_PARENT_WINDOW_OF] =
245 Accessibility_RELATION_PARENT_WINDOW_OF;
246 types[ATK_RELATION_DESCRIPTION_FOR] =
247 Accessibility_RELATION_DESCRIPTION_FOR;
248 types[ATK_RELATION_DESCRIBED_BY] = Accessibility_RELATION_DESCRIBED_BY;
253 static Accessibility_RelationType
254 spi_relation_type_from_atk_relation_type (AtkRelationType type)
256 static gboolean is_initialized = FALSE;
257 static Accessibility_RelationType
258 spi_relation_type_table[ATK_RELATION_LAST_DEFINED];
259 Accessibility_RelationType spi_type;
262 is_initialized = spi_init_relation_type_table (spi_relation_type_table);
264 if (type > ATK_RELATION_NULL && type < ATK_RELATION_LAST_DEFINED)
265 spi_type = spi_relation_type_table[type];
267 spi_type = Accessibility_RELATION_EXTENDED;
272 impl_GetRelationSet (DBusConnection * bus,
273 DBusMessage * message, void *user_data)
275 AtkObject *object = (AtkObject *) user_data;
278 DBusMessageIter iter, iter_array, iter_struct, iter_targets;
282 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
283 droute_not_yet_handled_error (message));
284 reply = dbus_message_new_method_return (message);
287 set = atk_object_ref_relation_set (object);
288 dbus_message_iter_init_append (reply, &iter);
289 if (!dbus_message_iter_open_container
290 (&iter, DBUS_TYPE_ARRAY, "(ua(so))", &iter_array))
294 count = atk_relation_set_get_n_relations (set);
295 for (i = 0; i < count; i++)
297 AtkRelation *r = atk_relation_set_get_relation (set, i);
303 rt = atk_relation_get_relation_type (r);
304 type = spi_relation_type_from_atk_relation_type (rt);
305 target = atk_relation_get_target (r);
306 if (!dbus_message_iter_open_container
307 (&iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct))
311 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &type);
312 if (!dbus_message_iter_open_container
313 (&iter_struct, DBUS_TYPE_ARRAY, "(so)", &iter_targets))
317 for (j = 0; j < target->len; j++)
319 AtkObject *obj = target->pdata[j];
323 spi_object_append_reference (&iter_targets, obj);
325 dbus_message_iter_close_container (&iter_struct, &iter_targets);
326 dbus_message_iter_close_container (&iter_array, &iter_struct);
328 dbus_message_iter_close_container (&iter, &iter_array);
330 // TODO: handle out of memory */
335 impl_GetRole (DBusConnection * bus, DBusMessage * message, void *user_data)
337 AtkObject *object = (AtkObject *) user_data;
342 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
343 droute_not_yet_handled_error (message));
344 role = atk_object_get_role (object);
345 rv = spi_accessible_role_from_atk_role (role);
346 reply = dbus_message_new_method_return (message);
349 dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
356 impl_get_role_str (void *datum)
358 g_return_val_if_fail (ATK_IS_OBJECT (datum), g_strdup (""));
359 return g_strdup_printf ("%d",
360 spi_accessible_role_from_atk_role
361 (atk_object_get_role ((AtkObject *) datum)));
365 impl_GetRoleName (DBusConnection * bus,
366 DBusMessage * message, void *user_data)
368 AtkObject *object = (AtkObject *) user_data;
370 const char *role_name;
373 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
374 droute_not_yet_handled_error (message));
375 role = atk_object_get_role (object);
376 role_name = atk_role_get_name (role);
379 reply = dbus_message_new_method_return (message);
382 dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
389 impl_GetLocalizedRoleName (DBusConnection * bus,
390 DBusMessage * message, void *user_data)
392 AtkObject *object = (AtkObject *) user_data;
394 const char *role_name;
397 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
398 droute_not_yet_handled_error (message));
399 role = atk_object_get_role (object);
400 role_name = atk_role_get_localized_name (role);
403 reply = dbus_message_new_method_return (message);
406 dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
413 impl_GetState (DBusConnection * bus, DBusMessage * message, void *user_data)
415 AtkObject *object = (AtkObject *) user_data;
417 DBusMessage *reply = NULL;
418 DBusMessageIter iter, iter_array;
420 dbus_uint32_t states[2];
424 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
425 droute_not_yet_handled_error (message));
427 reply = dbus_message_new_method_return (message);
428 dbus_message_iter_init_append (reply, &iter);
430 spi_atk_state_to_dbus_array (object, states);
431 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "u", &iter_array);
432 for (count = 0; count < 2; count++)
434 dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_UINT32,
437 dbus_message_iter_close_container (&iter, &iter_array);
442 impl_GetAttributes (DBusConnection * bus,
443 DBusMessage * message, void *user_data)
445 AtkObject *object = (AtkObject *) user_data;
446 AtkAttributeSet *attributes;
447 DBusMessage *reply = NULL;
448 DBusMessageIter iter;
450 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
451 droute_not_yet_handled_error (message));
453 attributes = atk_object_get_attributes (object);
455 reply = dbus_message_new_method_return (message);
456 dbus_message_iter_init_append (reply, &iter);
457 spi_object_append_attribute_set (&iter, attributes);
459 atk_attribute_set_free (attributes);
465 impl_GetApplication (DBusConnection * bus,
466 DBusMessage * message, void *user_data)
468 AtkObject *root = g_object_ref (atk_get_root ());
469 return spi_object_return_reference (message, root);
473 impl_GetInterfaces (DBusConnection * bus,
474 DBusMessage * message, void *user_data)
476 AtkObject *object = (AtkObject *) user_data;
478 const char *role_name;
480 DBusMessageIter iter, iter_array;
482 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
483 droute_not_yet_handled_error (message));
484 reply = dbus_message_new_method_return (message);
487 dbus_message_iter_init_append (reply, &iter);
488 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s",
490 spi_object_append_interfaces (&iter_array, object);
491 dbus_message_iter_close_container (&iter, &iter_array);
497 impl_Embedded (DBusConnection *bus,
498 DBusMessage *message,
501 AtkObject *object = (AtkObject *) user_data;
505 if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID))
507 return droute_invalid_arguments_error (message);
509 id = g_object_get_data (G_OBJECT (object), "dbus-plug-parent");
512 id = g_strconcat (dbus_message_get_sender (message), ":", path, NULL);
513 g_object_set_data (G_OBJECT (object), "dbus-plug-parent", id);
514 return dbus_message_new_method_return (message);
517 static DRouteMethod methods[] = {
518 {impl_GetChildAtIndex, "GetChildAtIndex"},
519 {impl_GetChildren, "GetChildren"},
520 {impl_GetIndexInParent, "GetIndexInParent"},
521 {impl_GetRelationSet, "GetRelationSet"},
522 {impl_GetRole, "GetRole"},
523 {impl_GetRoleName, "GetRoleName"},
524 {impl_GetLocalizedRoleName, "GetLocalizedRoleName"},
525 {impl_GetState, "GetState"},
526 {impl_GetAttributes, "GetAttributes"},
527 {impl_GetApplication, "GetApplication"},
528 {impl_GetInterfaces, "GetInterfaces"},
529 {impl_Embedded, "Embedded"},
533 static DRouteProperty properties[] = {
534 {impl_get_Name, impl_set_Name, "Name"},
535 {impl_get_Description, impl_set_Description, "Description"},
536 {impl_get_Parent, NULL, "Parent"},
537 {impl_get_ChildCount, NULL, "ChildCount"},
542 spi_initialize_accessible (DRoutePath * path)
544 droute_path_add_interface (path,
545 SPI_DBUS_INTERFACE_ACCESSIBLE,
546 methods, properties);