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 #ifdef SPI_ATK_PLUG_SOCKET
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 else if (role != Accessibility_ROLE_APPLICATION)
119 if (role != Accessibility_ROLE_APPLICATION)
121 spi_object_append_null_reference (&iter_variant);
123 spi_object_append_desktop_reference (&iter_variant);
127 spi_object_append_reference (&iter_variant, parent);
131 dbus_message_iter_close_container (iter, &iter_variant);
136 impl_get_ChildCount (DBusMessageIter * iter, void *user_data)
138 AtkObject *object = (AtkObject *) user_data;
140 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
142 return droute_return_v_int32 (iter,
143 atk_object_get_n_accessible_children
148 impl_GetChildAtIndex (DBusConnection * bus,
149 DBusMessage * message, void *user_data)
151 AtkObject *object = (AtkObject *) user_data;
156 dbus_error_init (&error);
157 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
158 droute_not_yet_handled_error (message));
159 if (!dbus_message_get_args
160 (message, &error, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID))
162 return droute_invalid_arguments_error (message);
164 child = atk_object_ref_accessible_child (object, i);
165 return spi_object_return_reference (message, child);
169 impl_GetChildren (DBusConnection * bus,
170 DBusMessage * message, void *user_data)
172 AtkObject *object = (AtkObject *) user_data;
176 DBusMessageIter iter, iter_array;
178 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
179 droute_not_yet_handled_error (message));
180 count = atk_object_get_n_accessible_children (object);
181 reply = dbus_message_new_method_return (message);
184 dbus_message_iter_init_append (reply, &iter);
185 if (!dbus_message_iter_open_container
186 (&iter, DBUS_TYPE_ARRAY, "(so)", &iter_array))
188 for (i = 0; i < count; i++)
190 AtkObject *child = atk_object_ref_accessible_child (object, i);
191 spi_object_append_reference (&iter_array, child);
193 g_object_unref (child);
195 if (!dbus_message_iter_close_container (&iter, &iter_array))
199 // TODO: handle out-of-memory
204 impl_GetIndexInParent (DBusConnection * bus,
205 DBusMessage * message, void *user_data)
207 AtkObject *object = (AtkObject *) user_data;
211 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
212 droute_not_yet_handled_error (message));
214 rv = atk_object_get_index_in_parent (object);
215 reply = dbus_message_new_method_return (message);
216 dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv, DBUS_TYPE_INVALID);
221 spi_init_relation_type_table (Accessibility_RelationType * types)
225 for (i = 0; i < ATK_RELATION_LAST_DEFINED; i++)
226 types[i] = Accessibility_RELATION_NULL;
228 types[ATK_RELATION_CONTROLLED_BY] = Accessibility_RELATION_CONTROLLED_BY;
229 types[ATK_RELATION_CONTROLLER_FOR] = Accessibility_RELATION_CONTROLLER_FOR;
230 types[ATK_RELATION_LABEL_FOR] = Accessibility_RELATION_LABEL_FOR;
231 types[ATK_RELATION_LABELLED_BY] = Accessibility_RELATION_LABELLED_BY;
232 types[ATK_RELATION_MEMBER_OF] = Accessibility_RELATION_MEMBER_OF;
233 types[ATK_RELATION_NODE_CHILD_OF] = Accessibility_RELATION_NODE_CHILD_OF;
234 types[ATK_RELATION_FLOWS_TO] = Accessibility_RELATION_FLOWS_TO;
235 types[ATK_RELATION_FLOWS_FROM] = Accessibility_RELATION_FLOWS_FROM;
236 types[ATK_RELATION_SUBWINDOW_OF] = Accessibility_RELATION_SUBWINDOW_OF;
237 types[ATK_RELATION_EMBEDS] = Accessibility_RELATION_EMBEDS;
238 types[ATK_RELATION_EMBEDDED_BY] = Accessibility_RELATION_EMBEDDED_BY;
239 types[ATK_RELATION_POPUP_FOR] = Accessibility_RELATION_POPUP_FOR;
240 types[ATK_RELATION_PARENT_WINDOW_OF] =
241 Accessibility_RELATION_PARENT_WINDOW_OF;
242 types[ATK_RELATION_DESCRIPTION_FOR] =
243 Accessibility_RELATION_DESCRIPTION_FOR;
244 types[ATK_RELATION_DESCRIBED_BY] = Accessibility_RELATION_DESCRIBED_BY;
249 static Accessibility_RelationType
250 spi_relation_type_from_atk_relation_type (AtkRelationType type)
252 static gboolean is_initialized = FALSE;
253 static Accessibility_RelationType
254 spi_relation_type_table[ATK_RELATION_LAST_DEFINED];
255 Accessibility_RelationType spi_type;
258 is_initialized = spi_init_relation_type_table (spi_relation_type_table);
260 if (type > ATK_RELATION_NULL && type < ATK_RELATION_LAST_DEFINED)
261 spi_type = spi_relation_type_table[type];
263 spi_type = Accessibility_RELATION_EXTENDED;
268 impl_GetRelationSet (DBusConnection * bus,
269 DBusMessage * message, void *user_data)
271 AtkObject *object = (AtkObject *) user_data;
274 DBusMessageIter iter, iter_array, iter_struct, iter_targets;
278 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
279 droute_not_yet_handled_error (message));
280 reply = dbus_message_new_method_return (message);
283 set = atk_object_ref_relation_set (object);
284 dbus_message_iter_init_append (reply, &iter);
285 if (!dbus_message_iter_open_container
286 (&iter, DBUS_TYPE_ARRAY, "(ua(so))", &iter_array))
290 count = atk_relation_set_get_n_relations (set);
291 for (i = 0; i < count; i++)
293 AtkRelation *r = atk_relation_set_get_relation (set, i);
299 rt = atk_relation_get_relation_type (r);
300 type = spi_relation_type_from_atk_relation_type (rt);
301 target = atk_relation_get_target (r);
302 if (!dbus_message_iter_open_container
303 (&iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct))
307 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &type);
308 if (!dbus_message_iter_open_container
309 (&iter_struct, DBUS_TYPE_ARRAY, "(so)", &iter_targets))
313 for (j = 0; j < target->len; j++)
315 AtkObject *obj = target->pdata[j];
319 spi_object_append_reference (&iter_targets, obj);
321 dbus_message_iter_close_container (&iter_struct, &iter_targets);
322 dbus_message_iter_close_container (&iter_array, &iter_struct);
324 dbus_message_iter_close_container (&iter, &iter_array);
326 // TODO: handle out of memory */
331 impl_GetRole (DBusConnection * bus, DBusMessage * message, void *user_data)
333 AtkObject *object = (AtkObject *) user_data;
338 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
339 droute_not_yet_handled_error (message));
340 role = atk_object_get_role (object);
341 rv = spi_accessible_role_from_atk_role (role);
342 reply = dbus_message_new_method_return (message);
345 dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
352 impl_get_role_str (void *datum)
354 g_return_val_if_fail (ATK_IS_OBJECT (datum), g_strdup (""));
355 return g_strdup_printf ("%d",
356 spi_accessible_role_from_atk_role
357 (atk_object_get_role ((AtkObject *) datum)));
361 impl_GetRoleName (DBusConnection * bus,
362 DBusMessage * message, void *user_data)
364 AtkObject *object = (AtkObject *) user_data;
366 const char *role_name;
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 role_name = atk_role_get_name (role);
375 reply = dbus_message_new_method_return (message);
378 dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
385 impl_GetLocalizedRoleName (DBusConnection * bus,
386 DBusMessage * message, void *user_data)
388 AtkObject *object = (AtkObject *) user_data;
390 const char *role_name;
393 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
394 droute_not_yet_handled_error (message));
395 role = atk_object_get_role (object);
396 role_name = atk_role_get_localized_name (role);
399 reply = dbus_message_new_method_return (message);
402 dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
409 impl_GetState (DBusConnection * bus, DBusMessage * message, void *user_data)
411 AtkObject *object = (AtkObject *) user_data;
413 DBusMessage *reply = NULL;
414 DBusMessageIter iter, iter_array;
416 dbus_uint32_t states[2];
420 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
421 droute_not_yet_handled_error (message));
423 reply = dbus_message_new_method_return (message);
424 dbus_message_iter_init_append (reply, &iter);
426 spi_atk_state_to_dbus_array (object, states);
427 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "u", &iter_array);
428 for (count = 0; count < 2; count++)
430 dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_UINT32,
433 dbus_message_iter_close_container (&iter, &iter_array);
438 impl_GetAttributes (DBusConnection * bus,
439 DBusMessage * message, void *user_data)
441 AtkObject *object = (AtkObject *) user_data;
442 AtkAttributeSet *attributes;
443 DBusMessage *reply = NULL;
444 DBusMessageIter iter;
446 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
447 droute_not_yet_handled_error (message));
449 attributes = atk_object_get_attributes (object);
451 reply = dbus_message_new_method_return (message);
452 dbus_message_iter_init_append (reply, &iter);
453 spi_object_append_attribute_set (&iter, attributes);
455 atk_attribute_set_free (attributes);
461 impl_GetApplication (DBusConnection * bus,
462 DBusMessage * message, void *user_data)
464 AtkObject *root = g_object_ref (atk_get_root ());
465 return spi_object_return_reference (message, root);
469 impl_GetInterfaces (DBusConnection * bus,
470 DBusMessage * message, void *user_data)
472 AtkObject *object = (AtkObject *) user_data;
474 const char *role_name;
476 DBusMessageIter iter, iter_array;
478 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
479 droute_not_yet_handled_error (message));
480 reply = dbus_message_new_method_return (message);
483 dbus_message_iter_init_append (reply, &iter);
484 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s",
486 spi_object_append_interfaces (&iter_array, object);
487 dbus_message_iter_close_container (&iter, &iter_array);
493 impl_Embedded (DBusConnection *bus,
494 DBusMessage *message,
497 AtkObject *object = (AtkObject *) user_data;
501 if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID))
503 return droute_invalid_arguments_error (message);
505 id = g_object_get_data (G_OBJECT (object), "dbus-plug-parent");
508 id = g_strconcat (dbus_message_get_sender (message), ":", path, NULL);
509 g_object_set_data (G_OBJECT (object), "dbus-plug-parent", id);
510 return dbus_message_new_method_return (message);
513 static DRouteMethod methods[] = {
514 {impl_GetChildAtIndex, "GetChildAtIndex"},
515 {impl_GetChildren, "GetChildren"},
516 {impl_GetIndexInParent, "GetIndexInParent"},
517 {impl_GetRelationSet, "GetRelationSet"},
518 {impl_GetRole, "GetRole"},
519 {impl_GetRoleName, "GetRoleName"},
520 {impl_GetLocalizedRoleName, "GetLocalizedRoleName"},
521 {impl_GetState, "GetState"},
522 {impl_GetAttributes, "GetAttributes"},
523 {impl_GetApplication, "GetApplication"},
524 {impl_GetInterfaces, "GetInterfaces"},
525 {impl_Embedded, "Embedded"},
529 static DRouteProperty properties[] = {
530 {impl_get_Name, impl_set_Name, "Name"},
531 {impl_get_Description, impl_set_Description, "Description"},
532 {impl_get_Parent, NULL, "Parent"},
533 {impl_get_ChildCount, NULL, "ChildCount"},
538 spi_initialize_accessible (DRoutePath * path)
540 droute_path_add_interface (path,
541 SPI_DBUS_INTERFACE_ACCESSIBLE,
542 methods, properties);