a4411d0fd4ece43b28b0d2409b133f2de3749111
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / tree-adaptor.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  * Copyright 2001, 2002 Sun Microsystems Inc.,
7  * Copyright 2001, 2002 Ximian, Inc.
8  * Copyright 2008, 2009 Codethink Ltd.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public
21  * License along with this library; if not, write to the
22  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */
25
26 #include <string.h>
27
28 #include <atk/atk.h>
29 #include <droute/droute.h>
30
31 #include "bridge.h"
32 #include "accessible-register.h"
33 #include "spi-common/spi-dbus.h"
34
35 /*---------------------------------------------------------------------------*/
36
37 static void
38 append_atk_object_interfaces (AtkObject *object, DBusMessageIter *iter)
39 {
40   const gchar *itf;
41
42   itf = SPI_DBUS_INTERFACE_ACCESSIBLE;
43   dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
44
45   if (ATK_IS_ACTION (object))
46     {
47       itf = SPI_DBUS_INTERFACE_ACTION;
48       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
49     }
50
51   if (ATK_IS_COMPONENT (object))
52     {
53       itf = SPI_DBUS_INTERFACE_COMPONENT;
54       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
55     }
56
57   if (ATK_IS_EDITABLE_TEXT (object))
58     {
59       itf = SPI_DBUS_INTERFACE_EDITABLE_TEXT;
60       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
61     }
62
63   if (ATK_IS_TEXT (object))
64     {
65       itf = SPI_DBUS_INTERFACE_TEXT;
66       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
67     }
68
69   if (ATK_IS_HYPERTEXT (object))
70     {
71       itf = SPI_DBUS_INTERFACE_HYPERTEXT;
72       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
73     }
74
75   if (ATK_IS_IMAGE (object))
76     {
77       itf = SPI_DBUS_INTERFACE_IMAGE;
78       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
79     }
80
81   if (ATK_IS_SELECTION (object))
82     {
83       itf = SPI_DBUS_INTERFACE_SELECTION;
84       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
85     }
86
87   if (ATK_IS_TABLE (object))
88     {
89       itf = SPI_DBUS_INTERFACE_TABLE;
90       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
91     }
92
93   if (ATK_IS_VALUE (object))
94     {
95       itf = SPI_DBUS_INTERFACE_VALUE;
96       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
97     }
98
99   if (ATK_IS_STREAMABLE_CONTENT (object))
100     {
101       itf = "org.freedesktop.atspi.StreamableContent";
102       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
103     }
104
105   if (ATK_IS_DOCUMENT (object))
106     {
107       itf = "org.freedesktop.atspi.Collection";
108       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
109       itf = SPI_DBUS_INTERFACE_DOCUMENT;
110       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
111     }
112
113   if (ATK_IS_HYPERLINK_IMPL (object))
114     {
115       itf = SPI_DBUS_INTERFACE_HYPERLINK;
116       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
117     }
118 }
119
120 /*---------------------------------------------------------------------------*/
121
122 static const char *dumm = "/APath/1";
123
124
125 /*
126  * Marshals the given AtkObject into the provided D-Bus iterator.
127  *
128  * The object is marshalled including all its client side cache data.
129  * The format of the structure is (ooaoassusau).
130  * This is used in the updateTree signal and the getTree method
131  * of the org.freedesktop.atspi.Tree interface.
132  */
133 static void
134 append_accessible(gpointer obj_data, gpointer iter)
135 {
136   AtkObject *obj;
137   DBusMessageIter *iter_array;
138   DBusMessageIter iter_struct, iter_sub_array;
139   dbus_int32_t states [2];
140   int count;
141
142   const char *name, *desc;
143   int i;
144   dbus_uint32_t role;
145   GSList *l;
146
147   obj = ATK_OBJECT(obj_data);
148   iter_array = (DBusMessageIter *) iter;
149
150   dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct);
151     {
152       AtkObject *parent;
153       gchar *path, *path_parent;
154
155       path = atk_dbus_object_to_path (obj);
156       dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
157
158       parent = atk_object_get_parent(obj);
159       if (parent == NULL)
160         path_parent = g_strdup("/");
161       else
162         path_parent = atk_dbus_object_to_path (parent);
163       dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path_parent);
164       g_free(path_parent);
165
166       dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "o", &iter_sub_array);
167         {
168           gint childcount, i;
169
170           childcount = atk_object_get_n_accessible_children (obj);
171           for (i = 0; i < childcount; i++)
172             {
173               AtkObject *child;
174               gchar *child_path;
175
176               child = atk_object_ref_accessible_child (obj, i);
177               child_path = atk_dbus_object_to_path (child);
178               g_object_unref(G_OBJECT(child));
179               if (G_LIKELY (child_path))
180                 {
181                   dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_OBJECT_PATH, &child_path);
182                 }
183               else
184                 {
185                   g_critical ("AT-SPI: Child object exists in accessible tree but has not been registered");
186                   g_free (child_path);
187                 }
188             }
189         }
190       dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
191
192       dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s", &iter_sub_array);
193       append_atk_object_interfaces (obj, &iter_sub_array);
194       dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
195
196       name = atk_object_get_name (obj);
197       if (!name)
198         name = "";
199       dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
200
201       role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));
202       dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role);
203
204       desc = atk_object_get_description (obj);
205       if (!desc)
206         desc = "";
207       dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &desc);
208
209       g_free(path);
210     }
211   spi_atk_state_to_dbus_array (obj, &states);
212       dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "u", &iter_sub_array);
213   for (count = 0; count < 2; count++)
214     dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_UINT32, &states[count]);
215       dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
216   dbus_message_iter_close_container (iter_array, &iter_struct);
217 }
218
219 /* For use as a GHFunc */
220 static void
221 append_accessible_hf (gpointer key, gpointer obj_data, gpointer iter)
222 {
223   append_accessible (obj_data, iter);
224 }
225
226 /*---------------------------------------------------------------------------*/
227
228 void
229 spi_emit_cache_removal (guint ref,  DBusConnection *bus)
230 {
231   DBusMessage *message;
232   DBusMessageIter iter;
233   gchar *path;
234
235   message = dbus_message_new_signal ("/org/freedesktop/atspi/tree", SPI_DBUS_INTERFACE_TREE, "removeAccessible");
236
237   dbus_message_iter_init_append (message, &iter);
238
239   path = atk_dbus_ref_to_path (ref);
240   dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &path);
241
242   dbus_connection_send(bus, message, NULL);
243 }
244
245 void
246 spi_emit_cache_update (const GList *accessibles, DBusConnection *bus)
247 {
248    DBusMessage *message;
249    DBusMessageIter iter;
250    DBusMessageIter iter_array;
251    message = dbus_message_new_signal ("/org/freedesktop/atspi/tree", SPI_DBUS_INTERFACE_TREE, "updateAccessible");
252
253    dbus_message_iter_init_append (message, &iter);
254    dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ooaoassusau)", &iter_array);
255    g_list_foreach ((GList *)accessibles, append_accessible, &iter_array);
256    dbus_message_iter_close_container(&iter, &iter_array);
257
258    dbus_connection_send(bus, message, NULL);
259 }
260
261
262 /*---------------------------------------------------------------------------*/
263
264 static DBusMessage *
265 impl_getRoot (DBusConnection *bus, DBusMessage *message, void *user_data)
266 {
267   AtkObject *root = atk_get_root();
268   char *path;
269   DBusMessage *reply;
270
271   if (!root)
272       return spi_dbus_general_error (message);
273   path = atk_dbus_object_to_path (root);
274   if (!path)
275       return spi_dbus_general_error (message);
276   reply = dbus_message_new_method_return (message);
277   dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
278   g_free (path);
279   return reply;
280 }
281
282 /*---------------------------------------------------------------------------*/
283
284 static DBusMessage *
285 impl_getTree (DBusConnection *bus, DBusMessage *message, void *user_data)
286 {
287   DBusMessage *reply;
288   DBusMessageIter iter, iter_array;
289
290   reply = dbus_message_new_method_return (message);
291
292   dbus_message_iter_init_append (reply, &iter);
293   dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ooaoassusau)", &iter_array);
294   atk_dbus_foreach_registered(append_accessible_hf, &iter_array);
295   dbus_message_iter_close_container(&iter, &iter_array);
296   return reply;
297 }
298
299 /*---------------------------------------------------------------------------*/
300
301 static DRouteMethod methods[] = {
302   {impl_getRoot, "getRoot"},
303   {impl_getTree, "getTree"},
304   {NULL, NULL}
305 };
306
307 void
308 spi_initialize_tree (DRoutePath *path)
309 {
310   droute_path_add_interface (path,
311                              SPI_DBUS_INTERFACE_TREE,
312                              methods,
313                              NULL);
314 };
315
316 /*END------------------------------------------------------------------------*/