Correct update flag
[platform/core/uifw/at-spi2-atk.git] / libspi / tree.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  *
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.
13  *
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.
18  *
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.
23  */
24
25 #include "accessible.h"
26
27 #define get_object(message) spi_dbus_get_object(dbus_message_get_path(message))
28
29 #define TREE_UPDATE_ACCESSIBLE 0
30 #define TREE_REMOVE_ACCESSIBLE 1
31
32 static dbus_bool_t
33 spi_dbus_append_tree_helper (DBusMessageIter * iter_array, AtkObject * obj,
34                              DRouteData * data)
35 {
36   DBusMessageIter iter_struct, iter_sub_array;
37   char *path = NULL;
38   char *path_parent;
39   const char *name, *desc;
40   dbus_uint16_t updating = TREE_UPDATE_ACCESSIBLE;
41   int i;
42   dbus_uint32_t role;
43
44   gint childcount;
45   GSList *l;
46
47   dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL,
48                                     &iter_struct);
49   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT16, &updating);
50   path = spi_dbus_get_path (obj);
51   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
52   path_parent = spi_dbus_get_path (atk_object_get_parent(obj));
53   if (!path_parent) path_parent = g_strdup("/");
54   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path_parent);
55   g_free(path_parent);
56   dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "o",
57                                     &iter_sub_array);
58   childcount = atk_object_get_n_accessible_children (obj);
59   for (i = 0; i < childcount; i++)
60     {
61       AtkObject *child = atk_object_ref_accessible_child (obj, i);
62       char *child_path = spi_dbus_get_path (child);
63       if (child_path)
64         {
65           dbus_message_iter_append_basic (&iter_sub_array,
66                                           DBUS_TYPE_OBJECT_PATH, &child_path);
67           g_free (child_path);
68         }
69       if (child)
70         g_object_unref (child);
71     }
72   if (!dbus_message_iter_close_container (&iter_struct, &iter_sub_array))
73     goto oom;
74   dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s",
75                                     &iter_sub_array);
76   for (l = data->interfaces; l; l = g_slist_next (l))
77     {
78       DRouteInterface *iface_def = (DRouteInterface *) l->data;
79       void *datum = NULL;
80       if (iface_def->get_datum)
81         {
82           datum = (*iface_def->get_datum) (path, data->user_data);
83           if (!datum)
84             continue;
85         }
86       dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_STRING,
87                                       &iface_def->name);
88       if (iface_def->free_datum)
89         (*iface_def->free_datum) (datum);
90     }
91   if (!dbus_message_iter_close_container (&iter_struct, &iter_sub_array))
92     goto oom;
93   name = atk_object_get_name (obj);
94   if (!name)
95     name = "";
96   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
97   role = spi_accessible_role_from_atk_role (atk_object_get_role (obj));
98   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role);
99   desc = atk_object_get_description (obj);
100   if (!desc)
101     desc = "";
102   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &desc);
103   if (!dbus_message_iter_close_container (iter_array, &iter_struct))
104     goto oom;
105   for (i = 0; i < childcount; i++)
106     {
107       AtkObject *child = atk_object_ref_accessible_child (obj, i);
108       dbus_bool_t result;
109       if (!child)
110         continue;
111       result = spi_dbus_append_tree_helper (iter_array, child, data);
112       g_object_unref (child);
113       if (!result)
114         goto oom;
115     }
116   g_free (path);
117   return TRUE;
118 oom:
119   if (path) g_free(path);
120   return FALSE;
121 }
122
123 dbus_bool_t
124 spi_dbus_append_tree (DBusMessage * message, AtkObject * obj,
125                       DRouteData * data)
126 {
127   DBusMessageIter iter, iter_array;
128   dbus_bool_t result;
129
130   dbus_message_iter_init_append (message, &iter);
131   dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(qooaoassus)",
132                                     &iter_array);
133   result = spi_dbus_append_tree_helper (&iter_array, obj, data);
134   if (result)
135     result = dbus_message_iter_close_container (&iter, &iter_array);
136   return result;
137 }
138
139 static DBusMessage *
140 impl_getRoot (DBusConnection * bus, DBusMessage * message, void *user_data)
141 {
142   AtkObject *root = atk_get_root();
143   char *path;
144   DBusMessage *reply;
145
146   if (root) path = spi_dbus_get_path(root);
147   if (!root || !path)
148     return spi_dbus_general_error (message);
149   reply = dbus_message_new_method_return (message);
150   dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path,
151                             DBUS_TYPE_INVALID);
152   g_free (path);
153   return reply;
154 }
155
156 static DBusMessage *
157 impl_getTree (DBusConnection * bus, DBusMessage * message, void *user_data)
158 {
159   DBusMessage *reply;
160   AtkObject *root = atk_get_root();
161
162   if (!root) return spi_dbus_general_error(message);
163   reply = dbus_message_new_method_return (message);
164   spi_dbus_append_tree (reply, root, (DRouteData *) user_data);
165   return reply;
166 }
167
168 static DRouteMethod methods[] = {
169   {DROUTE_METHOD, impl_getRoot, "getRoot", "o,root,o" },
170   {DROUTE_METHOD, impl_getTree, "getTree", "a(qooaoassus),tree,o", TRUE},
171   {0, NULL, NULL, NULL}
172 };
173
174 void
175 spi_initialize_tree (DRouteData * data)
176 {
177   droute_add_interface (data, "org.freedesktop.atspi.Tree",
178                         methods, NULL, NULL, NULL);
179 };