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 *this_app;
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 = &(this_app->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);
72 parent = atk_object_get_parent(obj);
74 path_parent = g_strdup("/");
76 path_parent = atk_dbus_get_path (parent);
77 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path_parent);
80 dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "o", &iter_sub_array);
84 childcount = atk_object_get_n_accessible_children (obj);
85 for (i = 0; i < childcount; i++)
90 child = atk_object_ref_accessible_child (obj, i);
91 child_path = atk_dbus_get_path (child);
92 g_object_unref(G_OBJECT(child));
93 dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_OBJECT_PATH, &child_path);
97 dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
99 dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s", &iter_sub_array);
101 for (l = data->interfaces; l; l = g_slist_next (l))
103 DRouteInterface *iface_def = (DRouteInterface *) l->data;
106 if (iface_def->get_datum)
108 datum = (*iface_def->get_datum) (path, data->user_data);
112 dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_STRING, &iface_def->name);
113 if (iface_def->free_datum)
114 (*iface_def->free_datum) (datum);
117 dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
119 name = atk_object_get_name (obj);
122 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
124 role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));
125 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role);
127 desc = atk_object_get_description (obj);
130 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &desc);
132 dbus_message_iter_close_container (iter_array, &iter_struct);
135 /*---------------------------------------------------------------------------*/
138 * Used to marshal array of objects to remove.
139 * Marshalls an object path onto the iter provided.
142 append_accessible_path(gpointer ref_data, gpointer null, gpointer data)
146 DBusMessageIter *iter_array;
148 iter_array = (DBusMessageIter *) data;
149 ref = GPOINTER_TO_INT(ref_data);
150 path = atk_dbus_get_path_from_ref(ref);
151 dbus_message_iter_append_basic (iter_array, DBUS_TYPE_OBJECT_PATH, &path);
155 /*---------------------------------------------------------------------------*/
158 send_cache_update(gpointer d)
160 DBusMessage *message;
161 DBusMessageIter iter;
162 DBusMessageIter iter_array;
165 data = &(this_app->droute);
167 message = dbus_message_new_signal ("/org/freedesktop/atspi/tree", SPI_DBUS_INTERFACE_TREE, "updateTree");
169 dbus_message_iter_init_append (message, &iter);
171 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ooaoassus)", &iter_array);
172 atk_dbus_foreach_update_list(append_accessible, &iter_array);
173 dbus_message_iter_close_container(&iter, &iter_array);
175 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "o", &iter_array);
176 atk_dbus_foreach_remove_list(append_accessible_path, &iter_array);
177 dbus_message_iter_close_container(&iter, &iter_array);
179 dbus_connection_send(data->bus, message, NULL);
180 update_pending = FALSE;
185 /*---------------------------------------------------------------------------*/
188 atk_tree_cache_needs_update(void)
192 g_idle_add(send_cache_update, NULL);
193 update_pending = TRUE;
197 /*---------------------------------------------------------------------------*/
200 impl_getRoot (DBusConnection *bus, DBusMessage *message, void *user_data)
202 AtkObject *root = atk_get_root();
206 if (root) path = atk_dbus_get_path(root);
208 return spi_dbus_general_error (message);
209 reply = dbus_message_new_method_return (message);
210 dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
215 /*---------------------------------------------------------------------------*/
218 impl_getTree (DBusConnection *bus, DBusMessage *message, void *user_data)
221 DBusMessageIter iter, iter_array;
222 AtkObject *root = atk_get_root();
225 return spi_dbus_general_error(message);
226 reply = dbus_message_new_method_return (message);
228 dbus_message_iter_init_append (reply, &iter);
229 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ooaoassus)", &iter_array);
230 atk_dbus_foreach_registered(append_accessible, &iter_array);
231 dbus_message_iter_close_container(&iter, &iter_array);
235 /*---------------------------------------------------------------------------*/
238 impl_introspect (DBusConnection *bus, DBusMessage *message, void *user_data)
246 path = dbus_message_get_path(message);
248 output = g_string_new(spi_introspection_header);
250 g_string_append_printf(output, spi_introspection_node_element, path);
252 spi_append_interface(output, SPI_DBUS_INTERFACE_TREE);
254 g_string_append(output, spi_introspection_footer);
255 final = g_string_free(output, FALSE);
257 reply = dbus_message_new_method_return (message);
258 g_assert(reply != NULL);
259 dbus_message_append_args(reply, DBUS_TYPE_STRING, &final,
266 /*---------------------------------------------------------------------------*/
268 static DBusHandlerResult
269 message_handler (DBusConnection *bus, DBusMessage *message, void *user_data)
271 const char *iface = dbus_message_get_interface (message);
272 const char *member = dbus_message_get_member (message);
274 DBusMessage *reply = NULL;
276 g_return_val_if_fail(iface != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
278 if (!strcmp(iface, SPI_DBUS_INTERFACE_TREE))
280 if (!strcmp(member, "getRoot"))
282 reply = impl_getRoot(bus, message, user_data);
285 if (!strcmp(member, "getTree"))
287 reply = impl_getTree(bus, message, user_data);
291 if (!strcmp(iface, "org.freedesktop.DBus.Introspectable"))
293 if (!strcmp(member, "Introspect"))
295 reply = impl_introspect(bus, message, user_data);
301 dbus_connection_send (bus, reply, NULL);
302 dbus_message_unref (reply);
305 return DBUS_HANDLER_RESULT_HANDLED;
308 /*---------------------------------------------------------------------------*/
310 static DBusObjectPathVTable tree_vtable =
314 NULL, NULL, NULL, NULL
317 /*---------------------------------------------------------------------------*/
320 spi_register_tree_object(DBusConnection *bus,
324 dbus_bool_t mem = FALSE;
325 mem = dbus_connection_register_object_path(bus, path, &tree_vtable, data);
326 g_assert(mem == TRUE);
329 /*END------------------------------------------------------------------------*/