Modify the paths scheme.
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / object.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 2008, 2009, 2010 Codethink Ltd.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /*
25  * This module contains utility functions for exporting AT-SPI
26  * objects based upon an ATK object.
27  *
28  * It incudes functions for marshalling object references
29  * and supported interfaces to a D-Bus message.
30  */
31
32 #include <atk/atk.h>
33 #include <common/spi-types.h>
34 #include <common/spi-dbus.h>
35
36 #include "accessible-register.h"
37 #include "accessible-cache.h"
38 #include "accessible-leasing.h"
39
40 #include "bridge.h"
41
42 /*---------------------------------------------------------------------------*/
43
44 /*
45  * This is the all important function that decides whether an object should
46  * be leased or not.
47  *
48  * The choice of algorithm for this is somewhat vuage. We want ideally to lease
49  * all atk objects that are not owned by their parent.
50  *
51  * The 'cache' object attempts to cache all objects that are owned by their
52  * parent by traversing the tree of accessibles, ignoring the children of
53  * manages-descendants and transient objects.
54  *
55  * This function will simply look for all the accessibles that the cache object
56  * has not found and assume that they need to be leased.
57  */
58 static void
59 maybe_lease (AtkObject *obj)
60 {
61   if (!spi_cache_in (spi_global_cache, G_OBJECT (obj)))
62     {
63       spi_leasing_take (spi_global_leasing, G_OBJECT (obj));
64     }
65 }
66
67 /*---------------------------------------------------------------------------*/
68
69 /*
70  * It is assumed that all of these functions are returning an accessible
71  * object to the client side.
72  *
73  * All of them will lease the AtkObject if it is deemed neccessary.
74  */
75
76 void
77 spi_object_append_reference (DBusMessageIter * iter, AtkObject * obj)
78 {
79   DBusMessageIter iter_struct;
80   const gchar *name;
81   gchar *path;
82
83   maybe_lease (obj);
84
85   name = dbus_bus_get_unique_name (spi_global_app_data->bus);
86   path = spi_register_object_to_path (spi_global_register, G_OBJECT (obj));
87
88   if (!path)
89     path = g_strdup (SPI_DBUS_PATH_NULL);
90
91   dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
92                                     &iter_struct);
93   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
94   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
95   dbus_message_iter_close_container (iter, &iter_struct);
96   
97   g_free (path);
98 }
99
100 void
101 spi_object_append_v_reference (DBusMessageIter * iter, AtkObject * obj)
102 {
103   DBusMessageIter iter_variant;
104
105   dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "(so)",
106                                     &iter_variant);
107      spi_object_append_reference (&iter_variant, obj);
108   dbus_message_iter_close_container (iter, &iter_variant);
109 }
110
111 void
112 spi_object_append_desktop_reference (DBusMessageIter * iter)
113 {
114   DBusMessageIter iter_struct;
115   const char *name = SPI_DBUS_NAME_REGISTRY;
116   const char *path = SPI_DBUS_PATH_ROOT;
117
118   dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
119                                     &iter_struct);
120   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
121   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
122   dbus_message_iter_close_container (iter, &iter_struct);
123 }
124
125 void
126 spi_object_append_null_reference (DBusMessageIter * iter)
127 {
128   DBusMessageIter iter_struct;
129   const char *name;
130   const char *path = "/org/at_spi/null";
131
132   name = dbus_bus_get_unique_name (spi_global_app_data->bus);
133
134   dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
135                                     &iter_struct);
136   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
137   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
138   dbus_message_iter_close_container (iter, &iter_struct);
139 }
140
141 DBusMessage *
142 spi_object_return_reference (DBusMessage * msg, AtkObject * obj)
143 {
144   DBusMessage *reply;
145
146   reply = dbus_message_new_method_return (msg);
147   if (reply)
148     {
149       DBusMessageIter iter;
150       dbus_message_iter_init_append (reply, &iter);
151       spi_object_append_reference (&iter, obj);
152     }
153   g_object_unref (G_OBJECT (obj));
154
155   return reply;
156 }
157
158 /*---------------------------------------------------------------------------*/
159
160 void
161 spi_object_append_interfaces (DBusMessageIter * iter, AtkObject * obj)
162 {
163   const gchar *itf;
164
165   itf = SPI_DBUS_INTERFACE_ACCESSIBLE;
166   dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
167
168   if (ATK_IS_ACTION (obj))
169     {
170       itf = SPI_DBUS_INTERFACE_ACTION;
171       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
172     }
173
174   if (ATK_IS_COMPONENT (obj))
175     {
176       itf = SPI_DBUS_INTERFACE_COMPONENT;
177       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
178     }
179
180   if (ATK_IS_EDITABLE_TEXT (obj))
181     {
182       itf = SPI_DBUS_INTERFACE_EDITABLE_TEXT;
183       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
184     }
185
186   if (ATK_IS_TEXT (obj))
187     {
188       itf = SPI_DBUS_INTERFACE_TEXT;
189       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
190     }
191
192   if (ATK_IS_HYPERTEXT (obj))
193     {
194       itf = SPI_DBUS_INTERFACE_HYPERTEXT;
195       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
196     }
197
198   if (ATK_IS_IMAGE (obj))
199     {
200       itf = SPI_DBUS_INTERFACE_IMAGE;
201       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
202     }
203
204   if (ATK_IS_SELECTION (obj))
205     {
206       itf = SPI_DBUS_INTERFACE_SELECTION;
207       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
208     }
209
210   if (ATK_IS_TABLE (obj))
211     {
212       itf = SPI_DBUS_INTERFACE_TABLE;
213       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
214     }
215
216   if (ATK_IS_VALUE (obj))
217     {
218       itf = SPI_DBUS_INTERFACE_VALUE;
219       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
220     }
221
222   if (ATK_IS_STREAMABLE_CONTENT (obj))
223     {
224       itf = "org.freedesktop.atspi.StreamableContent";
225       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
226     }
227
228   if (ATK_IS_DOCUMENT (obj))
229     {
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);
234     }
235
236   if (ATK_IS_HYPERLINK_IMPL (obj))
237     {
238       itf = SPI_DBUS_INTERFACE_HYPERLINK;
239       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
240     }
241 }
242
243 /*---------------------------------------------------------------------------*/
244
245 void
246 spi_object_append_attribute_set (DBusMessageIter * iter, AtkAttributeSet * attr)
247 {
248   DBusMessageIter dictIter;
249
250   dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{ss}", &dictIter);
251   while (attr)
252     {
253       DBusMessageIter dictEntryIter;
254       AtkAttribute *attribute = (AtkAttribute *) attr->data;
255       const char *key = attribute->name;
256       const char *value = attribute->value;
257
258       if (key == NULL)
259         key = "";
260       if (value == NULL)
261         value = "";
262
263       dbus_message_iter_open_container (&dictIter, DBUS_TYPE_DICT_ENTRY, NULL,
264                                         &dictEntryIter);
265       dbus_message_iter_append_basic (&dictEntryIter, DBUS_TYPE_STRING,
266                                       &key);
267       dbus_message_iter_append_basic (&dictEntryIter, DBUS_TYPE_STRING,
268                                       &value);
269       dbus_message_iter_close_container (&dictIter, &dictEntryIter);
270       attr = g_slist_next (attr);
271     }
272   dbus_message_iter_close_container (iter, &dictIter);
273 }
274
275 /*---------------------------------------------------------------------------*/
276
277 static gboolean
278 init_role_lookup_table (Accessibility_Role * role_table)
279 {
280   int i;
281   /* if it's not in the list below, dunno what it is */
282   for (i = 0; i < ATK_ROLE_LAST_DEFINED; ++i)
283     {
284       role_table[i] = Accessibility_ROLE_UNKNOWN;
285     }
286
287   role_table[ATK_ROLE_INVALID] = Accessibility_ROLE_INVALID;
288   role_table[ATK_ROLE_ACCEL_LABEL] = Accessibility_ROLE_ACCELERATOR_LABEL;
289   role_table[ATK_ROLE_ALERT] = Accessibility_ROLE_ALERT;
290   role_table[ATK_ROLE_ANIMATION] = Accessibility_ROLE_ANIMATION;
291   role_table[ATK_ROLE_ARROW] = Accessibility_ROLE_ARROW;
292   role_table[ATK_ROLE_CALENDAR] = Accessibility_ROLE_CALENDAR;
293   role_table[ATK_ROLE_CANVAS] = Accessibility_ROLE_CANVAS;
294   role_table[ATK_ROLE_CHECK_BOX] = Accessibility_ROLE_CHECK_BOX;
295   role_table[ATK_ROLE_CHECK_MENU_ITEM] = Accessibility_ROLE_CHECK_MENU_ITEM;
296   role_table[ATK_ROLE_COLOR_CHOOSER] = Accessibility_ROLE_COLOR_CHOOSER;
297   role_table[ATK_ROLE_COLUMN_HEADER] = Accessibility_ROLE_COLUMN_HEADER;
298   role_table[ATK_ROLE_COMBO_BOX] = Accessibility_ROLE_COMBO_BOX;
299   role_table[ATK_ROLE_DATE_EDITOR] = Accessibility_ROLE_DATE_EDITOR;
300   role_table[ATK_ROLE_DESKTOP_ICON] = Accessibility_ROLE_DESKTOP_ICON;
301   role_table[ATK_ROLE_DESKTOP_FRAME] = Accessibility_ROLE_DESKTOP_FRAME;
302   role_table[ATK_ROLE_DIAL] = Accessibility_ROLE_DIAL;
303   role_table[ATK_ROLE_DIALOG] = Accessibility_ROLE_DIALOG;
304   role_table[ATK_ROLE_DIRECTORY_PANE] = Accessibility_ROLE_DIRECTORY_PANE;
305   role_table[ATK_ROLE_DRAWING_AREA] = Accessibility_ROLE_DRAWING_AREA;
306   role_table[ATK_ROLE_FILE_CHOOSER] = Accessibility_ROLE_FILE_CHOOSER;
307   role_table[ATK_ROLE_FILLER] = Accessibility_ROLE_FILLER;
308   role_table[ATK_ROLE_FONT_CHOOSER] = Accessibility_ROLE_FONT_CHOOSER;
309   role_table[ATK_ROLE_FRAME] = Accessibility_ROLE_FRAME;
310   role_table[ATK_ROLE_GLASS_PANE] = Accessibility_ROLE_GLASS_PANE;
311   role_table[ATK_ROLE_HTML_CONTAINER] = Accessibility_ROLE_HTML_CONTAINER;
312   role_table[ATK_ROLE_ICON] = Accessibility_ROLE_ICON;
313   role_table[ATK_ROLE_IMAGE] = Accessibility_ROLE_IMAGE;
314   role_table[ATK_ROLE_INTERNAL_FRAME] = Accessibility_ROLE_INTERNAL_FRAME;
315   role_table[ATK_ROLE_LABEL] = Accessibility_ROLE_LABEL;
316   role_table[ATK_ROLE_LAYERED_PANE] = Accessibility_ROLE_LAYERED_PANE;
317   role_table[ATK_ROLE_LIST] = Accessibility_ROLE_LIST;
318   role_table[ATK_ROLE_LIST_ITEM] = Accessibility_ROLE_LIST_ITEM;
319   role_table[ATK_ROLE_MENU] = Accessibility_ROLE_MENU;
320   role_table[ATK_ROLE_MENU_BAR] = Accessibility_ROLE_MENU_BAR;
321   role_table[ATK_ROLE_MENU_ITEM] = Accessibility_ROLE_MENU_ITEM;
322   role_table[ATK_ROLE_OPTION_PANE] = Accessibility_ROLE_OPTION_PANE;
323   role_table[ATK_ROLE_PAGE_TAB] = Accessibility_ROLE_PAGE_TAB;
324   role_table[ATK_ROLE_PAGE_TAB_LIST] = Accessibility_ROLE_PAGE_TAB_LIST;
325   role_table[ATK_ROLE_PANEL] = Accessibility_ROLE_PANEL;
326   role_table[ATK_ROLE_PASSWORD_TEXT] = Accessibility_ROLE_PASSWORD_TEXT;
327   role_table[ATK_ROLE_POPUP_MENU] = Accessibility_ROLE_POPUP_MENU;
328   role_table[ATK_ROLE_PROGRESS_BAR] = Accessibility_ROLE_PROGRESS_BAR;
329   role_table[ATK_ROLE_PUSH_BUTTON] = Accessibility_ROLE_PUSH_BUTTON;
330   role_table[ATK_ROLE_RADIO_BUTTON] = Accessibility_ROLE_RADIO_BUTTON;
331   role_table[ATK_ROLE_RADIO_MENU_ITEM] = Accessibility_ROLE_RADIO_MENU_ITEM;
332   role_table[ATK_ROLE_ROOT_PANE] = Accessibility_ROLE_ROOT_PANE;
333   role_table[ATK_ROLE_ROW_HEADER] = Accessibility_ROLE_ROW_HEADER;
334   role_table[ATK_ROLE_SCROLL_BAR] = Accessibility_ROLE_SCROLL_BAR;
335   role_table[ATK_ROLE_SCROLL_PANE] = Accessibility_ROLE_SCROLL_PANE;
336   role_table[ATK_ROLE_SEPARATOR] = Accessibility_ROLE_SEPARATOR;
337   role_table[ATK_ROLE_SLIDER] = Accessibility_ROLE_SLIDER;
338   role_table[ATK_ROLE_SPIN_BUTTON] = Accessibility_ROLE_SPIN_BUTTON;
339   role_table[ATK_ROLE_SPLIT_PANE] = Accessibility_ROLE_SPLIT_PANE;
340   role_table[ATK_ROLE_STATUSBAR] = Accessibility_ROLE_STATUS_BAR;
341   role_table[ATK_ROLE_TABLE] = Accessibility_ROLE_TABLE;
342   role_table[ATK_ROLE_TABLE_CELL] = Accessibility_ROLE_TABLE_CELL;
343   role_table[ATK_ROLE_TABLE_COLUMN_HEADER] =
344     Accessibility_ROLE_TABLE_COLUMN_HEADER;
345   role_table[ATK_ROLE_TABLE_ROW_HEADER] = Accessibility_ROLE_TABLE_ROW_HEADER;
346   role_table[ATK_ROLE_TEAR_OFF_MENU_ITEM] =
347     Accessibility_ROLE_TEAROFF_MENU_ITEM;
348   role_table[ATK_ROLE_TERMINAL] = Accessibility_ROLE_TERMINAL;
349   role_table[ATK_ROLE_TEXT] = Accessibility_ROLE_TEXT;
350   role_table[ATK_ROLE_TOGGLE_BUTTON] = Accessibility_ROLE_TOGGLE_BUTTON;
351   role_table[ATK_ROLE_TOOL_BAR] = Accessibility_ROLE_TOOL_BAR;
352   role_table[ATK_ROLE_TOOL_TIP] = Accessibility_ROLE_TOOL_TIP;
353   role_table[ATK_ROLE_TREE] = Accessibility_ROLE_TREE;
354   role_table[ATK_ROLE_TREE_TABLE] = Accessibility_ROLE_TREE_TABLE;
355   role_table[ATK_ROLE_UNKNOWN] = Accessibility_ROLE_UNKNOWN;
356   role_table[ATK_ROLE_VIEWPORT] = Accessibility_ROLE_VIEWPORT;
357   role_table[ATK_ROLE_WINDOW] = Accessibility_ROLE_WINDOW;
358   role_table[ATK_ROLE_HEADER] = Accessibility_ROLE_HEADER;
359   role_table[ATK_ROLE_FOOTER] = Accessibility_ROLE_FOOTER;
360   role_table[ATK_ROLE_PARAGRAPH] = Accessibility_ROLE_PARAGRAPH;
361   role_table[ATK_ROLE_RULER] = Accessibility_ROLE_RULER;
362   role_table[ATK_ROLE_APPLICATION] = Accessibility_ROLE_APPLICATION;
363   role_table[ATK_ROLE_AUTOCOMPLETE] = Accessibility_ROLE_AUTOCOMPLETE;
364   role_table[ATK_ROLE_EDITBAR] = Accessibility_ROLE_EDITBAR;
365   role_table[ATK_ROLE_EMBEDDED] = Accessibility_ROLE_EMBEDDED;
366   role_table[ATK_ROLE_ENTRY] = Accessibility_ROLE_ENTRY;
367   role_table[ATK_ROLE_CHART] = Accessibility_ROLE_CHART;
368   role_table[ATK_ROLE_CAPTION] = Accessibility_ROLE_CAPTION;
369   role_table[ATK_ROLE_DOCUMENT_FRAME] = Accessibility_ROLE_DOCUMENT_FRAME;
370   role_table[ATK_ROLE_HEADING] = Accessibility_ROLE_HEADING;
371   role_table[ATK_ROLE_PAGE] = Accessibility_ROLE_PAGE;
372   role_table[ATK_ROLE_SECTION] = Accessibility_ROLE_SECTION;
373   role_table[ATK_ROLE_FORM] = Accessibility_ROLE_FORM;
374   role_table[ATK_ROLE_REDUNDANT_OBJECT] = Accessibility_ROLE_REDUNDANT_OBJECT;
375   role_table[ATK_ROLE_LINK] = Accessibility_ROLE_LINK;
376   role_table[ATK_ROLE_INPUT_METHOD_WINDOW] =
377     Accessibility_ROLE_INPUT_METHOD_WINDOW;
378   return TRUE;
379 }
380
381 Accessibility_Role
382 spi_accessible_role_from_atk_role (AtkRole role)
383 {
384   static gboolean is_initialized = FALSE;
385   static Accessibility_Role spi_role_table[ATK_ROLE_LAST_DEFINED];
386   Accessibility_Role spi_role;
387
388   if (!is_initialized)
389     {
390       is_initialized = init_role_lookup_table (spi_role_table);
391     }
392
393   if (role >= 0 && role < ATK_ROLE_LAST_DEFINED)
394     {
395       spi_role = spi_role_table[role];
396     }
397   else
398     {
399       spi_role = Accessibility_ROLE_EXTENDED;
400     }
401   return spi_role;
402 }
403
404 /*END------------------------------------------------------------------------*/