2 * AT-SPI - Assistive Technology Service Provider Interface
3 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
5 * Copyright 2008 Novell, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 #include <droute/droute.h>
25 #include "common/spi-dbus.h"
26 #include "common/spi-stateset.h"
28 #include "accessible-register.h"
29 #include "accessible-marshaller.h"
34 /*---------------------------------------------------------------------------*/
37 spi_dbus_append_name_and_path_inner (DBusMessageIter * iter,
38 const char *bus_name, const char *path)
40 DBusMessageIter iter_struct;
45 path = SPI_DBUS_PATH_NULL;
47 dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
49 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &bus_name);
50 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
51 dbus_message_iter_close_container (iter, &iter_struct);
54 extern gchar *atspi_dbus_name;
57 spi_dbus_append_name_and_path (DBusMessage * message, DBusMessageIter * iter,
58 AtkObject * obj, gboolean do_register,
62 DBusMessageIter iter_struct;
64 path = atk_dbus_object_to_path (obj, do_register);
66 spi_dbus_append_name_and_path_inner (iter, atspi_dbus_name, path);
74 * Marshals the D-Bus path of an AtkObject into a D-Bus message.
76 * Unrefs the AtkObject if unref is true.
79 spi_dbus_return_object (DBusMessage * message, AtkObject * obj,
80 gboolean do_register, gboolean unref)
83 reply = dbus_message_new_method_return (message);
87 dbus_message_iter_init_append (reply, &iter);
88 spi_dbus_append_name_and_path (message, &iter, obj, do_register, unref);
95 spi_dbus_return_hyperlink (DBusMessage * message, AtkHyperlink * link,
96 AtkObject * container, gboolean unref)
98 return spi_dbus_return_sub_object (message, G_OBJECT (link),
99 G_OBJECT (container), unref);
103 spi_dbus_return_sub_object (DBusMessage * message, GObject * sub,
104 GObject * container, gboolean unref)
109 path = atk_dbus_sub_object_to_path (sub, container);
112 g_object_unref (sub);
115 path = g_strdup (SPI_DBUS_PATH_NULL);
117 reply = dbus_message_new_method_return (message);
120 dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path,
129 /*---------------------------------------------------------------------------*/
132 * Marshals a variant containing the D-Bus path of an AtkObject into a D-Bus
135 * Unrefs the object if unref is true.
138 spi_dbus_return_v_object (DBusMessageIter * iter, AtkObject * obj, int unref)
140 DBusMessageIter iter_variant;
143 path = atk_dbus_object_to_path (obj, FALSE);
146 path = g_strdup (SPI_DBUS_PATH_NULL);
149 g_object_unref (obj);
151 dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "(so)",
153 spi_dbus_append_name_and_path_inner (&iter_variant, NULL, path);
154 dbus_message_iter_close_container (iter, &iter_variant);
158 /*---------------------------------------------------------------------------*/
161 append_atk_object_interfaces (AtkObject * object, DBusMessageIter * iter)
165 itf = SPI_DBUS_INTERFACE_ACCESSIBLE;
166 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
168 if (ATK_IS_ACTION (object))
170 itf = SPI_DBUS_INTERFACE_ACTION;
171 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
174 if (ATK_IS_COMPONENT (object))
176 itf = SPI_DBUS_INTERFACE_COMPONENT;
177 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
180 if (ATK_IS_EDITABLE_TEXT (object))
182 itf = SPI_DBUS_INTERFACE_EDITABLE_TEXT;
183 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
186 if (ATK_IS_TEXT (object))
188 itf = SPI_DBUS_INTERFACE_TEXT;
189 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
192 if (ATK_IS_HYPERTEXT (object))
194 itf = SPI_DBUS_INTERFACE_HYPERTEXT;
195 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
198 if (ATK_IS_IMAGE (object))
200 itf = SPI_DBUS_INTERFACE_IMAGE;
201 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
204 if (ATK_IS_SELECTION (object))
206 itf = SPI_DBUS_INTERFACE_SELECTION;
207 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
210 if (ATK_IS_TABLE (object))
212 itf = SPI_DBUS_INTERFACE_TABLE;
213 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
216 if (ATK_IS_VALUE (object))
218 itf = SPI_DBUS_INTERFACE_VALUE;
219 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
222 if (ATK_IS_STREAMABLE_CONTENT (object))
224 itf = "org.freedesktop.atspi.StreamableContent";
225 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
228 if (ATK_IS_DOCUMENT (object))
230 itf = "org.freedesktop.atspi.Collection";
231 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
232 itf = SPI_DBUS_INTERFACE_DOCUMENT;
233 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
236 if (ATK_IS_HYPERLINK_IMPL (object))
238 itf = SPI_DBUS_INTERFACE_HYPERLINK;
239 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
243 /*---------------------------------------------------------------------------*/
246 * Marshals the given AtkObject into the provided D-Bus iterator.
248 * The object is marshalled including all its client side cache data.
249 * The format of the structure is (o(so)a(so)assusau).
250 * This is used in the updateTree signal and the GetTree method
251 * of the org.freedesktop.atspi.Tree interface.
253 * To marshal an object its parent, and all its children must already
254 * be registered with D-Bus and have been given a D-Bus object path.
257 spi_atk_append_accessible (AtkObject * obj, gpointer data)
259 DBusMessageIter iter_struct, iter_sub_array;
260 dbus_uint32_t states[2];
263 DBusMessageIter *iter_array = (DBusMessageIter *) data;
265 const char *name, *desc;
268 set = atk_object_ref_state_set (obj);
272 gchar *bus_parent = NULL, *path_parent;
274 /* Marshall object path */
275 path = atk_dbus_object_to_path (obj, FALSE);
277 role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));
279 /* Marshall parent */
280 parent = atk_object_get_parent (obj);
283 /* TODO: Support getting parent of an AtkPlug */
284 #ifdef __ATK_PLUG_H__
285 if (ATK_IS_PLUG (obj))
287 char *id = g_object_get_data (G_OBJECT (obj), "dbus-plug-parent");
289 bus_parent = g_strdup (id);
290 if (bus_parent && (path_parent = g_utf8_strchr (bus_parent + 1, -1, ':')))
292 *(path_parent++) = '\0';
293 /* path_parent is going to be freed, so dup it */
294 path_parent = g_strdup (path_parent);
297 else if (role != Accessibility_ROLE_APPLICATION)
299 if (role != Accessibility_ROLE_APPLICATION)
301 path_parent = g_strdup (SPI_DBUS_PATH_NULL);
303 path_parent = atk_dbus_desktop_object_path ();
307 path_parent = atk_dbus_object_to_path (parent, FALSE);
310 /* This should only happen if a widget is re-parented to
311 * an AtkObject that has not been registered and is then
312 * updated. Ideally objects would be de-registered when
313 * they are removed from a registered tree object, but
314 * this would invalidate a huge amount of cache when
319 ("AT-SPI: Registered accessible marshalled when parent not registered");
321 path_parent = atk_dbus_desktop_object_path ();
325 dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL,
327 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH,
329 spi_dbus_append_name_and_path_inner (&iter_struct, bus_parent,
331 g_free (path_parent);
334 /* Marshall children */
335 dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "(so)",
337 if (!atk_state_set_contains_state (set, ATK_STATE_MANAGES_DESCENDANTS))
341 childcount = atk_object_get_n_accessible_children (obj);
342 for (i = 0; i < childcount; i++)
347 child = atk_object_ref_accessible_child (obj, i);
348 child_path = atk_dbus_object_to_path (child, FALSE);
351 spi_dbus_append_name_and_path_inner (&iter_sub_array, NULL,
355 g_object_unref (G_OBJECT (child));
358 #ifdef __ATK_PLUG_H__
359 if (ATK_IS_SOCKET (obj) && atk_socket_is_occupied (ATK_SOCKET (obj)))
361 AtkSocket *socket = ATK_SOCKET (obj);
362 gchar *child_name, *child_path;
363 child_name = g_strdup (socket->embedded_plug_id);
364 child_path = g_utf8_strchr (child_name + 1, -1, ':');
367 *(child_path++) = '\0';
368 spi_dbus_append_name_and_path_inner (&iter_sub_array, child_name,
375 dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
377 /* Marshall interfaces */
378 dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s",
380 append_atk_object_interfaces (obj, &iter_sub_array);
381 dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
384 name = atk_object_get_name (obj);
387 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
390 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role);
392 /* Marshall description */
393 desc = atk_object_get_description (obj);
396 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &desc);
400 /* Marshall state set */
401 spi_atk_state_set_to_dbus_array (set, states);
402 dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "u",
404 for (count = 0; count < 2; count++)
406 dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_UINT32,
409 dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
411 dbus_message_iter_close_container (iter_array, &iter_struct);
412 g_object_unref (set);
416 spi_atk_append_attribute_set (DBusMessageIter * iter, AtkAttributeSet * attr)
418 DBusMessageIter dictIter;
420 dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{ss}", &dictIter);
421 spi_atk_append_attribute_set_inner (&dictIter, attr);
422 dbus_message_iter_close_container (iter, &dictIter);
426 spi_atk_append_attribute_set_inner (DBusMessageIter * iter,
427 AtkAttributeSet * attr)
429 DBusMessageIter dictEntryIter;
433 AtkAttribute *attribute = (AtkAttribute *) attr->data;
434 dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL,
436 dbus_message_iter_append_basic (&dictEntryIter, DBUS_TYPE_STRING,
438 dbus_message_iter_append_basic (&dictEntryIter, DBUS_TYPE_STRING,
440 dbus_message_iter_close_container (iter, &dictEntryIter);
441 attr = g_slist_next (attr);
445 /*END------------------------------------------------------------------------*/