6359fa775a0db1c7e38f14257274dead5a1fe2f8
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / adaptors / accessible-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  *
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 <atk/atk.h>
26 #include <droute/droute.h>
27
28 #include "common/spi-dbus.h"
29 #include "common/spi-stateset.h"
30 #include "object.h"
31
32 static dbus_bool_t
33 impl_get_Name (DBusMessageIter * iter, void *user_data)
34 {
35   AtkObject *object = (AtkObject *) user_data;
36
37   g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
38
39   return droute_return_v_string (iter, atk_object_get_name (object));
40 }
41
42 static dbus_bool_t
43 impl_set_Name (DBusMessageIter * iter, void *user_data)
44 {
45   AtkObject *object = (AtkObject *) user_data;
46   const char *name = droute_get_v_string (iter);
47
48   g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
49
50   atk_object_set_name (object, name);
51   return TRUE;
52 }
53
54 static dbus_bool_t
55 impl_get_Description (DBusMessageIter * iter, void *user_data)
56 {
57   AtkObject *object = (AtkObject *) user_data;
58
59   g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
60
61   return droute_return_v_string (iter, atk_object_get_description (object));
62 }
63
64 static dbus_bool_t
65 impl_set_Description (DBusMessageIter * iter, void *user_data)
66 {
67   AtkObject *object = (AtkObject *) user_data;
68   const char *description = droute_get_v_string (iter);
69
70   g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
71
72   atk_object_set_description (object, description);
73   return TRUE;
74 }
75
76 static dbus_bool_t
77 impl_get_Parent (DBusMessageIter * iter, void *user_data)
78 {
79   AtkObject *object = (AtkObject *) user_data;
80
81   g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
82
83   spi_object_append_v_reference (iter, atk_object_get_parent (object));
84   return TRUE;
85 }
86
87 static dbus_bool_t
88 impl_get_ChildCount (DBusMessageIter * iter, void *user_data)
89 {
90   AtkObject *object = (AtkObject *) user_data;
91
92   g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE);
93
94   return droute_return_v_int32 (iter,
95                                 atk_object_get_n_accessible_children
96                                 (object));
97 }
98
99 static DBusMessage *
100 impl_GetChildAtIndex (DBusConnection * bus,
101                       DBusMessage * message, void *user_data)
102 {
103   AtkObject *object = (AtkObject *) user_data;
104   DBusError error;
105   dbus_int32_t i;
106   AtkObject *child;
107
108   dbus_error_init (&error);
109   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
110                         droute_not_yet_handled_error (message));
111   if (!dbus_message_get_args 
112        (message, &error, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID))
113     {
114       return droute_invalid_arguments_error (message);
115     }
116   child = atk_object_ref_accessible_child (object, i);
117   return spi_object_return_reference (message, child);
118 }
119
120 static DBusMessage *
121 impl_GetChildren (DBusConnection * bus,
122                   DBusMessage * message, void *user_data)
123 {
124   AtkObject *object = (AtkObject *) user_data;
125   gint i;
126   gint count;
127   DBusMessage *reply;
128   DBusMessageIter iter, iter_array;
129
130   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
131                         droute_not_yet_handled_error (message));
132   count = atk_object_get_n_accessible_children (object);
133   reply = dbus_message_new_method_return (message);
134   if (!reply)
135     goto oom;
136   dbus_message_iter_init_append (reply, &iter);
137   if (!dbus_message_iter_open_container
138       (&iter, DBUS_TYPE_ARRAY, "(so)", &iter_array))
139     goto oom;
140   for (i = 0; i < count; i++)
141     {
142       AtkObject *child = atk_object_ref_accessible_child (object, i);
143       spi_object_append_reference (&iter_array, child); 
144       if (child)
145         g_object_unref (child);
146     }
147   if (!dbus_message_iter_close_container (&iter, &iter_array))
148     goto oom;
149   return reply;
150 oom:
151   // TODO: handle out-of-memory
152   return reply;
153 }
154
155 static DBusMessage *
156 impl_GetIndexInParent (DBusConnection * bus,
157                        DBusMessage * message, void *user_data)
158 {
159   AtkObject *object = (AtkObject *) user_data;
160   dbus_uint32_t rv;
161   DBusMessage *reply;
162
163   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
164                         droute_not_yet_handled_error (message));
165
166   rv = atk_object_get_index_in_parent (object);
167   reply = dbus_message_new_method_return (message);
168   dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv, DBUS_TYPE_INVALID);
169   return reply;
170 }
171
172 static gboolean
173 spi_init_relation_type_table (Accessibility_RelationType * types)
174 {
175   gint i;
176
177   for (i = 0; i < ATK_RELATION_LAST_DEFINED; i++)
178     types[i] = Accessibility_RELATION_NULL;
179
180   types[ATK_RELATION_CONTROLLED_BY] = Accessibility_RELATION_CONTROLLED_BY;
181   types[ATK_RELATION_CONTROLLER_FOR] = Accessibility_RELATION_CONTROLLER_FOR;
182   types[ATK_RELATION_LABEL_FOR] = Accessibility_RELATION_LABEL_FOR;
183   types[ATK_RELATION_LABELLED_BY] = Accessibility_RELATION_LABELLED_BY;
184   types[ATK_RELATION_MEMBER_OF] = Accessibility_RELATION_MEMBER_OF;
185   types[ATK_RELATION_NODE_CHILD_OF] = Accessibility_RELATION_NODE_CHILD_OF;
186   types[ATK_RELATION_FLOWS_TO] = Accessibility_RELATION_FLOWS_TO;
187   types[ATK_RELATION_FLOWS_FROM] = Accessibility_RELATION_FLOWS_FROM;
188   types[ATK_RELATION_SUBWINDOW_OF] = Accessibility_RELATION_SUBWINDOW_OF;
189   types[ATK_RELATION_EMBEDS] = Accessibility_RELATION_EMBEDS;
190   types[ATK_RELATION_EMBEDDED_BY] = Accessibility_RELATION_EMBEDDED_BY;
191   types[ATK_RELATION_POPUP_FOR] = Accessibility_RELATION_POPUP_FOR;
192   types[ATK_RELATION_PARENT_WINDOW_OF] =
193     Accessibility_RELATION_PARENT_WINDOW_OF;
194   types[ATK_RELATION_DESCRIPTION_FOR] =
195     Accessibility_RELATION_DESCRIPTION_FOR;
196   types[ATK_RELATION_DESCRIBED_BY] = Accessibility_RELATION_DESCRIBED_BY;
197
198   return TRUE;
199 }
200
201 static Accessibility_RelationType
202 spi_relation_type_from_atk_relation_type (AtkRelationType type)
203 {
204   static gboolean is_initialized = FALSE;
205   static Accessibility_RelationType
206     spi_relation_type_table[ATK_RELATION_LAST_DEFINED];
207   Accessibility_RelationType spi_type;
208
209   if (!is_initialized)
210     is_initialized = spi_init_relation_type_table (spi_relation_type_table);
211
212   if (type > ATK_RELATION_NULL && type < ATK_RELATION_LAST_DEFINED)
213     spi_type = spi_relation_type_table[type];
214   else
215     spi_type = Accessibility_RELATION_EXTENDED;
216   return spi_type;
217 }
218
219 static DBusMessage *
220 impl_GetRelationSet (DBusConnection * bus,
221                      DBusMessage * message, void *user_data)
222 {
223   AtkObject *object = (AtkObject *) user_data;
224   DBusMessage *reply;
225   AtkRelationSet *set;
226   DBusMessageIter iter, iter_array, iter_struct, iter_targets;
227   gint count;
228   gint i, j;
229
230   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
231                         droute_not_yet_handled_error (message));
232   reply = dbus_message_new_method_return (message);
233   if (!reply)
234     return NULL;
235   set = atk_object_ref_relation_set (object);
236   dbus_message_iter_init_append (reply, &iter);
237   if (!dbus_message_iter_open_container
238       (&iter, DBUS_TYPE_ARRAY, "(ua(so))", &iter_array))
239     {
240       goto oom;
241     }
242   count = atk_relation_set_get_n_relations (set);
243   for (i = 0; i < count; i++)
244     {
245       AtkRelation *r = atk_relation_set_get_relation (set, i);
246       AtkRelationType rt;
247       GPtrArray *target;
248       dbus_uint32_t type;
249       if (!r)
250         continue;
251       rt = atk_relation_get_relation_type (r);
252       type = spi_relation_type_from_atk_relation_type (rt);
253       target = atk_relation_get_target (r);
254       if (!dbus_message_iter_open_container
255           (&iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct))
256         {
257           goto oom;
258         }
259       dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &type);
260       if (!dbus_message_iter_open_container
261           (&iter_struct, DBUS_TYPE_ARRAY, "(so)", &iter_targets))
262         {
263           goto oom;
264         }
265       for (j = 0; j < target->len; j++)
266         {
267           AtkObject *obj = target->pdata[j];
268           char *path;
269           if (!obj)
270             continue;
271           spi_object_append_reference (&iter_targets, obj);
272         }
273       dbus_message_iter_close_container (&iter_struct, &iter_targets);
274       dbus_message_iter_close_container (&iter_array, &iter_struct);
275     }
276   dbus_message_iter_close_container (&iter, &iter_array);
277 oom:
278   // TODO: handle out of memory */
279   return reply;
280 }
281
282 static DBusMessage *
283 impl_GetRole (DBusConnection * bus, DBusMessage * message, void *user_data)
284 {
285   AtkObject *object = (AtkObject *) user_data;
286   gint role;
287   dbus_uint32_t rv;
288   DBusMessage *reply;
289
290   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
291                         droute_not_yet_handled_error (message));
292   role = atk_object_get_role (object);
293   rv = spi_accessible_role_from_atk_role (role);
294   reply = dbus_message_new_method_return (message);
295   if (reply)
296     {
297       dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
298                                 DBUS_TYPE_INVALID);
299     }
300   return reply;
301 }
302
303 static char *
304 impl_get_role_str (void *datum)
305 {
306   g_return_val_if_fail (ATK_IS_OBJECT (datum), g_strdup (""));
307   return g_strdup_printf ("%d",
308                           spi_accessible_role_from_atk_role
309                           (atk_object_get_role ((AtkObject *) datum)));
310 }
311
312 static DBusMessage *
313 impl_GetRoleName (DBusConnection * bus,
314                   DBusMessage * message, void *user_data)
315 {
316   AtkObject *object = (AtkObject *) user_data;
317   gint role;
318   const char *role_name;
319   DBusMessage *reply;
320
321   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
322                         droute_not_yet_handled_error (message));
323   role = atk_object_get_role (object);
324   role_name = atk_role_get_name (role);
325   if (!role_name)
326     role_name = "";
327   reply = dbus_message_new_method_return (message);
328   if (reply)
329     {
330       dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
331                                 DBUS_TYPE_INVALID);
332     }
333   return reply;
334 }
335
336 static DBusMessage *
337 impl_GetLocalizedRoleName (DBusConnection * bus,
338                            DBusMessage * message, void *user_data)
339 {
340   AtkObject *object = (AtkObject *) user_data;
341   gint role;
342   const char *role_name;
343   DBusMessage *reply;
344
345   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
346                         droute_not_yet_handled_error (message));
347   role = atk_object_get_role (object);
348   role_name = atk_role_get_localized_name (role);
349   if (!role_name)
350     role_name = "";
351   reply = dbus_message_new_method_return (message);
352   if (reply)
353     {
354       dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
355                                 DBUS_TYPE_INVALID);
356     }
357   return reply;
358 }
359
360 static DBusMessage *
361 impl_GetState (DBusConnection * bus, DBusMessage * message, void *user_data)
362 {
363   AtkObject *object = (AtkObject *) user_data;
364
365   DBusMessage *reply = NULL;
366   DBusMessageIter iter, iter_array;
367
368   dbus_uint32_t states[2];
369
370   guint count;
371
372   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
373                         droute_not_yet_handled_error (message));
374
375   reply = dbus_message_new_method_return (message);
376   dbus_message_iter_init_append (reply, &iter);
377
378   spi_atk_state_to_dbus_array (object, states);
379   dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "u", &iter_array);
380   for (count = 0; count < 2; count++)
381     {
382       dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_UINT32,
383                                       &states[count]);
384     }
385   dbus_message_iter_close_container (&iter, &iter_array);
386   return reply;
387 }
388
389 static DBusMessage *
390 impl_GetAttributes (DBusConnection * bus,
391                     DBusMessage * message, void *user_data)
392 {
393   AtkObject *object = (AtkObject *) user_data;
394   AtkAttributeSet *attributes;
395   DBusMessage *reply = NULL;
396   DBusMessageIter iter;
397
398   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
399                         droute_not_yet_handled_error (message));
400
401   attributes = atk_object_get_attributes (object);
402
403   reply = dbus_message_new_method_return (message);
404   dbus_message_iter_init_append (reply, &iter);
405   spi_object_append_attribute_set (&iter, attributes);
406
407   atk_attribute_set_free (attributes);
408
409   return reply;
410 }
411
412 static DBusMessage *
413 impl_GetApplication (DBusConnection * bus,
414                      DBusMessage * message, void *user_data)
415 {
416   AtkObject *root = atk_get_root ();
417   return spi_object_return_reference (message, root);
418 }
419
420 static DBusMessage *
421 impl_GetInterfaces (DBusConnection * bus,
422                     DBusMessage * message, void *user_data)
423 {
424   AtkObject *object = (AtkObject *) user_data;
425   gint role;
426   const char *role_name;
427   DBusMessage *reply;
428   DBusMessageIter iter, iter_array;
429
430   g_return_val_if_fail (ATK_IS_OBJECT (user_data),
431                         droute_not_yet_handled_error (message));
432   reply = dbus_message_new_method_return (message);
433   if (reply)
434     {
435       dbus_message_iter_init_append (reply, &iter);
436       dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s",
437                                         &iter_array);
438       spi_object_append_interfaces (&iter_array, object);
439       dbus_message_iter_close_container (&iter, &iter_array);
440     }
441   return reply;
442 }
443
444 static DBusMessage *
445 impl_Embedded (DBusConnection *bus,
446                     DBusMessage *message,
447                     void *user_data)
448 {
449   AtkObject *object = (AtkObject *) user_data;
450   char *path;
451   gchar *id;
452
453   if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID))
454     {
455       return droute_invalid_arguments_error (message);
456     }
457   id = g_object_get_data (G_OBJECT (object), "dbus-plug-parent");
458   if (id)
459     g_free (id);
460   id = g_strconcat (dbus_message_get_sender (message), ":", path, NULL);
461   g_object_set_data (G_OBJECT (object), "dbus-plug-parent", id);
462   return dbus_message_new_method_return (message);
463 }
464
465 static DRouteMethod methods[] = {
466   {impl_GetChildAtIndex, "GetChildAtIndex"},
467   {impl_GetChildren, "GetChildren"},
468   {impl_GetIndexInParent, "GetIndexInParent"},
469   {impl_GetRelationSet, "GetRelationSet"},
470   {impl_GetRole, "GetRole"},
471   {impl_GetRoleName, "GetRoleName"},
472   {impl_GetLocalizedRoleName, "GetLocalizedRoleName"},
473   {impl_GetState, "GetState"},
474   {impl_GetAttributes, "GetAttributes"},
475   {impl_GetApplication, "GetApplication"},
476   {impl_GetInterfaces, "GetInterfaces"},
477   {impl_Embedded, "Embedded"},
478   {NULL, NULL}
479 };
480
481 static DRouteProperty properties[] = {
482   {impl_get_Name, impl_set_Name, "Name"},
483   {impl_get_Description, impl_set_Description, "Description"},
484   {impl_get_Parent, NULL, "Parent"},
485   {impl_get_ChildCount, NULL, "ChildCount"},
486   {NULL, NULL, NULL}
487 };
488
489 void
490 spi_initialize_accessible (DRoutePath * path)
491 {
492   droute_path_add_interface (path,
493                              SPI_DBUS_INTERFACE_ACCESSIBLE,
494                              methods, properties);
495 };