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/introspect-loader.h>
28 #include "accessible.h"
31 extern SpiAppData *app_data;
32 static gboolean update_pending = FALSE;
34 /*---------------------------------------------------------------------------*/
36 static const char *dumm = "/APath/1";
39 * Marshals the given AtkObject into the provided D-Bus iterator.
41 * The object is marshalled including all its client side cache data.
42 * The format of the structure is (ooaoassusau).
43 * This is used in the updateTree signal and the getTree method
44 * of the org.freedesktop.atspi.Tree interface.
47 append_accessible(gpointer ref, gpointer obj_data, gpointer iter)
50 DBusMessageIter *iter_array;
51 DBusMessageIter iter_struct, iter_sub_array;
56 const char *name, *desc;
61 obj = ATK_OBJECT(obj_data);
62 iter_array = (DBusMessageIter *) iter;
63 data = &(app_data->droute);
65 dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct);
68 gchar *path, *path_parent;
70 path = atk_dbus_get_path_from_ref(GPOINTER_TO_INT(ref));
71 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
73 parent = atk_object_get_parent(obj);
75 path_parent = g_strdup("/");
77 path_parent = atk_dbus_get_path (parent);
78 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path_parent);
81 dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "o", &iter_sub_array);
85 childcount = atk_object_get_n_accessible_children (obj);
86 for (i = 0; i < childcount; i++)
91 child = atk_object_ref_accessible_child (obj, i);
92 child_path = atk_dbus_get_path (child);
93 g_object_unref(G_OBJECT(child));
94 dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_OBJECT_PATH, &child_path);
98 dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
100 dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s", &iter_sub_array);
102 for (l = data->interfaces; l; l = g_slist_next (l))
104 DRouteInterface *iface_def = (DRouteInterface *) l->data;
107 if (iface_def->get_datum)
109 datum = (*iface_def->get_datum) (path, data->user_data);
113 dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_STRING, &iface_def->name);
114 if (iface_def->free_datum)
115 (*iface_def->free_datum) (datum);
118 dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
120 name = atk_object_get_name (obj);
123 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
125 role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));
126 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role);
128 desc = atk_object_get_description (obj);
131 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &desc);
135 spi_atk_state_to_dbus_array (obj, &states);
136 dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "u", &iter_sub_array);
137 for (count = 0; states[count]; count++)
138 dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_UINT32, &states[count]);
139 dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
140 dbus_message_iter_close_container (iter_array, &iter_struct);
143 /*---------------------------------------------------------------------------*/
146 * Used to marshal array of objects to remove.
147 * Marshalls an object path onto the iter provided.
150 append_accessible_path(gpointer ref_data, gpointer null, gpointer data)
154 DBusMessageIter *iter_array;
156 iter_array = (DBusMessageIter *) data;
157 ref = GPOINTER_TO_INT(ref_data);
158 path = atk_dbus_get_path_from_ref(ref);
159 dbus_message_iter_append_basic (iter_array, DBUS_TYPE_OBJECT_PATH, &path);
163 /*---------------------------------------------------------------------------*/
166 send_cache_update(gpointer d)
168 DBusMessage *message;
169 DBusMessageIter iter;
170 DBusMessageIter iter_array;
173 data = &(app_data->droute);
175 message = dbus_message_new_signal ("/org/freedesktop/atspi/tree", SPI_DBUS_INTERFACE_TREE, "updateTree");
177 dbus_message_iter_init_append (message, &iter);
179 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ooaoassusau)", &iter_array);
180 atk_dbus_foreach_update_list(append_accessible, &iter_array);
181 dbus_message_iter_close_container(&iter, &iter_array);
183 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "o", &iter_array);
184 atk_dbus_foreach_remove_list(append_accessible_path, &iter_array);
185 dbus_message_iter_close_container(&iter, &iter_array);
187 dbus_connection_send(data->bus, message, NULL);
188 update_pending = FALSE;
193 /*---------------------------------------------------------------------------*/
196 atk_tree_cache_needs_update(void)
200 g_idle_add(send_cache_update, NULL);
201 update_pending = TRUE;
205 /*---------------------------------------------------------------------------*/
208 impl_getRoot (DBusConnection *bus, DBusMessage *message, void *user_data)
210 AtkObject *root = atk_get_root();
214 if (root) path = atk_dbus_get_path(root);
216 return spi_dbus_general_error (message);
217 reply = dbus_message_new_method_return (message);
218 dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
223 /*---------------------------------------------------------------------------*/
226 impl_getTree (DBusConnection *bus, DBusMessage *message, void *user_data)
229 DBusMessageIter iter, iter_array;
230 AtkObject *root = atk_get_root();
233 return spi_dbus_general_error(message);
234 reply = dbus_message_new_method_return (message);
236 dbus_message_iter_init_append (reply, &iter);
237 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ooaoassusau)", &iter_array);
238 atk_dbus_foreach_registered(append_accessible, &iter_array);
239 dbus_message_iter_close_container(&iter, &iter_array);
243 /*---------------------------------------------------------------------------*/
246 impl_introspect (DBusConnection *bus, DBusMessage *message, void *user_data)
254 path = dbus_message_get_path(message);
256 output = g_string_new(spi_introspection_header);
258 g_string_append_printf(output, spi_introspection_node_element, path);
260 spi_append_interface(output, SPI_DBUS_INTERFACE_TREE);
262 g_string_append(output, spi_introspection_footer);
263 final = g_string_free(output, FALSE);
265 reply = dbus_message_new_method_return (message);
266 g_assert(reply != NULL);
267 dbus_message_append_args(reply, DBUS_TYPE_STRING, &final,
274 /*---------------------------------------------------------------------------*/
276 static DBusHandlerResult
277 message_handler (DBusConnection *bus, DBusMessage *message, void *user_data)
279 const char *iface = dbus_message_get_interface (message);
280 const char *member = dbus_message_get_member (message);
282 DBusMessage *reply = NULL;
284 g_return_val_if_fail(iface != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
286 if (!strcmp(iface, SPI_DBUS_INTERFACE_TREE))
288 if (!strcmp(member, "getRoot"))
290 reply = impl_getRoot(bus, message, user_data);
293 if (!strcmp(member, "getTree"))
295 reply = impl_getTree(bus, message, user_data);
299 if (!strcmp(iface, "org.freedesktop.DBus.Introspectable"))
301 if (!strcmp(member, "Introspect"))
303 reply = impl_introspect(bus, message, user_data);
309 dbus_connection_send (bus, reply, NULL);
310 dbus_message_unref (reply);
313 return DBUS_HANDLER_RESULT_HANDLED;
316 /*---------------------------------------------------------------------------*/
318 static DBusObjectPathVTable tree_vtable =
322 NULL, NULL, NULL, NULL
325 /*---------------------------------------------------------------------------*/
328 spi_register_tree_object(DBusConnection *bus,
332 dbus_bool_t mem = FALSE;
333 mem = dbus_connection_register_object_path(bus, path, &tree_vtable, data);
334 g_assert(mem == TRUE);
337 /*END------------------------------------------------------------------------*/