2002-08-12 Darren Kenny <darren.kenny@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 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 #include <libbonobo.h>
24 #include "../spi-private.h"
25 #include "cspi-bonobo-listener.h"
26
27 typedef struct
28 {
29   union
30     {
31       AccessibleEventListenerCB     event;
32       AccessibleKeystrokeListenerCB key_event;
33       gpointer                      method;
34     } cb;
35   gpointer user_data;
36 } EventHandler;
37
38 GObjectClass *event_parent_class;
39 GObjectClass *keystroke_parent_class;
40
41 /*
42  * Misc. helpers.
43  */
44
45 static EventHandler *
46 cspi_event_handler_new (gpointer method, gpointer user_data)
47 {
48   EventHandler *eh = g_new0 (EventHandler, 1);
49
50   eh->cb.method = method;
51   eh->user_data = user_data;
52
53   return eh;
54 }
55
56 static void
57 cspi_event_handler_free (EventHandler *handler)
58 {
59   g_free (handler);
60 }
61
62 static GList *
63 cspi_event_list_remove_by_cb (GList *list, gpointer callback)
64 {
65   GList *l, *next;
66         
67   for (l = list; l; l = next)
68     {
69       EventHandler *eh = l->data;
70       next = l->next;
71       
72       list = g_list_delete_link (list, l);
73       
74       cspi_event_handler_free (eh);
75     }
76
77   return list;
78 }
79
80 /*
81  * Standard event dispatcher
82  */
83
84 BONOBO_CLASS_BOILERPLATE (CSpiEventListener, cspi_event_listener,
85                           GObject, spi_event_listener_get_type ())
86
87 static void
88 cspi_event (SpiEventListener    *listener,
89             Accessibility_Event *event)
90 {
91   GList *l;
92   CSpiEventListener *clistener = (CSpiEventListener *) listener;
93   AccessibleEvent    aevent;
94   Accessible        *source = cspi_object_add (cspi_dup_ref(event->source));
95   
96   aevent.type    = event->type;
97   aevent.source  = source;
98   aevent.detail1 = event->detail1;
99   aevent.detail2 = event->detail2;
100
101   /* FIXME: re-enterancy hazard on this list */
102   for (l = clistener->callbacks; l; l = l->next)
103     {
104       EventHandler *eh = l->data;
105
106       eh->cb.event (&aevent, eh->user_data);
107     }
108
109   cspi_object_unref( source );
110 }
111
112 static void
113 cspi_event_listener_instance_init (CSpiEventListener *listener)
114 {
115 }
116
117 static void
118 cspi_event_listener_finalize (GObject *object)
119 {
120   CSpiEventListener *listener = (CSpiEventListener *) object;
121   GList *l;
122   
123   for (l = listener->callbacks; l; l = l->next)
124     {
125       cspi_event_handler_free (l->data);
126     }
127   
128   g_list_free (listener->callbacks);
129
130   event_parent_class->finalize (object);
131 }
132
133 static void
134 cspi_event_listener_class_init (CSpiEventListenerClass *klass)
135 {
136   GObjectClass *object_class = (GObjectClass *) klass;
137
138   event_parent_class = g_type_class_peek_parent (klass);
139   object_class->finalize = cspi_event_listener_finalize;
140
141   klass->event = cspi_event;
142 }
143
144 gpointer
145 cspi_event_listener_new (void)
146 {
147   CSpiEventListener *listener;
148
149   listener = g_object_new (cspi_event_listener_get_type (), NULL);
150
151   return listener;
152 }
153
154 void
155 cspi_event_listener_add_cb (AccessibleEventListener  *al,
156                             AccessibleEventListenerCB callback,
157                             void                     *user_data)
158 {
159   CSpiEventListener *listener = al;
160
161   g_return_if_fail (CSPI_IS_EVENT_LISTENER (listener));
162
163   listener->callbacks = g_list_prepend (listener->callbacks,
164                                         cspi_event_handler_new (callback, user_data));
165 }
166
167 void
168 cspi_event_listener_remove_cb (AccessibleEventListener  *al,
169                                AccessibleEventListenerCB callback)
170 {
171   CSpiEventListener *listener = al;
172
173   g_return_if_fail (CSPI_IS_EVENT_LISTENER (listener));
174
175   listener->callbacks = cspi_event_list_remove_by_cb (listener->callbacks, callback);
176 }
177
178 /*
179  * Key event dispatcher
180  */
181 static gboolean
182 cspi_key_event (SpiKeystrokeListener            *listener,
183                 const Accessibility_DeviceEvent *keystroke)
184 {
185   GList *l;
186   CSpiKeystrokeListener *clistener = (CSpiKeystrokeListener *) listener;
187   AccessibleKeystroke akeystroke;
188   gboolean handled = FALSE;
189
190 #ifdef SPI_KEYEVENT_DEBUG
191   fprintf (stderr, "%s%c",
192            (keystroke->modifiers & SPI_KEYMASK_ALT)?"Alt-":"",
193            ((keystroke->modifiers & SPI_KEYMASK_SHIFT)^(keystroke->modifiers & SPI_KEYMASK_SHIFTLOCK))?
194            (char) toupper((int) keystroke->keyID) : (char) tolower((int) keystroke->keyID));
195   
196   fprintf (stderr, "Key:\tsym %ld\n\tmods %x\n\tcode %d\n\ttime %ld\n",
197            (long) keystroke->keyID,
198            (unsigned int) keystroke->modifiers,
199            (int) keystroke->keycode,
200            (long int) keystroke->timestamp);
201 #endif
202
203   switch (keystroke->type)
204     {
205       case Accessibility_KEY_PRESSED:
206         akeystroke.type = SPI_KEY_PRESSED;
207         break;
208       case Accessibility_KEY_RELEASED:
209         akeystroke.type = SPI_KEY_RELEASED;
210         break;
211       default:
212         akeystroke.type = 0;
213         break;
214     }
215   akeystroke.keyID     = keystroke->id;
216   akeystroke.keycode   = keystroke->hw_code;
217   akeystroke.timestamp = keystroke->timestamp;
218   akeystroke.keystring = g_strdup (keystroke->event_string);
219   akeystroke.modifiers = keystroke->modifiers;
220
221   /* FIXME: re-enterancy hazard on this list */
222   for (l = clistener->callbacks; l; l = l->next)
223     {
224       EventHandler *eh = l->data;
225
226       if ((handled = eh->cb.key_event (&akeystroke, eh->user_data)))
227         {
228           break;
229         }
230     }
231   
232   return handled;
233 }
234
235 static void
236 cspi_keystroke_listener_init (CSpiKeystrokeListener *listener)
237 {
238 }
239
240
241 static void
242 cspi_keystroke_listener_finalize (GObject *object)
243 {
244   CSpiKeystrokeListener *listener = (CSpiKeystrokeListener *) 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   keystroke_parent_class->finalize (object);
255 }
256
257 static void
258 cspi_keystroke_listener_class_init (CSpiKeystrokeListenerClass *klass)
259 {
260   GObjectClass *object_class = (GObjectClass *) klass;
261
262   keystroke_parent_class = g_type_class_peek_parent (klass);
263   object_class->finalize = cspi_keystroke_listener_finalize;
264
265   klass->key_event = cspi_key_event;
266 }
267
268 BONOBO_TYPE_FUNC (CSpiKeystrokeListener, 
269                   spi_keystroke_listener_get_type (),
270                   cspi_keystroke_listener);
271
272 gpointer
273 cspi_keystroke_listener_new (void)
274 {
275   CSpiEventListener *listener;
276
277   listener = g_object_new (cspi_keystroke_listener_get_type (), NULL);
278
279   return listener;
280 }
281
282 void
283 cspi_keystroke_listener_add_cb (AccessibleKeystrokeListener  *al,
284                                 AccessibleKeystrokeListenerCB callback,
285                                 void                         *user_data)
286 {
287   CSpiKeystrokeListener *listener = al;
288
289   g_return_if_fail (CSPI_IS_KEYSTROKE_LISTENER (listener));
290
291   listener->callbacks = g_list_prepend (listener->callbacks,
292                                         cspi_event_handler_new (callback, user_data));
293 }
294
295 void
296 cspi_keystroke_listener_remove_cb (AccessibleKeystrokeListener  *al,
297                                    AccessibleKeystrokeListenerCB callback)
298 {
299   CSpiKeystrokeListener *listener = al;
300
301   g_return_if_fail (CSPI_IS_KEYSTROKE_LISTENER (listener));
302
303   listener->callbacks = cspi_event_list_remove_by_cb (listener->callbacks, callback);
304 }
305
306 void
307 cspi_event_listener_unref (AccessibleEventListener *listener)
308 {
309   bonobo_object_unref (BONOBO_OBJECT (listener));
310 }
311
312 void
313 cspi_keystroke_listener_unref (AccessibleKeystrokeListener *listener)
314 {
315   bonobo_object_unref (BONOBO_OBJECT (listener));
316 }
317
318
319 CORBA_Object
320 cspi_event_listener_get_corba (AccessibleEventListener *listener)
321 {
322   return BONOBO_OBJREF (listener);
323 }
324
325 CORBA_Object
326 cspi_keystroke_listener_get_corba (AccessibleKeystrokeListener *listener)
327 {
328   return BONOBO_OBJREF (listener);
329 }
330