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 strucuture is (ooaoassus).
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;
54 const char *name, *desc;
59 obj = ATK_OBJECT(obj_data);
60 iter_array = (DBusMessageIter *) iter;
61 data = &(app_data->droute);
63 dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct);
66 gchar *path, *path_parent;
68 path = atk_dbus_get_path_from_ref(GPOINTER_TO_INT(ref));
69 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
71 parent = atk_object_get_parent(obj);
73 path_parent = g_strdup("/");
75 path_parent = atk_dbus_get_path (parent);
76 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path_parent);
79 dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "o", &iter_sub_array);
83 childcount = atk_object_get_n_accessible_children (obj);
84 for (i = 0; i < childcount; i++)
89 child = atk_object_ref_accessible_child (obj, i);
90 child_path = atk_dbus_get_path (child);
91 g_object_unref(G_OBJECT(child));
92 dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_OBJECT_PATH, &child_path);
96 dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
98 dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s", &iter_sub_array);
100 for (l = data->interfaces; l; l = g_slist_next (l))
102 DRouteInterface *iface_def = (DRouteInterface *) l->data;
105 if (iface_def->get_datum)
107 datum = (*iface_def->get_datum) (path, data->user_data);
111 dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_STRING, &iface_def->name);
112 if (iface_def->free_datum)
113 (*iface_def->free_datum) (datum);
116 dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
118 name = atk_object_get_name (obj);
121 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
123 role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));
124 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role);
126 desc = atk_object_get_description (obj);
129 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &desc);
133 dbus_message_iter_close_container (iter_array, &iter_struct);
136 /*---------------------------------------------------------------------------*/
139 * Used to marshal array of objects to remove.
140 * Marshalls an object path onto the iter provided.
143 append_accessible_path(gpointer ref_data, gpointer null, gpointer data)
147 DBusMessageIter *iter_array;
149 iter_array = (DBusMessageIter *) data;
150 ref = GPOINTER_TO_INT(ref_data);
151 path = atk_dbus_get_path_from_ref(ref);
152 dbus_message_iter_append_basic (iter_array, DBUS_TYPE_OBJECT_PATH, &path);
156 /*---------------------------------------------------------------------------*/
159 send_cache_update(gpointer d)
161 DBusMessage *message;
162 DBusMessageIter iter;
163 DBusMessageIter iter_array;
166 data = &(app_data->droute);
168 message = dbus_message_new_signal ("/org/freedesktop/atspi/tree", SPI_DBUS_INTERFACE_TREE, "updateTree");
170 dbus_message_iter_init_append (message, &iter);
172 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ooaoassus)", &iter_array);
173 atk_dbus_foreach_update_list(append_accessible, &iter_array);
174 dbus_message_iter_close_container(&iter, &iter_array);
176 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "o", &iter_array);
177 atk_dbus_foreach_remove_list(append_accessible_path, &iter_array);
178 dbus_message_iter_close_container(&iter, &iter_array);
180 dbus_connection_send(data->bus, message, NULL);
181 update_pending = FALSE;
186 /*---------------------------------------------------------------------------*/
189 atk_tree_cache_needs_update(void)
193 g_idle_add(send_cache_update, NULL);
194 update_pending = TRUE;
198 /*---------------------------------------------------------------------------*/
201 impl_getRoot (DBusConnection *bus, DBusMessage *message, void *user_data)
203 AtkObject *root = atk_get_root();
207 if (root) path = atk_dbus_get_path(root);
209 return spi_dbus_general_error (message);
210 reply = dbus_message_new_method_return (message);
211 dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
216 /*---------------------------------------------------------------------------*/
219 impl_getTree (DBusConnection *bus, DBusMessage *message, void *user_data)
222 DBusMessageIter iter, iter_array;
223 AtkObject *root = atk_get_root();
226 return spi_dbus_general_error(message);
227 reply = dbus_message_new_method_return (message);
229 dbus_message_iter_init_append (reply, &iter);
230 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ooaoassus)", &iter_array);
231 atk_dbus_foreach_registered(append_accessible, &iter_array);
232 dbus_message_iter_close_container(&iter, &iter_array);
236 /*---------------------------------------------------------------------------*/
239 impl_introspect (DBusConnection *bus, DBusMessage *message, void *user_data)
247 path = dbus_message_get_path(message);
249 output = g_string_new(spi_introspection_header);
251 g_string_append_printf(output, spi_introspection_node_element, path);
253 spi_append_interface(output, SPI_DBUS_INTERFACE_TREE);
255 g_string_append(output, spi_introspection_footer);
256 final = g_string_free(output, FALSE);
258 reply = dbus_message_new_method_return (message);
259 g_assert(reply != NULL);
260 dbus_message_append_args(reply, DBUS_TYPE_STRING, &final,
267 /*---------------------------------------------------------------------------*/
269 static DBusHandlerResult
270 message_handler (DBusConnection *bus, DBusMessage *message, void *user_data)
272 const char *iface = dbus_message_get_interface (message);
273 const char *member = dbus_message_get_member (message);
275 DBusMessage *reply = NULL;
277 g_return_val_if_fail(iface != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
279 if (!strcmp(iface, SPI_DBUS_INTERFACE_TREE))
281 if (!strcmp(member, "getRoot"))
283 reply = impl_getRoot(bus, message, user_data);
286 if (!strcmp(member, "getTree"))
288 reply = impl_getTree(bus, message, user_data);
292 if (!strcmp(iface, "org.freedesktop.DBus.Introspectable"))
294 if (!strcmp(member, "Introspect"))
296 reply = impl_introspect(bus, message, user_data);
302 dbus_connection_send (bus, reply, NULL);
303 dbus_message_unref (reply);
306 return DBUS_HANDLER_RESULT_HANDLED;
309 /*---------------------------------------------------------------------------*/
311 static DBusObjectPathVTable tree_vtable =
315 NULL, NULL, NULL, NULL
318 /*---------------------------------------------------------------------------*/
321 spi_register_tree_object(DBusConnection *bus,
325 dbus_bool_t mem = FALSE;
326 mem = dbus_connection_register_object_path(bus, path, &tree_vtable, data);
327 g_assert(mem == TRUE);
330 /*END------------------------------------------------------------------------*/