Fixes for 98836, 98842, added slots to IDL for ABI freeze.
[platform/core/uifw/at-spi2-atk.git] / cspi / bonobo / cspi-bonobo-listener.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2002 Ximian Inc.
6  * Copyright 2002 Sun Microsystems, 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 #include <libbonobo.h>
25 #include "../spi-private.h"
26 #include "cspi-bonobo-listener.h"
27
28 typedef struct
29 {
30   union
31     {
32       AccessibleEventListenerCB     event;
33       AccessibleDeviceListenerCB    device_event;
34       gpointer                      method;
35     } cb;
36   gpointer user_data;
37 } EventHandler;
38
39 GObjectClass *event_parent_class;
40 GObjectClass *device_parent_class;
41
42 /*
43  * Misc. helpers.
44  */
45
46 static EventHandler *
47 cspi_event_handler_new (gpointer method, gpointer user_data)
48 {
49   EventHandler *eh = g_new0 (EventHandler, 1);
50
51   eh->cb.method = method;
52   eh->user_data = user_data;
53
54   return eh;
55 }
56
57 static void
58 cspi_event_handler_free (EventHandler *handler)
59 {
60   g_free (handler);
61 }
62
63 static GList *
64 cspi_event_list_remove_by_cb (GList *list, gpointer callback)
65 {
66   GList *l, *next;
67         
68   for (l = list; l; l = next)
69     {
70       EventHandler *eh = l->data;
71       next = l->next;
72       
73       list = g_list_delete_link (list, l);
74       
75       cspi_event_handler_free (eh);
76     }
77
78   return list;
79 }
80
81 /*
82  * Standard event dispatcher
83  */
84
85 BONOBO_CLASS_BOILERPLATE (CSpiEventListener, cspi_event_listener,
86                           GObject, spi_event_listener_get_type ())
87
88 static void
89 cspi_event (SpiEventListener    *listener,
90             Accessibility_Event *event)
91 {
92   GList *l;
93   CSpiEventListener *clistener = (CSpiEventListener *) listener;
94   InternalEvent      aevent;
95   Accessible        *source = cspi_object_borrow (event->source);
96   
97   aevent.event.type    = event->type;
98   aevent.event.source  = source;
99   aevent.event.detail1 = event->detail1;
100   aevent.event.detail2 = event->detail2;
101   aevent.data          = &event->any_data;
102
103   /* FIXME: re-enterancy hazard on this list */
104   for (l = clistener->callbacks; l; l = l->next)
105     {
106       EventHandler *eh = l->data;
107       /* cast hides our private stuff from client handlers */
108       eh->cb.event ((AccessibleEvent *) &aevent, eh->user_data);
109     }
110
111   cspi_object_return (source);
112 }
113
114 static void
115 cspi_event_listener_instance_init (CSpiEventListener *listener)
116 {
117 }
118
119 static void
120 cspi_event_listener_finalize (GObject *object)
121 {
122   CSpiEventListener *listener = (CSpiEventListener *) object;
123   GList *l;
124   
125   for (l = listener->callbacks; l; l = l->next)
126     {
127       cspi_event_handler_free (l->data);
128     }
129   
130   g_list_free (listener->callbacks);
131
132   event_parent_class->finalize (object);
133 }
134
135 static void
136 cspi_event_listener_class_init (CSpiEventListenerClass *klass)
137 {
138   GObjectClass *object_class = (GObjectClass *) klass;
139
140   event_parent_class = g_type_class_peek_parent (klass);
141   object_class->finalize = cspi_event_listener_finalize;
142
143   klass->event = cspi_event;
144 }
145
146 gpointer
147 cspi_event_listener_new (void)
148 {
149   CSpiEventListener *listener;
150
151   listener = g_object_new (cspi_event_listener_get_type (), NULL);
152
153   return listener;
154 }
155
156 void
157 cspi_event_listener_add_cb (AccessibleEventListener  *al,
158                             AccessibleEventListenerCB callback,
159                             void                     *user_data)
160 {
161   CSpiEventListener *listener = al;
162
163   g_return_if_fail (CSPI_IS_EVENT_LISTENER (listener));
164
165   listener->callbacks = g_list_prepend (listener->callbacks,
166                                         cspi_event_handler_new (callback, user_data));
167 }
168
169 void
170 cspi_event_listener_remove_cb (AccessibleEventListener  *al,
171                                AccessibleEventListenerCB callback)
172 {
173   CSpiEventListener *listener = al;
174
175   g_return_if_fail (CSPI_IS_EVENT_LISTENER (listener));
176
177   listener->callbacks = cspi_event_list_remove_by_cb (listener->callbacks, callback);
178 }
179
180 /* 
181  * Device event handler
182  */
183 static gboolean
184 cspi_device_event (SpiDeviceListener               *listener,
185                    const Accessibility_DeviceEvent *event)
186 {
187   GList *l;
188   CSpiDeviceListener *clistener = (CSpiDeviceListener *) listener;
189   AccessibleDeviceEvent anevent;
190   gboolean handled = FALSE;
191
192   switch (event->type)
193     {
194       case Accessibility_KEY_PRESSED_EVENT:
195         anevent.type = SPI_KEY_PRESSED;
196         break;
197       case Accessibility_KEY_RELEASED_EVENT:
198         anevent.type = SPI_KEY_RELEASED;
199         break;
200       case Accessibility_BUTTON_PRESSED_EVENT:
201         anevent.type = SPI_BUTTON_PRESSED;
202         break;
203       case Accessibility_BUTTON_RELEASED_EVENT:
204         anevent.type = SPI_BUTTON_RELEASED;
205         break;
206       default:
207         anevent.type = 0;
208         break;
209     }
210   anevent.keyID     = event->id;
211   anevent.keycode   = event->hw_code;
212   anevent.timestamp = event->timestamp;
213   anevent.keystring = g_strdup (event->event_string);
214   anevent.modifiers = event->modifiers;
215
216   /* FIXME: re-enterancy hazard on this list */
217   for (l = clistener->callbacks; l; l = l->next)
218     {
219       EventHandler *eh = l->data;
220
221       if ((handled = eh->cb.device_event (&anevent, eh->user_data)))
222         {
223           break;
224         }
225     }
226   
227   return handled;
228 }
229
230 static void
231 cspi_device_listener_init (CSpiDeviceListener *listener)
232 {
233 }
234
235 static void
236 cspi_device_listener_finalize (GObject *object)
237 {
238   CSpiDeviceListener *listener = (CSpiDeviceListener *) object;
239   GList *l;
240   
241   for (l = listener->callbacks; l; l = l->next)
242     {
243       cspi_event_handler_free (l->data);
244     }
245   
246   g_list_free (listener->callbacks);
247
248   device_parent_class->finalize (object);
249 }
250
251 static void
252 cspi_device_listener_class_init (CSpiDeviceListenerClass *klass)
253 {
254   GObjectClass *object_class = (GObjectClass *) klass;
255
256   device_parent_class = g_type_class_peek_parent (klass);
257   object_class->finalize = cspi_device_listener_finalize;
258
259   klass->device_event = cspi_device_event;
260 }
261
262 BONOBO_TYPE_FUNC (CSpiDeviceListener, 
263                   spi_device_listener_get_type (),
264                   cspi_device_listener);
265
266 gpointer
267 cspi_device_listener_new (void)
268 {
269   CSpiEventListener *listener = g_object_new (cspi_device_listener_get_type (), NULL);
270
271   return listener;
272 }
273
274 void
275 cspi_device_listener_add_cb (AccessibleDeviceListener  *al,
276                              AccessibleDeviceListenerCB callback,
277                              void                      *user_data)
278 {
279   CSpiDeviceListener *listener = al;
280
281   g_return_if_fail (CSPI_IS_DEVICE_LISTENER (listener));
282
283   listener->callbacks = g_list_prepend (listener->callbacks,
284                                         cspi_event_handler_new (callback, user_data));
285 }
286
287 void
288 cspi_device_listener_remove_cb (AccessibleDeviceListener  *al,
289                                 AccessibleDeviceListenerCB callback)
290 {
291   CSpiDeviceListener *listener = al;
292
293   g_return_if_fail (CSPI_IS_DEVICE_LISTENER (listener));
294
295   listener->callbacks = cspi_event_list_remove_by_cb (listener->callbacks, callback);
296 }
297
298 void
299 cspi_event_listener_unref (AccessibleEventListener *listener)
300 {
301   bonobo_object_unref (BONOBO_OBJECT (listener));
302 }
303
304 void
305 cspi_device_listener_unref (AccessibleDeviceListener *listener)
306 {
307   bonobo_object_unref (BONOBO_OBJECT (listener));
308 }
309
310
311 CORBA_Object
312 cspi_event_listener_get_corba (AccessibleEventListener *listener)
313 {
314   return BONOBO_OBJREF (listener);
315 }
316
317 CORBA_Object
318 cspi_device_listener_get_corba (AccessibleDeviceListener *listener)
319 {
320   return BONOBO_OBJREF (listener);
321 }
322