source: trunk/third/at-spi/libspi/application.c @ 18688

Revision 18688, 11.0 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18687, 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, 2002 Sun Microsystems Inc.,
6 * Copyright 2001, 2002 Ximian, Inc.
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/* application.c: implements SpiApplication.idl */
25
26#include <string.h>
27#include <config.h>
28#include <atk/atkutil.h>
29#include <libspi/application.h>
30#include "spi-private.h"
31
32/* Our parent Gtk object type */
33#define PARENT_TYPE SPI_ACCESSIBLE_TYPE
34
35/* A pointer to our parent object class */
36static SpiAccessibleClass *spi_application_parent_class;
37
38static SpiApplication *the_app;
39
40/* static methods */
41
42static void notify_listeners (GList *listeners,
43                              SpiAccessible *source,
44                              Accessibility_Event *e);
45
46static const char *reverse_lookup_name_for_toolkit_event (char *toolkit_name);
47
48static const char *
49lookup_toolkit_event_for_name (const char *generic_name)
50{
51  char *toolkit_specific_name;
52  SpiApplicationClass *klass = g_type_class_peek (SPI_APPLICATION_TYPE);
53#ifdef SPI_DEBUG
54  fprintf (stderr, "looking for %s in hash table.\n", generic_name);
55#endif
56  toolkit_specific_name =
57    (char *) g_hash_table_lookup (klass->toolkit_event_names, generic_name);
58#ifdef SPI_DEBUG
59  fprintf (stderr, "generic event %s converted to %s\n", generic_name, toolkit_specific_name);
60#endif
61  return toolkit_specific_name;
62}
63
64/*
65 * Implemented GObject::finalize
66 */
67static void
68spi_accessible_application_finalize (GObject *object)
69{
70  GList *l;
71  SpiApplication *application = (SpiApplication *) object;
72  CORBA_Environment ev;
73
74  CORBA_exception_init (&ev);
75
76  for (l = application->toolkit_listeners; l; l = l->next)
77    {
78      CORBA_Object_release ((CORBA_Object) l->data, &ev);
79    }
80
81  CORBA_exception_free (&ev);
82
83  g_list_free (application->toolkit_listeners);
84  application->toolkit_listeners = NULL;
85
86  g_print ("application finalize called\n");
87  (G_OBJECT_CLASS (spi_application_parent_class))->finalize (object);
88}
89
90static CORBA_string
91impl_accessibility_application_get_toolkit_name (PortableServer_Servant servant,
92                                                 CORBA_Environment     *ev)
93{
94  return CORBA_string_dup (atk_get_toolkit_name ());
95}
96
97static CORBA_string
98impl_accessibility_application_get_version (PortableServer_Servant servant,
99                                            CORBA_Environment     *ev)
100{
101  return CORBA_string_dup (atk_get_toolkit_version ());
102}
103
104static CORBA_long
105impl_accessibility_application_get_id (PortableServer_Servant servant,
106                                       CORBA_Environment     *ev)
107{
108  SpiApplication *application = SPI_APPLICATION (
109    bonobo_object_from_servant (servant));
110
111  return application->id;
112}
113
114static void
115impl_accessibility_application_set_id (PortableServer_Servant servant,
116                                       const CORBA_long id,
117                                       CORBA_Environment *ev)
118{
119  SpiApplication *application = SPI_APPLICATION (
120    bonobo_object_from_servant (servant));
121
122  application->id = id;
123}
124
125static AtkObject *
126get_atk_object_ref (GObject *gobject)
127{
128  AtkObject *aobject;
129
130  if (ATK_IS_IMPLEMENTOR (gobject))
131    {
132      aobject = atk_implementor_ref_accessible (ATK_IMPLEMENTOR (gobject));
133    }
134  else if (ATK_IS_OBJECT (gobject))
135    {
136      aobject = ATK_OBJECT (gobject);
137      g_object_ref (G_OBJECT (aobject));
138    }
139  else
140    {
141      aobject = NULL;
142      g_error ("received event from non-AtkImplementor");
143    }
144
145  return aobject;
146}
147
148static gboolean
149spi_application_object_event_listener (GSignalInvocationHint *signal_hint,
150                                       guint                   n_param_values,
151                                       const GValue           *param_values,
152                                       gpointer                data)
153{
154  Accessibility_Event e;
155  AtkObject     *aobject;
156  SpiAccessible *source;
157  GSignalQuery   signal_query;
158  gchar         *event_name;
159  const char    *generic_name;
160
161  g_return_val_if_fail (the_app != NULL, FALSE);
162 
163  g_signal_query (signal_hint->signal_id, &signal_query);
164
165  /* TODO: move GTK reference out of app.c into bridge */
166  event_name = g_strdup_printf ("Gtk:%s:%s",
167                                g_type_name (signal_query.itype),
168                                signal_query.signal_name);
169
170  generic_name = reverse_lookup_name_for_toolkit_event (event_name);
171
172  fprintf (stderr, "Received (object) signal %s maps to '%s'\n",
173           event_name, generic_name);
174
175  g_free (event_name);
176
177  g_return_val_if_fail (generic_name, FALSE);
178
179  aobject = get_atk_object_ref (g_value_get_object (param_values + 0));
180
181  source = spi_accessible_new (aobject);
182  e.type = CORBA_string_dup (generic_name);
183  e.source = CORBA_OBJECT_NIL;
184  e.detail1 = 0;
185  e.detail2 = 0;
186  spi_init_any_nil (&e.any_data);
187  notify_listeners (the_app->toolkit_listeners, source, &e);
188
189  bonobo_object_unref (BONOBO_OBJECT (source));
190
191  g_object_unref (G_OBJECT (aobject));
192
193  return TRUE;
194}
195
196static gboolean
197spi_application_toolkit_event_listener (GSignalInvocationHint *signal_hint,
198                                        guint                  n_param_values,
199                                        const GValue          *param_values,
200                                        gpointer               data)
201{
202  Accessibility_Event e;
203  AtkObject      *aobject;
204  SpiAccessible *source;
205  GSignalQuery   signal_query;
206  char          *event_name;
207
208  g_return_val_if_fail (the_app != NULL, FALSE);
209
210  g_signal_query (signal_hint->signal_id, &signal_query);
211
212  /* TODO: move GTK reference out of app.c into bridge */
213  event_name = g_strdup_printf ("Gtk:%s:%s",
214                                g_type_name (signal_query.itype),
215                                signal_query.signal_name);
216
217#ifdef SPI_DEBUG 
218  fprintf (stderr, "Received signal %s\n", event_name);
219#endif
220 
221  aobject = get_atk_object_ref (g_value_get_object (param_values + 0));
222
223  source = spi_accessible_new (aobject);
224  e.type = CORBA_string_dup (event_name);
225  e.source = CORBA_OBJECT_NIL;
226  e.detail1 = 0;
227  e.detail2 = 0;
228  spi_init_any_nil (&e.any_data);
229  notify_listeners (the_app->toolkit_listeners, source, &e);
230
231  bonobo_object_unref (BONOBO_OBJECT (source));
232  g_object_unref (G_OBJECT (aobject));
233
234  g_free (event_name);
235
236  return TRUE;
237}
238
239static void
240impl_accessibility_application_register_toolkit_event_listener (PortableServer_Servant servant,
241                                                                Accessibility_EventListener listener,
242                                                                const CORBA_char *event_name,
243                                                                CORBA_Environment *ev)
244{
245  guint spi_listener_id;
246  spi_listener_id =
247     atk_add_global_event_listener (spi_application_toolkit_event_listener, event_name);
248  the_app->toolkit_listeners = g_list_append (the_app->toolkit_listeners,
249                                              CORBA_Object_duplicate (listener, ev));
250#ifdef SPI_DEBUG
251  fprintf (stderr, "registered %d for toolkit events named: %s\n",
252           spi_listener_id,
253           event_name);
254#endif
255}
256
257static void
258impl_accessibility_application_register_object_event_listener (PortableServer_Servant servant,
259                                                               Accessibility_EventListener listener,
260                                                               const CORBA_char *event_name,
261                                                               CORBA_Environment *ev)
262{
263  guint spi_listener_id = 0;
264  const char *toolkit_specific_event_name =
265          lookup_toolkit_event_for_name (event_name);
266  if (toolkit_specific_event_name)
267  {
268    spi_listener_id =
269       atk_add_global_event_listener (spi_application_object_event_listener,
270                                      toolkit_specific_event_name);
271    the_app->toolkit_listeners = g_list_append (the_app->toolkit_listeners,
272                                              CORBA_Object_duplicate (listener, ev));
273  }
274#ifdef SPI_DEBUG
275  fprintf (stderr, "registered %d for object events named: %s\n",
276           spi_listener_id,
277           event_name);
278#endif
279}
280
281static void
282notify_listeners (GList *listeners, SpiAccessible *source, Accessibility_Event *e)
283{
284  GList *l;
285  CORBA_Environment ev;
286
287  CORBA_exception_init (&ev);
288
289  for (l = listeners; l; l = l->next)
290    {
291      Accessibility_EventListener listener = l->data;
292
293      e->source = bonobo_object_dup_ref (BONOBO_OBJREF (source), &ev);
294
295      Accessibility_EventListener_notifyEvent (listener, e, &ev);
296      /*
297       * when this (oneway) call completes, the CORBA refcount and
298       * Bonobo_Unknown refcount will be decremented by the recipient
299       */
300      CORBA_exception_free (&ev);
301    }
302}
303
304static const char *
305reverse_lookup_name_for_toolkit_event (char *toolkit_specific_name)
306{
307    const char *generic_name;
308    SpiApplicationClass *klass = g_type_class_peek (SPI_APPLICATION_TYPE);
309#ifdef SPI_DEBUG
310    fprintf (stderr, "(reverse lookup) looking for %s in hash table.\n", toolkit_specific_name);
311#endif
312    generic_name =
313            (const char *) g_hash_table_lookup (klass->generic_event_names, toolkit_specific_name);
314#ifdef SPI_DEBUG
315    fprintf (stderr, "toolkit event %s converted to %s\n", toolkit_specific_name, generic_name);
316#endif
317    return generic_name;
318}
319
320static void
321init_toolkit_names (GHashTable **generic_event_names, GHashTable **toolkit_event_names)
322{
323        *toolkit_event_names = g_hash_table_new (g_str_hash, g_str_equal);
324        *generic_event_names = g_hash_table_new (g_str_hash, g_str_equal);
325        g_hash_table_insert (*toolkit_event_names,
326                             "object:property-change",
327                             "Gtk:AtkObject:property-change");
328        g_hash_table_insert (*generic_event_names,
329                             "Gtk:AtkObject:property-change",
330                             "object:property-change");
331#ifdef SPI_DEBUG
332        fprintf (stderr, "inserted spi_selection_changed hash\n");
333#endif
334}
335
336static void
337spi_application_class_init (SpiApplicationClass *klass)
338{
339  GObjectClass * object_class = (GObjectClass *) klass;
340  POA_Accessibility_Application__epv *epv = &klass->epv;
341
342  spi_application_parent_class = g_type_class_ref (SPI_ACCESSIBLE_TYPE);
343
344  object_class->finalize = spi_accessible_application_finalize;
345
346  epv->_get_toolkitName = impl_accessibility_application_get_toolkit_name;
347  epv->_get_version = impl_accessibility_application_get_version;
348  epv->_get_id = impl_accessibility_application_get_id;
349  epv->_set_id = impl_accessibility_application_set_id;
350  epv->registerToolkitEventListener = impl_accessibility_application_register_toolkit_event_listener;
351  init_toolkit_names (&klass->generic_event_names, &klass->toolkit_event_names);
352}
353
354static void
355spi_application_init (SpiApplication *application)
356{
357  application->toolkit_listeners = NULL;
358  the_app = application;
359}
360
361BONOBO_TYPE_FUNC_FULL (SpiApplication,
362                       Accessibility_Application,
363                       PARENT_TYPE, spi_application);
364
365SpiApplication *
366spi_application_new (AtkObject *app_root)
367{
368  return SPI_APPLICATION (spi_accessible_construct (
369        SPI_APPLICATION_TYPE, app_root));
370}
Note: See TracBrowser for help on using the repository browser.