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