Third time lucky for sorting out accessible registration.
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / accessible-marshaller.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2008 Novell, Inc.
6  *
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.
11  *
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.
16  *
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.
21  */
22
23 #include "accessible-register.h"
24 #include "accessible-marshaller.h"
25
26 #include "spi-common/spi-dbus.h"
27
28 #define INVALID_PATH "/Invalid"
29
30 /*---------------------------------------------------------------------------*/
31
32 /*
33  * Marshals the D-Bus path of an AtkObject into a D-Bus message.
34  *
35  * Unrefs the AtkObject if unref is true.
36  */
37 DBusMessage *
38 spi_dbus_return_object (DBusMessage *message, AtkObject *obj, gboolean unref)
39 {
40   DBusMessage *reply;
41   gchar *path;
42
43   path = atk_dbus_object_to_path (obj);
44
45   if (unref)
46     g_object_unref (obj);
47
48   reply = dbus_message_new_method_return (message);
49   if (reply)
50     {
51       dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, path,
52                                 DBUS_TYPE_INVALID);
53     }
54   return reply;
55 }
56
57 /*---------------------------------------------------------------------------*/
58
59 /*
60  * Marshals a variant containing the D-Bus path of an AtkObject into a D-Bus
61  * message.
62  *
63  * Unrefs the object if unref is true.
64  */
65 dbus_bool_t
66 spi_dbus_return_v_object (DBusMessageIter *iter, AtkObject *obj, int unref)
67 {
68   char *path;
69
70   path = atk_dbus_object_to_path (obj);
71
72   if (unref)
73     g_object_unref (obj);
74
75   return droute_return_v_object (iter, path);
76 }
77
78 /*---------------------------------------------------------------------------*/
79
80 static void
81 append_atk_object_interfaces (AtkObject *object, DBusMessageIter *iter)
82 {
83   const gchar *itf;
84
85   itf = SPI_DBUS_INTERFACE_ACCESSIBLE;
86   dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
87
88   if (ATK_IS_ACTION (object))
89     {
90       itf = SPI_DBUS_INTERFACE_ACTION;
91       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
92     }
93
94   if (ATK_IS_COMPONENT (object))
95     {
96       itf = SPI_DBUS_INTERFACE_COMPONENT;
97       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
98     }
99
100   if (ATK_IS_EDITABLE_TEXT (object))
101     {
102       itf = SPI_DBUS_INTERFACE_EDITABLE_TEXT;
103       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
104     }
105
106   if (ATK_IS_TEXT (object))
107     {
108       itf = SPI_DBUS_INTERFACE_TEXT;
109       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
110     }
111
112   if (ATK_IS_HYPERTEXT (object))
113     {
114       itf = SPI_DBUS_INTERFACE_HYPERTEXT;
115       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
116     }
117
118   if (ATK_IS_IMAGE (object))
119     {
120       itf = SPI_DBUS_INTERFACE_IMAGE;
121       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
122     }
123
124   if (ATK_IS_SELECTION (object))
125     {
126       itf = SPI_DBUS_INTERFACE_SELECTION;
127       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
128     }
129
130   if (ATK_IS_TABLE (object))
131     {
132       itf = SPI_DBUS_INTERFACE_TABLE;
133       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
134     }
135
136   if (ATK_IS_VALUE (object))
137     {
138       itf = SPI_DBUS_INTERFACE_VALUE;
139       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
140     }
141
142   if (ATK_IS_STREAMABLE_CONTENT (object))
143     {
144       itf = "org.freedesktop.atspi.StreamableContent";
145       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
146     }
147
148   if (ATK_IS_DOCUMENT (object))
149     {
150       itf = "org.freedesktop.atspi.Collection";
151       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
152       itf = SPI_DBUS_INTERFACE_DOCUMENT;
153       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
154     }
155
156   if (ATK_IS_HYPERLINK_IMPL (object))
157     {
158       itf = SPI_DBUS_INTERFACE_HYPERLINK;
159       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
160     }
161 }
162
163 /*---------------------------------------------------------------------------*/
164
165 /*
166  * Marshals the given AtkObject into the provided D-Bus iterator.
167  *
168  * The object is marshalled including all its client side cache data.
169  * The format of the structure is (ooaoassusau).
170  * This is used in the updateTree signal and the getTree method
171  * of the org.freedesktop.atspi.Tree interface.
172  *
173  * To marshal an object its parent, and all its children must already
174  * be registered with D-Bus and have been given a D-Bus object path.
175  */
176 void
177 spi_atk_append_accessible(AtkObject *obj, gpointer iter)
178 {
179   DBusMessageIter *iter_array;
180   DBusMessageIter iter_struct, iter_sub_array;
181   dbus_int32_t states [2];
182   int count;
183
184   const char *name, *desc;
185   int i;
186   dbus_uint32_t role;
187   GSList *l;
188
189   iter_array = (DBusMessageIter *) iter;
190
191   dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct);
192     {
193       AtkObject *parent;
194       gchar *path, *path_parent;
195
196       /* Marshall object path */
197       path = atk_dbus_object_to_path (obj);
198       dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
199
200       /* Marshall parent */
201       parent = atk_object_get_parent(obj);
202       if (parent == NULL)
203         {
204           path_parent = g_strdup("/");
205         }
206       else
207         {
208           path_parent = atk_dbus_object_to_path (parent);
209           if (!path_parent)
210             {
211               path_parent = g_strdup(INVALID_PATH);
212             }
213         }
214       dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path_parent);
215       g_free(path_parent);
216
217       /* Marshall children */
218       dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "o", &iter_sub_array);
219         {
220           gint childcount, i;
221
222           childcount = atk_object_get_n_accessible_children (obj);
223           for (i = 0; i < childcount; i++)
224             {
225               AtkObject *child;
226               gchar *child_path;
227
228               child = atk_object_ref_accessible_child (obj, i);
229               child_path = atk_dbus_object_to_path (child);
230               g_object_unref(G_OBJECT(child));
231               if (!G_LIKELY (child_path))
232                 {
233                   child_path = g_strdup(INVALID_PATH);
234                 }
235               dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_OBJECT_PATH, &child_path);
236               g_free (child_path);
237             }
238         }
239       dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
240
241       /* Marshall interfaces */
242       dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s", &iter_sub_array);
243       append_atk_object_interfaces (obj, &iter_sub_array);
244       dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
245
246       /* Marshall name */
247       name = atk_object_get_name (obj);
248       if (!name)
249         name = "";
250       dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
251
252       /* Marshall role */
253       role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));
254       dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role);
255
256       /* Marshall description */
257       desc = atk_object_get_description (obj);
258       if (!desc)
259         desc = "";
260       dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &desc);
261
262       g_free(path);
263
264       /* Marshall state set */
265       spi_atk_state_to_dbus_array (obj, &states);
266       dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "u", &iter_sub_array);
267       for (count = 0; count < 2; count++)
268         {
269           dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_UINT32, &states[count]);
270         }
271       dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
272     }
273   dbus_message_iter_close_container (iter_array, &iter_struct);
274 }
275
276 /*END------------------------------------------------------------------------*/
277