source: trunk/third/at-spi/libspi/accessible.c @ 18422

Revision 18422, 18.7 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18421, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * AT-SPI - Assistive Technology Service Provider Interface
3 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4 *
5 * Copyright 2001 Sun Microsystems 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/* accessible.c: the core of the accessibility implementation */
24
25#include <config.h>
26#include <stdio.h>
27#include <bonobo/bonobo-exception.h>
28#include <atk/atk.h>
29#include <libspi/libspi.h>
30
31/* Our parent Gtk object type  */
32#define PARENT_TYPE SPI_TYPE_BASE
33
34static gboolean spi_init_role_lookup_table (Accessibility_Role *role_table);
35static Accessibility_Role spi_role_from_atk_role (AtkRole role);
36
37static gboolean
38spi_init_role_lookup_table (Accessibility_Role *role_table)
39{
40  int i;
41  /* if it's not in the list below, dunno what it is */
42  for (i = 0; i < ATK_ROLE_LAST_DEFINED; ++i)
43    {
44      role_table [i] = Accessibility_ROLE_UNKNOWN;
45    }
46 
47  role_table [ATK_ROLE_INVALID] =          Accessibility_ROLE_INVALID;
48  role_table [ATK_ROLE_ACCEL_LABEL] =      Accessibility_ROLE_ACCELERATOR_LABEL;
49  role_table [ATK_ROLE_ALERT] =            Accessibility_ROLE_ALERT;
50  role_table [ATK_ROLE_ANIMATION] =        Accessibility_ROLE_ANIMATION;
51  role_table [ATK_ROLE_ARROW] =            Accessibility_ROLE_ARROW;
52  role_table [ATK_ROLE_CALENDAR] =         Accessibility_ROLE_CALENDAR;
53  role_table [ATK_ROLE_CANVAS] =           Accessibility_ROLE_CANVAS;
54  role_table [ATK_ROLE_CHECK_BOX] =        Accessibility_ROLE_CHECK_BOX;
55  role_table [ATK_ROLE_CHECK_MENU_ITEM] =  Accessibility_ROLE_CHECK_MENU_ITEM;
56  role_table [ATK_ROLE_COLOR_CHOOSER] =    Accessibility_ROLE_COLOR_CHOOSER;
57  role_table [ATK_ROLE_COLUMN_HEADER] =    Accessibility_ROLE_COLUMN_HEADER;
58  role_table [ATK_ROLE_COMBO_BOX] =        Accessibility_ROLE_COMBO_BOX;
59  role_table [ATK_ROLE_DATE_EDITOR] =      Accessibility_ROLE_DATE_EDITOR;
60  role_table [ATK_ROLE_DESKTOP_ICON] =     Accessibility_ROLE_DESKTOP_ICON;
61  role_table [ATK_ROLE_DESKTOP_FRAME] =    Accessibility_ROLE_DESKTOP_FRAME;
62  role_table [ATK_ROLE_DIAL] =             Accessibility_ROLE_DIAL;
63  role_table [ATK_ROLE_DIALOG] =           Accessibility_ROLE_DIALOG;
64  role_table [ATK_ROLE_DIRECTORY_PANE] =   Accessibility_ROLE_DIRECTORY_PANE;
65  role_table [ATK_ROLE_DRAWING_AREA] =     Accessibility_ROLE_DRAWING_AREA;
66  role_table [ATK_ROLE_FILE_CHOOSER] =     Accessibility_ROLE_FILE_CHOOSER;
67  role_table [ATK_ROLE_FILLER] =           Accessibility_ROLE_FILLER;
68  role_table [ATK_ROLE_FONT_CHOOSER] =     Accessibility_ROLE_FONT_CHOOSER;
69  role_table [ATK_ROLE_FRAME] =            Accessibility_ROLE_FRAME;
70  role_table [ATK_ROLE_GLASS_PANE] =       Accessibility_ROLE_GLASS_PANE;
71  role_table [ATK_ROLE_HTML_CONTAINER] =   Accessibility_ROLE_HTML_CONTAINER;
72  role_table [ATK_ROLE_ICON] =             Accessibility_ROLE_ICON;
73  role_table [ATK_ROLE_IMAGE] =            Accessibility_ROLE_IMAGE;
74  role_table [ATK_ROLE_INTERNAL_FRAME] =   Accessibility_ROLE_INTERNAL_FRAME;
75  role_table [ATK_ROLE_LABEL] =            Accessibility_ROLE_LABEL;
76  role_table [ATK_ROLE_LAYERED_PANE] =     Accessibility_ROLE_LAYERED_PANE;
77  role_table [ATK_ROLE_LIST] =             Accessibility_ROLE_LIST;
78  role_table [ATK_ROLE_LIST_ITEM] =        Accessibility_ROLE_LIST_ITEM;
79  role_table [ATK_ROLE_MENU] =             Accessibility_ROLE_MENU;
80  role_table [ATK_ROLE_MENU_BAR] =         Accessibility_ROLE_MENU_BAR;
81  role_table [ATK_ROLE_MENU_ITEM] =        Accessibility_ROLE_MENU_ITEM;
82  role_table [ATK_ROLE_OPTION_PANE] =      Accessibility_ROLE_OPTION_PANE;
83  role_table [ATK_ROLE_PAGE_TAB] =         Accessibility_ROLE_PAGE_TAB;
84  role_table [ATK_ROLE_PAGE_TAB_LIST] =    Accessibility_ROLE_PAGE_TAB_LIST;
85  role_table [ATK_ROLE_PANEL] =            Accessibility_ROLE_PANEL;
86  role_table [ATK_ROLE_PASSWORD_TEXT] =    Accessibility_ROLE_PASSWORD_TEXT;
87  role_table [ATK_ROLE_POPUP_MENU] =       Accessibility_ROLE_POPUP_MENU;
88  role_table [ATK_ROLE_PROGRESS_BAR] =     Accessibility_ROLE_PROGRESS_BAR;
89  role_table [ATK_ROLE_PUSH_BUTTON] =      Accessibility_ROLE_PUSH_BUTTON;
90  role_table [ATK_ROLE_RADIO_BUTTON] =     Accessibility_ROLE_RADIO_BUTTON;
91  role_table [ATK_ROLE_RADIO_MENU_ITEM] =  Accessibility_ROLE_RADIO_MENU_ITEM;
92  role_table [ATK_ROLE_ROOT_PANE] =        Accessibility_ROLE_ROOT_PANE;
93  role_table [ATK_ROLE_ROW_HEADER] =       Accessibility_ROLE_ROW_HEADER;
94  role_table [ATK_ROLE_SCROLL_BAR] =       Accessibility_ROLE_SCROLL_BAR;
95  role_table [ATK_ROLE_SCROLL_PANE] =      Accessibility_ROLE_SCROLL_PANE;
96  role_table [ATK_ROLE_SEPARATOR] =        Accessibility_ROLE_SEPARATOR;
97  role_table [ATK_ROLE_SLIDER] =           Accessibility_ROLE_SLIDER;
98  role_table [ATK_ROLE_SPIN_BUTTON] =      Accessibility_ROLE_SPIN_BUTTON;
99  role_table [ATK_ROLE_SPLIT_PANE] =       Accessibility_ROLE_SPLIT_PANE;
100  role_table [ATK_ROLE_STATUSBAR] =        Accessibility_ROLE_STATUS_BAR;
101  role_table [ATK_ROLE_TABLE] =            Accessibility_ROLE_TABLE;
102  role_table [ATK_ROLE_TABLE_CELL] =       Accessibility_ROLE_TABLE_CELL;
103  role_table [ATK_ROLE_TABLE_COLUMN_HEADER] = Accessibility_ROLE_COLUMN_HEADER;
104  role_table [ATK_ROLE_TABLE_ROW_HEADER] = Accessibility_ROLE_ROW_HEADER;
105  role_table [ATK_ROLE_TEAR_OFF_MENU_ITEM] = Accessibility_ROLE_TEAROFF_MENU_ITEM;
106  role_table [ATK_ROLE_TERMINAL] =         Accessibility_ROLE_TERMINAL;
107  role_table [ATK_ROLE_TEXT] =             Accessibility_ROLE_TEXT;
108  role_table [ATK_ROLE_TOGGLE_BUTTON] =    Accessibility_ROLE_TOGGLE_BUTTON;
109  role_table [ATK_ROLE_TOOL_BAR] =         Accessibility_ROLE_TOOL_BAR;
110  role_table [ATK_ROLE_TOOL_TIP] =         Accessibility_ROLE_TOOL_TIP;
111  role_table [ATK_ROLE_TREE] =             Accessibility_ROLE_TREE;
112  role_table [ATK_ROLE_TREE_TABLE] =       Accessibility_ROLE_TREE_TABLE;
113  role_table [ATK_ROLE_UNKNOWN] =          Accessibility_ROLE_UNKNOWN;
114  role_table [ATK_ROLE_VIEWPORT] =         Accessibility_ROLE_VIEWPORT;
115  role_table [ATK_ROLE_WINDOW] =           Accessibility_ROLE_WINDOW;
116  role_table [ATK_ROLE_LAST_DEFINED] =     Accessibility_ROLE_EXTENDED;
117 
118  return TRUE;
119}
120
121static Accessibility_Role
122spi_role_from_atk_role (AtkRole role)
123{
124  static gboolean is_initialized = FALSE;
125  static Accessibility_Role spi_role_table [ATK_ROLE_LAST_DEFINED];
126  Accessibility_Role spi_role;
127
128  if (!is_initialized)
129   {
130     is_initialized = spi_init_role_lookup_table (spi_role_table);         
131   }
132
133  if (role >= 0 && role < ATK_ROLE_LAST_DEFINED)
134    {
135      spi_role = spi_role_table [role];
136    }
137  else
138    {
139      spi_role = Accessibility_ROLE_EXTENDED;       
140    }
141  return spi_role;
142}
143
144static AtkObject *
145get_atkobject_from_servant (PortableServer_Servant servant)
146{
147  SpiBase *object = SPI_BASE (bonobo_object_from_servant (servant));
148
149  g_return_val_if_fail (object, NULL);
150  g_return_val_if_fail (ATK_IS_OBJECT(object->gobj), NULL);
151  return ATK_OBJECT(object->gobj);
152}
153
154/*
155 * CORBA Accessibility::Accessible::get_name method implementation
156 */
157static CORBA_char *
158impl_accessibility_accessible_get_name (PortableServer_Servant servant,
159                                        CORBA_Environment     *ev)
160{
161  const gchar *name;
162  CORBA_char  *retval;
163  AtkObject   *object = get_atkobject_from_servant (servant);
164
165  g_return_val_if_fail (object != NULL, CORBA_string_dup (""));
166
167  name = atk_object_get_name (object);
168
169  if (name)
170    {
171      retval = CORBA_string_dup (name);
172    }
173  else
174    {
175      retval = CORBA_string_dup ("");
176    }
177
178  return retval;
179}
180
181/*
182 * CORBA Accessibility::Accessible::set_name method implementation
183 */
184static void
185impl_accessibility_accessible_set_name (PortableServer_Servant servant,
186                                        const CORBA_char      *name,
187                                        CORBA_Environment     *ev)
188{
189  AtkObject *object = get_atkobject_from_servant (servant);
190
191  g_return_if_fail (object != NULL);
192
193  atk_object_set_name (object, name);
194}
195
196/*
197 * CORBA Accessibility::Accessible::get_description method implementation
198 */
199static CORBA_char *
200impl_accessibility_accessible_get_description (PortableServer_Servant servant,
201                                               CORBA_Environment     *ev)
202{
203  const gchar *descr;
204  CORBA_char  *retval;
205  AtkObject   *object = get_atkobject_from_servant (servant);
206
207  g_return_val_if_fail (object != NULL, CORBA_string_dup (""));
208
209  descr = atk_object_get_description (object);
210
211  if (descr)
212    {
213      retval = CORBA_string_dup (descr);
214    }
215  else
216    {
217      retval = CORBA_string_dup ("");
218    }
219
220  return retval;
221}
222
223/*
224 * CORBA Accessibility::Accessible::set_description method implementation
225 */
226static void
227impl_accessibility_accessible_set_description (PortableServer_Servant servant,
228                                               const CORBA_char      *descr,
229                                               CORBA_Environment     *ev)
230{
231  AtkObject *object = get_atkobject_from_servant (servant);
232
233  g_return_if_fail (object != NULL);
234
235  atk_object_set_description (object, descr);
236}
237
238/*
239 * CORBA Accessibility::Accessible::get_parent method implementation
240 */
241static Accessibility_Accessible
242impl_accessibility_accessible_get_parent (PortableServer_Servant servant,
243                                          CORBA_Environment     *ev)
244{
245  AtkObject *parent;
246  AtkObject *object = get_atkobject_from_servant (servant);
247
248  g_return_val_if_fail (object != NULL, CORBA_OBJECT_NIL);
249
250  parent = atk_object_get_parent (object);
251
252  return spi_accessible_new_return (parent, FALSE, ev);
253}
254
255/*
256 * CORBA Accessibility::Accessible::get_IndexInParent method implementation
257 */
258static CORBA_long
259impl_accessibility_accessible_get_index_in_parent (PortableServer_Servant servant,
260                                                   CORBA_Environment     *ev)
261{
262  AtkObject *object = get_atkobject_from_servant (servant);
263
264  g_return_val_if_fail (object != NULL, -1);
265
266  return atk_object_get_index_in_parent (object);
267}
268
269/*
270 * CORBA Accessibility::Accessible::get_childCount method implementation
271 */
272static CORBA_long
273impl_accessibility_accessible_get_child_count (PortableServer_Servant servant,
274                                               CORBA_Environment     *ev)
275{
276  AtkObject *object = get_atkobject_from_servant (servant);
277
278  g_return_val_if_fail (object != NULL, 0);
279
280  return atk_object_get_n_accessible_children (object);
281}
282
283/*
284 * CORBA Accessibility::Accessible::getChildAtIndex method implementation
285 */
286static Accessibility_Accessible
287impl_accessibility_accessible_get_child_at_index (PortableServer_Servant servant,
288                                                  const CORBA_long      index,
289                                                  CORBA_Environment     *ev)
290{
291  AtkObject *child;
292  AtkObject *object = get_atkobject_from_servant (servant);
293
294  g_return_val_if_fail (object != NULL, CORBA_OBJECT_NIL);
295
296  child = atk_object_ref_accessible_child (object, index);
297
298  return spi_accessible_new_return (child, TRUE, ev);
299}
300
301/*
302 * CORBA Accessibility::Accessible::getState method implementation
303 */
304static Accessibility_StateSet
305impl_accessibility_accessible_get_state (PortableServer_Servant servant,
306                                         CORBA_Environment     *ev)
307{
308  AtkObject *object = get_atkobject_from_servant (servant);
309  AtkStateSet *atk_set;
310  SpiStateSet *set;
311  Accessibility_StateSet retval;
312
313  bonobo_return_val_if_fail (object != NULL, NULL, ev);
314
315  atk_set = atk_object_ref_state_set (object);
316 
317  set = spi_state_set_new (atk_set);
318  retval = bonobo_object_dup_ref (
319                                  BONOBO_OBJREF(set),
320                                  ev);
321
322  return retval;
323}
324
325/*
326 * CORBA Accessibility::Accessible::getRelationSet method implementation
327 */
328static Accessibility_RelationSet *
329impl_accessibility_accessible_get_relation_set (PortableServer_Servant servant,
330                                                CORBA_Environment     *ev)
331{
332  Accessibility_RelationSet *retval;
333  gint n_relations;
334  gint i;
335  AtkRelationSet *relation_set;
336  AtkObject      *object = get_atkobject_from_servant (servant);
337
338  bonobo_return_val_if_fail (object != NULL, NULL, ev);
339
340  relation_set = atk_object_ref_relation_set (object);
341
342  n_relations = atk_relation_set_get_n_relations (relation_set);
343
344  retval = CORBA_sequence_Accessibility_Relation__alloc ();
345  retval->_length = retval->_maximum = n_relations;
346  retval->_buffer = CORBA_sequence_Accessibility_Relation_allocbuf (n_relations);
347  CORBA_sequence_set_release (retval, CORBA_TRUE);
348         
349  for (i = 0; i < n_relations; ++i)
350    {
351      retval->_buffer[i] =
352        bonobo_object_dup_ref (
353          BONOBO_OBJREF (
354            spi_relation_new (atk_relation_set_get_relation (relation_set, i))),
355          ev);
356    }
357 
358  return retval;
359}
360
361/*
362 * CORBA Accessibility::Accessible::getRole method implementation
363 */
364static Accessibility_Role
365impl_accessibility_accessible_get_role (PortableServer_Servant servant,
366                                        CORBA_Environment     *ev)
367{
368  AtkRole            role;
369  Accessibility_Role retval;
370  AtkObject         *object = get_atkobject_from_servant (servant);
371
372  g_return_val_if_fail (object != NULL, 0);
373
374  role = atk_object_get_role (object);
375  retval = spi_role_from_atk_role (role);
376
377  return retval;
378}
379
380/*
381 * CORBA Accessibility::Accessible::getRole method implementation
382 */
383static CORBA_char *
384impl_accessibility_accessible_get_role_name (PortableServer_Servant servant,
385                                             CORBA_Environment     *ev)
386{
387  const gchar     *role_name;
388  AtkRole    role;
389  AtkObject *object = get_atkobject_from_servant (servant);
390
391  g_return_val_if_fail (object != NULL, 0);
392
393  role = atk_object_get_role (object);
394
395  role_name = atk_role_get_name (role);
396  if (role_name)
397    return CORBA_string_dup (role_name);
398  else
399    return CORBA_string_dup ("");
400}
401
402static void
403spi_accessible_class_init (SpiAccessibleClass *klass)
404{
405        POA_Accessibility_Accessible__epv *epv = &klass->epv;
406
407        epv->_get_name = impl_accessibility_accessible_get_name;
408        epv->_set_name = impl_accessibility_accessible_set_name;
409        epv->_get_description = impl_accessibility_accessible_get_description;
410        epv->_set_description = impl_accessibility_accessible_set_description;
411
412        epv->_get_parent = impl_accessibility_accessible_get_parent;
413        epv->_get_childCount = impl_accessibility_accessible_get_child_count;
414        epv->getChildAtIndex = impl_accessibility_accessible_get_child_at_index;
415        epv->getIndexInParent = impl_accessibility_accessible_get_index_in_parent;
416
417        epv->getRelationSet = impl_accessibility_accessible_get_relation_set;
418        epv->getState = impl_accessibility_accessible_get_state;
419        epv->getRole = impl_accessibility_accessible_get_role;
420        epv->getRoleName = impl_accessibility_accessible_get_role_name;
421}
422
423static void
424spi_accessible_init (SpiAccessible *accessible)
425{
426}
427
428BONOBO_TYPE_FUNC_FULL (SpiAccessible,
429                       Accessibility_Accessible,
430                       PARENT_TYPE,
431                       spi_accessible);
432
433static GHashTable *public_corba_refs = NULL;
434
435static GHashTable *
436get_public_refs (void)
437{
438  if (!public_corba_refs)
439    {
440      public_corba_refs = g_hash_table_new (NULL, NULL);
441    }
442  return public_corba_refs;
443}
444
445static void
446de_register_public_ref (SpiBase *object)
447{
448  g_hash_table_remove (get_public_refs (), object->gobj);
449}
450
451SpiAccessible *
452spi_accessible_new (AtkObject *o)
453{
454  return spi_accessible_construct (SPI_ACCESSIBLE_TYPE, o);       
455}
456
457SpiAccessible *
458spi_accessible_construct (GType type, AtkObject *o)
459{
460    SpiAccessible *retval;
461    CORBA_Environment ev;
462
463    CORBA_exception_init (&ev);
464
465    g_assert (o);
466    g_assert (g_type_is_a (type, SPI_ACCESSIBLE_TYPE));
467
468    if ((retval = g_hash_table_lookup (get_public_refs (), o)))
469      {
470        bonobo_object_ref (BONOBO_OBJECT (retval));
471        return retval;
472      }
473    else
474      {
475        retval = g_object_new (type, NULL);
476        spi_base_construct (SPI_BASE (retval), G_OBJECT(o));
477      }
478   
479    g_hash_table_insert (get_public_refs (), o, retval);
480    g_signal_connect (G_OBJECT (retval), "destroy",
481                      G_CALLBACK (de_register_public_ref),
482                      NULL);
483
484    /* aggregate appropriate SPI interfaces based on ATK interfaces */
485 
486    if (ATK_IS_ACTION (o))
487      {
488        bonobo_object_add_interface (bonobo_object (retval),
489                BONOBO_OBJECT (spi_action_interface_new (o)));
490      }
491
492    if (ATK_IS_COMPONENT (o))
493      {
494        bonobo_object_add_interface (bonobo_object (retval),
495                                     BONOBO_OBJECT (spi_component_interface_new (o)));
496      }
497
498    if (ATK_IS_EDITABLE_TEXT (o))
499      {
500         bonobo_object_add_interface (bonobo_object (retval),
501                                      BONOBO_OBJECT(spi_editable_text_interface_new (o)));
502      }
503
504    else if (ATK_IS_TEXT (o))
505       {
506         bonobo_object_add_interface (bonobo_object (retval),
507                                      BONOBO_OBJECT (spi_text_interface_new (o)));
508       }
509
510    if (ATK_IS_HYPERTEXT (o))
511      {
512        bonobo_object_add_interface (bonobo_object (retval),
513                                     BONOBO_OBJECT (spi_hypertext_interface_new (o)));
514      }
515
516    if (ATK_IS_IMAGE (o))
517      {
518        bonobo_object_add_interface (bonobo_object (retval),
519                                     BONOBO_OBJECT (spi_image_interface_new (o)));
520      }
521
522    if (ATK_IS_SELECTION (o))
523      {
524        bonobo_object_add_interface (bonobo_object (retval),
525                                     BONOBO_OBJECT (spi_selection_interface_new (o)));
526      }
527
528    if (ATK_IS_TABLE (o))
529      {
530        bonobo_object_add_interface (bonobo_object (retval),
531                                     BONOBO_OBJECT (spi_table_interface_new (o)));
532      }
533
534    if (ATK_IS_VALUE (o))
535      {
536        bonobo_object_add_interface (bonobo_object (retval),
537                                     BONOBO_OBJECT (spi_value_interface_new (o)));
538      }
539
540    return retval;
541}
542
543/**
544 * spi_accessible_new_return:
545 * @o: an AtkObject or NULL
546 * @release_ref: whether to unref this AtkObject before return
547 * @ev: a CORBA environment
548 *
549 * A helper function to instantiate a CORBA accessiblility
550 * proxy from an AtkObject.
551 *
552 * Return value: the proxy or CORBA_OBJECT_NIL
553 **/
554Accessibility_Accessible
555spi_accessible_new_return (AtkObject         *o,
556                           gboolean           release_ref,
557                           CORBA_Environment *ev)
558{
559  SpiAccessible *accessible;
560  Accessibility_Accessible retval;
561
562  if (!o)
563    {
564      return CORBA_OBJECT_NIL;
565    }
566  else if (SPI_IS_REMOTE_OBJECT (o))
567    {
568      retval = spi_remote_object_get_accessible (SPI_REMOTE_OBJECT (o));
569    }
570  else
571    {
572      accessible = spi_accessible_construct (SPI_ACCESSIBLE_TYPE, o);
573      retval = CORBA_Object_duplicate (BONOBO_OBJREF (accessible), ev);
574    }
575
576  if (release_ref)
577    {
578      g_object_unref (G_OBJECT (o));
579    }
580 
581  return retval;
582}
Note: See TracBrowser for help on using the repository browser.