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 "atspi/atspi.h"
30 #include "accessible-stateset.h"
32 #include "introspection.h"
35 impl_get_Name (DBusMessageIter * iter, void *user_data)
37 AtkObject *object = (AtkObject *) user_data;
39 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
41 return droute_return_v_string (iter, atk_object_get_name (object));
45 impl_get_Description (DBusMessageIter * iter, void *user_data)
47 AtkObject *object = (AtkObject *) user_data;
49 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
51 return droute_return_v_string (iter, atk_object_get_description (object));
55 impl_get_Parent (DBusMessageIter * iter, void *user_data)
57 AtkObject *obj = (AtkObject *) user_data;
59 DBusMessageIter iter_variant;
62 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
64 role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));
66 dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "(so)",
69 parent = atk_object_get_parent (obj);
72 /* TODO, move in to a 'Plug' wrapper. */
73 if (ATK_IS_PLUG (obj))
75 char *id = g_object_get_data (G_OBJECT (obj), "dbus-plug-parent");
81 bus_parent = g_strdup (id);
82 if (bus_parent && (path_parent = g_utf8_strchr (bus_parent + 1, -1, ':')))
84 DBusMessageIter iter_parent;
85 *(path_parent++) = '\0';
86 dbus_message_iter_open_container (&iter_variant, DBUS_TYPE_STRUCT, NULL,
88 dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_STRING, &bus_parent);
89 dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_OBJECT_PATH, &path_parent);
90 dbus_message_iter_close_container (&iter_variant, &iter_parent);
94 spi_object_append_null_reference (&iter_variant);
99 spi_object_append_null_reference (&iter_variant);
102 else if (role != ATSPI_ROLE_APPLICATION)
103 spi_object_append_null_reference (&iter_variant);
105 spi_object_append_desktop_reference (&iter_variant);
109 spi_object_append_reference (&iter_variant, parent);
113 dbus_message_iter_close_container (iter, &iter_variant);
118 impl_get_ChildCount (DBusMessageIter * iter, void *user_data)
120 AtkObject *object = (AtkObject *) user_data;
123 g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
125 childCount = (ATK_IS_SOCKET (object) && atk_socket_is_occupied (ATK_SOCKET (object)))
127 : atk_object_get_n_accessible_children (object);
128 return droute_return_v_int32 (iter, childCount);
132 impl_GetChildAtIndex (DBusConnection * bus,
133 DBusMessage * message, void *user_data)
135 AtkObject *object = (AtkObject *) user_data;
141 dbus_error_init (&error);
142 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
143 droute_not_yet_handled_error (message));
144 if (!dbus_message_get_args
145 (message, &error, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID))
147 return droute_invalid_arguments_error (message);
150 if (ATK_IS_SOCKET (object) && atk_socket_is_occupied (ATK_SOCKET (object)) && i == 0)
152 AtkSocket *socket = ATK_SOCKET (object);
153 gchar *child_name, *child_path;
154 child_name = g_strdup (socket->embedded_plug_id);
155 child_path = g_utf8_strchr (child_name + 1, -1, ':');
158 DBusMessageIter iter, iter_socket;
159 *(child_path++) = '\0';
160 reply = dbus_message_new_method_return (message);
163 dbus_message_iter_init_append (reply, &iter);
164 dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL,
166 dbus_message_iter_append_basic (&iter_socket, DBUS_TYPE_STRING, &child_name);
167 dbus_message_iter_append_basic (&iter_socket, DBUS_TYPE_OBJECT_PATH, &child_path);
168 dbus_message_iter_close_container (&iter, &iter_socket);
173 child = atk_object_ref_accessible_child (object, i);
174 reply = spi_object_return_reference (message, child);
175 g_object_unref (child);
181 impl_GetChildren (DBusConnection * bus,
182 DBusMessage * message, void *user_data)
184 AtkObject *object = (AtkObject *) user_data;
188 DBusMessageIter iter, iter_array;
190 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
191 droute_not_yet_handled_error (message));
192 count = atk_object_get_n_accessible_children (object);
193 reply = dbus_message_new_method_return (message);
196 dbus_message_iter_init_append (reply, &iter);
197 if (!dbus_message_iter_open_container
198 (&iter, DBUS_TYPE_ARRAY, "(so)", &iter_array))
200 for (i = 0; i < count; i++)
202 AtkObject *child = atk_object_ref_accessible_child (object, i);
203 spi_object_append_reference (&iter_array, child);
205 g_object_unref (child);
207 if (!dbus_message_iter_close_container (&iter, &iter_array))
211 // TODO: handle out-of-memory
216 impl_GetIndexInParent (DBusConnection * bus,
217 DBusMessage * message, void *user_data)
219 AtkObject *object = (AtkObject *) user_data;
223 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
224 droute_not_yet_handled_error (message));
226 rv = atk_object_get_index_in_parent (object);
227 reply = dbus_message_new_method_return (message);
228 dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv, DBUS_TYPE_INVALID);
233 spi_init_relation_type_table (AtspiRelationType * types)
237 for (i = 0; i < ATK_RELATION_LAST_DEFINED; i++)
238 types[i] = ATSPI_RELATION_NULL;
240 types[ATK_RELATION_CONTROLLED_BY] = ATSPI_RELATION_CONTROLLED_BY;
241 types[ATK_RELATION_CONTROLLER_FOR] = ATSPI_RELATION_CONTROLLER_FOR;
242 types[ATK_RELATION_LABEL_FOR] = ATSPI_RELATION_LABEL_FOR;
243 types[ATK_RELATION_LABELLED_BY] = ATSPI_RELATION_LABELLED_BY;
244 types[ATK_RELATION_MEMBER_OF] = ATSPI_RELATION_MEMBER_OF;
245 types[ATK_RELATION_NODE_CHILD_OF] = ATSPI_RELATION_NODE_CHILD_OF;
246 types[ATK_RELATION_FLOWS_TO] = ATSPI_RELATION_FLOWS_TO;
247 types[ATK_RELATION_FLOWS_FROM] = ATSPI_RELATION_FLOWS_FROM;
248 types[ATK_RELATION_SUBWINDOW_OF] = ATSPI_RELATION_SUBWINDOW_OF;
249 types[ATK_RELATION_EMBEDS] = ATSPI_RELATION_EMBEDS;
250 types[ATK_RELATION_EMBEDDED_BY] = ATSPI_RELATION_EMBEDDED_BY;
251 types[ATK_RELATION_POPUP_FOR] = ATSPI_RELATION_POPUP_FOR;
252 types[ATK_RELATION_PARENT_WINDOW_OF] =
253 ATSPI_RELATION_PARENT_WINDOW_OF;
254 types[ATK_RELATION_DESCRIPTION_FOR] =
255 ATSPI_RELATION_DESCRIPTION_FOR;
256 types[ATK_RELATION_DESCRIBED_BY] = ATSPI_RELATION_DESCRIBED_BY;
257 types[ATK_RELATION_NODE_PARENT_OF] = ATSPI_RELATION_NODE_PARENT_OF;
262 static AtspiRelationType
263 spi_relation_type_from_atk_relation_type (AtkRelationType type)
265 static gboolean is_initialized = FALSE;
266 static AtspiRelationType
267 spi_relation_type_table[ATK_RELATION_LAST_DEFINED];
268 AtspiRelationType spi_type;
271 is_initialized = spi_init_relation_type_table (spi_relation_type_table);
273 if (type > ATK_RELATION_NULL && type < ATK_RELATION_LAST_DEFINED)
274 spi_type = spi_relation_type_table[type];
276 spi_type = ATSPI_RELATION_EXTENDED;
281 impl_GetRelationSet (DBusConnection * bus,
282 DBusMessage * message, void *user_data)
284 AtkObject *object = (AtkObject *) user_data;
287 DBusMessageIter iter, iter_array, iter_struct, iter_targets;
291 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
292 droute_not_yet_handled_error (message));
293 reply = dbus_message_new_method_return (message);
296 set = atk_object_ref_relation_set (object);
297 dbus_message_iter_init_append (reply, &iter);
298 if (!dbus_message_iter_open_container
299 (&iter, DBUS_TYPE_ARRAY, "(ua(so))", &iter_array))
305 count = atk_relation_set_get_n_relations (set);
306 for (i = 0; i < count; i++)
308 AtkRelation *r = atk_relation_set_get_relation (set, i);
314 rt = atk_relation_get_relation_type (r);
315 type = spi_relation_type_from_atk_relation_type (rt);
316 target = atk_relation_get_target (r);
317 if (!dbus_message_iter_open_container
318 (&iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct))
322 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &type);
323 if (!dbus_message_iter_open_container
324 (&iter_struct, DBUS_TYPE_ARRAY, "(so)", &iter_targets))
328 for (j = 0; j < target->len; j++)
330 AtkObject *obj = target->pdata[j];
333 spi_object_append_reference (&iter_targets, obj);
335 dbus_message_iter_close_container (&iter_struct, &iter_targets);
336 dbus_message_iter_close_container (&iter_array, &iter_struct);
338 dbus_message_iter_close_container (&iter, &iter_array);
340 // TODO: handle out of memory */
345 impl_GetRole (DBusConnection * bus, DBusMessage * message, void *user_data)
347 AtkObject *object = (AtkObject *) user_data;
352 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
353 droute_not_yet_handled_error (message));
354 role = atk_object_get_role (object);
355 rv = spi_accessible_role_from_atk_role (role);
356 reply = dbus_message_new_method_return (message);
359 dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
366 impl_GetRoleName (DBusConnection * bus,
367 DBusMessage * message, void *user_data)
369 AtkObject *object = (AtkObject *) user_data;
371 const char *role_name;
374 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
375 droute_not_yet_handled_error (message));
376 role = atk_object_get_role (object);
377 role_name = atk_role_get_name (role);
380 reply = dbus_message_new_method_return (message);
383 dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
390 impl_GetLocalizedRoleName (DBusConnection * bus,
391 DBusMessage * message, void *user_data)
393 AtkObject *object = (AtkObject *) user_data;
395 const char *role_name;
398 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
399 droute_not_yet_handled_error (message));
400 role = atk_object_get_role (object);
401 role_name = atk_role_get_localized_name (role);
404 reply = dbus_message_new_method_return (message);
407 dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
414 impl_GetState (DBusConnection * bus, DBusMessage * message, void *user_data)
416 AtkObject *object = (AtkObject *) user_data;
418 DBusMessage *reply = NULL;
419 DBusMessageIter iter, iter_array;
421 dbus_uint32_t states[2];
425 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
426 droute_not_yet_handled_error (message));
428 reply = dbus_message_new_method_return (message);
429 dbus_message_iter_init_append (reply, &iter);
431 spi_atk_state_to_dbus_array (object, states);
432 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "u", &iter_array);
433 for (count = 0; count < 2; count++)
435 dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_UINT32,
438 dbus_message_iter_close_container (&iter, &iter_array);
443 impl_GetAttributes (DBusConnection * bus,
444 DBusMessage * message, void *user_data)
446 AtkObject *object = (AtkObject *) user_data;
447 AtkAttributeSet *attributes;
448 DBusMessage *reply = NULL;
449 DBusMessageIter iter;
451 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
452 droute_not_yet_handled_error (message));
454 attributes = atk_object_get_attributes (object);
456 reply = dbus_message_new_method_return (message);
457 dbus_message_iter_init_append (reply, &iter);
458 spi_object_append_attribute_set (&iter, attributes);
460 atk_attribute_set_free (attributes);
466 impl_GetApplication (DBusConnection * bus,
467 DBusMessage * message, void *user_data)
469 return spi_object_return_reference (message, atk_get_root ());
473 impl_GetInterfaces (DBusConnection * bus,
474 DBusMessage * message, void *user_data)
476 AtkObject *object = (AtkObject *) user_data;
478 DBusMessageIter iter, iter_array;
480 g_return_val_if_fail (ATK_IS_OBJECT (user_data),
481 droute_not_yet_handled_error (message));
482 reply = dbus_message_new_method_return (message);
485 dbus_message_iter_init_append (reply, &iter);
486 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s",
488 spi_object_append_interfaces (&iter_array, object);
489 dbus_message_iter_close_container (&iter, &iter_array);
494 static DRouteMethod methods[] = {
495 {impl_GetChildAtIndex, "GetChildAtIndex"},
496 {impl_GetChildren, "GetChildren"},
497 {impl_GetIndexInParent, "GetIndexInParent"},
498 {impl_GetRelationSet, "GetRelationSet"},
499 {impl_GetRole, "GetRole"},
500 {impl_GetRoleName, "GetRoleName"},
501 {impl_GetLocalizedRoleName, "GetLocalizedRoleName"},
502 {impl_GetState, "GetState"},
503 {impl_GetAttributes, "GetAttributes"},
504 {impl_GetApplication, "GetApplication"},
505 {impl_GetInterfaces, "GetInterfaces"},
509 static DRouteProperty properties[] = {
510 {impl_get_Name, NULL, "Name"},
511 {impl_get_Description, NULL, "Description"},
512 {impl_get_Parent, NULL, "Parent"},
513 {impl_get_ChildCount, NULL, "ChildCount"},
518 spi_initialize_accessible (DRoutePath * path)
520 droute_path_add_interface (path,
521 ATSPI_DBUS_INTERFACE_ACCESSIBLE,
522 spi_org_a11y_atspi_Accessible,
523 methods, properties);