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

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