Fixes for 106932, and added support for synthesis of mouse buttons 4 and 5.
[platform/core/uifw/at-spi2-atk.git] / libspi / application.c
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 */
36 static SpiAccessibleClass *spi_application_parent_class;
37
38 static SpiApplication *the_app;
39
40 /* static methods */
41
42 static void notify_listeners (GList *listeners,
43                               SpiAccessible *source,
44                               Accessibility_Event *e);
45
46 /*
47  * Implemented GObject::finalize
48  */
49 static void
50 spi_accessible_application_finalize (GObject *object)
51 {
52   GList *l;
53   SpiApplication *application = (SpiApplication *) object;
54   CORBA_Environment ev;
55
56   CORBA_exception_init (&ev);
57
58   for (l = application->toolkit_listeners; l; l = l->next)
59     {
60       CORBA_Object_release ((CORBA_Object) l->data, &ev);
61     }
62
63   CORBA_exception_free (&ev);
64
65   g_list_free (application->toolkit_listeners);
66   application->toolkit_listeners = NULL;
67
68   g_print ("application finalize called\n");
69   (G_OBJECT_CLASS (spi_application_parent_class))->finalize (object);
70 }
71
72 static CORBA_string
73 impl_accessibility_application_get_toolkit_name (PortableServer_Servant servant,
74                                                  CORBA_Environment     *ev)
75 {
76   return CORBA_string_dup (atk_get_toolkit_name ());
77 }
78
79 static CORBA_string
80 impl_accessibility_application_get_version (PortableServer_Servant servant,
81                                             CORBA_Environment     *ev)
82 {
83   return CORBA_string_dup (atk_get_toolkit_version ());
84 }
85
86 static CORBA_long
87 impl_accessibility_application_get_id (PortableServer_Servant servant,
88                                        CORBA_Environment     *ev)
89 {
90   SpiApplication *application = SPI_APPLICATION (
91     bonobo_object_from_servant (servant));
92
93   return application->id;
94 }
95
96 static void
97 impl_accessibility_application_set_id (PortableServer_Servant servant,
98                                        const CORBA_long id,
99                                        CORBA_Environment *ev)
100 {
101   SpiApplication *application = SPI_APPLICATION (
102     bonobo_object_from_servant (servant));
103
104   application->id = id;
105 }
106
107 static AtkObject *
108 get_atk_object_ref (GObject *gobject)
109 {
110   AtkObject *aobject;
111
112   if (ATK_IS_IMPLEMENTOR (gobject))
113     {
114       aobject = atk_implementor_ref_accessible (ATK_IMPLEMENTOR (gobject));
115     }
116   else if (ATK_IS_OBJECT (gobject))
117     {
118       aobject = ATK_OBJECT (gobject);
119       g_object_ref (G_OBJECT (aobject));
120     }
121   else
122     {
123       aobject = NULL;
124       g_error ("received event from non-AtkImplementor");
125     }
126
127   return aobject;
128 }
129
130 static gboolean
131 spi_application_toolkit_event_listener (GSignalInvocationHint *signal_hint,
132                                         guint                  n_param_values,
133                                         const GValue          *param_values,
134                                         gpointer               data)
135 {
136   Accessibility_Event e;
137   AtkObject      *aobject;
138   SpiAccessible *source;
139   GSignalQuery   signal_query;
140   char          *event_name;
141
142   g_return_val_if_fail (the_app != NULL, FALSE);
143
144   g_signal_query (signal_hint->signal_id, &signal_query);
145
146   /* TODO: move GTK reference out of app.c into bridge */
147   event_name = g_strdup_printf ("Gtk:%s:%s",
148                                 g_type_name (signal_query.itype), 
149                                 signal_query.signal_name);
150
151 #ifdef SPI_DEBUG  
152   fprintf (stderr, "Received signal %s\n", event_name);
153 #endif
154   
155   aobject = get_atk_object_ref (g_value_get_object (param_values + 0));
156
157   source = spi_accessible_new (aobject);
158   e.type = CORBA_string_dup (event_name);
159   e.source = CORBA_OBJECT_NIL;
160   e.detail1 = 0;
161   e.detail2 = 0;
162   spi_init_any_nil (&e.any_data);
163   notify_listeners (the_app->toolkit_listeners, source, &e);
164
165   bonobo_object_unref (BONOBO_OBJECT (source));
166   g_object_unref (G_OBJECT (aobject));
167
168   g_free (event_name);
169
170   return TRUE;
171 }
172
173 static void
174 impl_accessibility_application_register_toolkit_event_listener (PortableServer_Servant servant,
175                                                                 Accessibility_EventListener listener,
176                                                                 const CORBA_char *event_name,
177                                                                 CORBA_Environment *ev)
178 {
179   guint spi_listener_id;
180   spi_listener_id =
181      atk_add_global_event_listener (spi_application_toolkit_event_listener, event_name);
182   the_app->toolkit_listeners = g_list_append (the_app->toolkit_listeners,
183                                               CORBA_Object_duplicate (listener, ev));
184 #ifdef SPI_DEBUG
185   fprintf (stderr, "registered %d for toolkit events named: %s\n",
186            spi_listener_id,
187            event_name);
188 #endif
189 }
190
191 static void
192 notify_listeners (GList *listeners, SpiAccessible *source, Accessibility_Event *e)
193 {
194   GList *l;
195   CORBA_Environment ev;
196
197   CORBA_exception_init (&ev);
198
199   for (l = listeners; l; l = l->next)
200     {
201       Accessibility_EventListener listener = l->data;
202
203       e->source = bonobo_object_dup_ref (BONOBO_OBJREF (source), &ev);
204
205       Accessibility_EventListener_notifyEvent (listener, e, &ev);
206       /*
207        * when this (oneway) call completes, the CORBA refcount and
208        * Bonobo_Unknown refcount will be decremented by the recipient
209        */
210       CORBA_exception_free (&ev);
211     }
212 }
213
214 static void
215 init_toolkit_names (GHashTable **generic_event_names, GHashTable **toolkit_event_names)
216 {
217         *toolkit_event_names = g_hash_table_new (g_str_hash, g_str_equal);
218         *generic_event_names = g_hash_table_new (g_str_hash, g_str_equal);
219         g_hash_table_insert (*toolkit_event_names,
220                              "object:property-change",
221                              "Gtk:AtkObject:property-change");
222         g_hash_table_insert (*generic_event_names,
223                              "Gtk:AtkObject:property-change",
224                              "object:property-change");
225 #ifdef SPI_DEBUG
226         fprintf (stderr, "inserted spi_selection_changed hash\n");
227 #endif
228 }
229
230 static void
231 spi_application_class_init (SpiApplicationClass *klass)
232 {
233   GObjectClass * object_class = (GObjectClass *) klass;
234   POA_Accessibility_Application__epv *epv = &klass->epv;
235
236   spi_application_parent_class = g_type_class_ref (SPI_ACCESSIBLE_TYPE);
237
238   object_class->finalize = spi_accessible_application_finalize;
239
240   epv->_get_toolkitName = impl_accessibility_application_get_toolkit_name;
241   epv->_get_version = impl_accessibility_application_get_version;
242   epv->_get_id = impl_accessibility_application_get_id;
243   epv->_set_id = impl_accessibility_application_set_id;
244   epv->registerToolkitEventListener = impl_accessibility_application_register_toolkit_event_listener;
245   init_toolkit_names (&klass->generic_event_names, &klass->toolkit_event_names);
246 }
247
248 static void
249 spi_application_init (SpiApplication *application)
250 {
251   application->toolkit_listeners = NULL;
252   the_app = application;
253 }
254
255 BONOBO_TYPE_FUNC_FULL (SpiApplication,
256                        Accessibility_Application,
257                        PARENT_TYPE, spi_application);
258
259 SpiApplication *
260 spi_application_new (AtkObject *app_root)
261 {
262   return SPI_APPLICATION (spi_accessible_construct (
263         SPI_APPLICATION_TYPE, app_root));
264 }