Re-work the bonobo code.
[platform/upstream/at-spi2-core.git] / cspi / bonobo / cspi-bonobo-listener.c
1 #include <libbonobo.h>
2 #include "../spi-private.h"
3 #include "cspi-bonobo-listener.h"
4
5 typedef struct
6 {
7   union
8     {
9       AccessibleEventListenerCB     event;
10       AccessibleKeystrokeListenerCB key_event;
11       gpointer                      method;
12     } cb;
13   gpointer user_data;
14 } EventHandler;
15
16 GObjectClass *event_parent_class;
17 GObjectClass *keystroke_parent_class;
18
19 /*
20  * Misc. helpers.
21  */
22
23 static EventHandler *
24 event_handler_new (gpointer method, gpointer user_data)
25 {
26   EventHandler *eh = g_new0 (EventHandler, 1);
27
28   eh->cb.method = method;
29   eh->user_data = user_data;
30
31   return eh;
32 }
33
34 static void
35 event_handler_free (EventHandler *handler)
36 {
37   g_free (handler);
38 }
39
40 static GList *
41 event_list_remove_by_cb (GList *list, gpointer callback)
42 {
43   GList *l, *next;
44         
45   for (l = list; l; l = next)
46     {
47       EventHandler *eh = l->data;
48       next = l->next;
49       
50       list = g_list_delete_link (list, l);
51       
52       event_handler_free (eh);
53     }
54
55   return list;
56 }
57
58 /*
59  * Standard event dispatcher
60  */
61
62 BONOBO_CLASS_BOILERPLATE (CSpiEventListener, cspi_event_listener,
63                           GObject, spi_event_listener_get_type ())
64
65 static void
66 cspi_event (SpiEventListener    *listener,
67             Accessibility_Event *event)
68 {
69   GList *l;
70   CSpiEventListener *clistener = (CSpiEventListener *) listener;
71   AccessibleEvent    aevent;
72   Accessible        *source;
73
74   source = cspi_object_add (bonobo_object_dup_ref (event->source, cspi_ev ()));
75
76   aevent.type    = event->type;
77   aevent.source  = source;
78   aevent.detail1 = event->detail1;
79   aevent.detail2 = event->detail2;
80
81   /* FIXME: re-enterancy hazard on this list */
82   for (l = clistener->callbacks; l; l = l->next)
83     {
84       EventHandler *eh = l->data;
85
86       eh->cb.event (&aevent, eh->user_data);
87     }
88
89   cspi_object_unref (source);
90 }
91
92 static void
93 cspi_event_listener_instance_init (CSpiEventListener *listener)
94 {
95 }
96
97 static void
98 cspi_event_listener_finalize (GObject *object)
99 {
100   CSpiEventListener *listener = (CSpiEventListener *) object;
101   GList *l;
102   
103   for (l = listener->callbacks; l; l = l->next)
104     {
105       event_handler_free (l->data);
106     }
107   
108   g_list_free (listener->callbacks);
109
110   event_parent_class->finalize (object);
111 }
112
113 static void
114 cspi_event_listener_class_init (CSpiEventListenerClass *klass)
115 {
116   GObjectClass *object_class = (GObjectClass *) klass;
117
118   event_parent_class = g_type_class_peek_parent (klass);
119   object_class->finalize = cspi_event_listener_finalize;
120
121   klass->event = cspi_event;
122 }
123
124 CORBA_Object
125 cspi_event_listener_new (void)
126 {
127   CSpiEventListener *listener;
128
129   listener = g_object_new (cspi_event_listener_get_type (), NULL);
130
131   return CORBA_Object_duplicate (BONOBO_OBJREF (listener), cspi_ev ());
132 }
133
134 void
135 cspi_event_listener_add_cb (AccessibleEventListener  *al,
136                             AccessibleEventListenerCB callback,
137                             void                     *user_data)
138 {
139   CSpiEventListener *listener = bonobo_object (
140     ORBit_small_get_servant (CSPI_OBJREF (al)));
141
142   g_return_if_fail (CSPI_IS_EVENT_LISTENER (listener));
143
144   listener->callbacks = g_list_prepend (listener->callbacks,
145                                         event_handler_new (callback, user_data));
146 }
147
148 void
149 cspi_event_listener_remove_cb (AccessibleEventListener  *al,
150                                AccessibleEventListenerCB callback)
151 {
152   CSpiEventListener *listener = bonobo_object (
153     ORBit_small_get_servant (CSPI_OBJREF (al)));
154
155   g_return_if_fail (CSPI_IS_EVENT_LISTENER (listener));
156
157   listener->callbacks = event_list_remove_by_cb (listener->callbacks, callback);
158 }
159
160 /*
161  * Key event dispatcher
162  */
163
164 static gboolean
165 cspi_key_event (SpiKeystrokeListener          *listener,
166                 const Accessibility_KeyStroke *keystroke)
167 {
168   GList *l;
169   CSpiKeystrokeListener *clistener = (CSpiKeystrokeListener *) listener;
170   AccessibleKeystroke akeystroke;
171   gboolean handled = FALSE;
172
173 #ifdef SPI_KEYEVENT_DEBUG
174   fprintf (stderr, "%s%c",
175            (keystroke->modifiers & SPI_KEYMASK_ALT)?"Alt-":"",
176            ((keystroke->modifiers & SPI_KEYMASK_SHIFT)^(keystroke->modifiers & SPI_KEYMASK_SHIFTLOCK))?
177            (char) toupper((int) keystroke->keyID) : (char) tolower((int) keystroke->keyID));
178   
179   fprintf (stderr, "Key:\tsym %ld\n\tmods %x\n\tcode %d\n\ttime %ld\n",
180            (long) keystroke->keyID,
181            (unsigned int) keystroke->modifiers,
182            (int) keystroke->keycode,
183            (long int) keystroke->timestamp);
184 #endif
185
186   switch (keystroke->type)
187     {
188       case Accessibility_KEY_PRESSED:
189         akeystroke.type = SPI_KEY_PRESSED;
190         break;
191       case Accessibility_KEY_RELEASED:
192         akeystroke.type = SPI_KEY_RELEASED;
193         break;
194       default:
195         akeystroke.type = 0;
196         break;
197     }
198   akeystroke.keyID     = keystroke->keyID;
199   akeystroke.keycode   = keystroke->keycode;
200   akeystroke.timestamp = keystroke->timestamp;
201   akeystroke.modifiers = keystroke->modifiers;
202
203   /* FIXME: re-enterancy hazard on this list */
204   for (l = clistener->callbacks; l; l = l->next)
205     {
206       EventHandler *eh = l->data;
207
208       if ((handled = eh->cb.key_event (&akeystroke, eh->user_data)))
209         {
210           break;
211         }
212     }
213   
214   return handled;
215 }
216
217 static void
218 cspi_keystroke_listener_init (CSpiKeystrokeListener *listener)
219 {
220 }
221
222
223 static void
224 cspi_keystroke_listener_finalize (GObject *object)
225 {
226   CSpiKeystrokeListener *listener = (CSpiKeystrokeListener *) object;
227   GList *l;
228   
229   for (l = listener->callbacks; l; l = l->next)
230     {
231       event_handler_free (l->data);
232     }
233   
234   g_list_free (listener->callbacks);
235
236   keystroke_parent_class->finalize (object);
237 }
238
239 static void
240 cspi_keystroke_listener_class_init (CSpiKeystrokeListenerClass *klass)
241 {
242   GObjectClass *object_class = (GObjectClass *) klass;
243
244   keystroke_parent_class = g_type_class_peek_parent (klass);
245   object_class->finalize = cspi_keystroke_listener_finalize;
246
247   klass->key_event = cspi_key_event;
248 }
249
250 BONOBO_TYPE_FUNC (CSpiKeystrokeListener, 
251                   spi_keystroke_listener_get_type (),
252                   cspi_keystroke_listener);
253
254 CORBA_Object
255 cspi_keystroke_listener_new (void)
256 {
257   CSpiEventListener *listener;
258
259   listener = g_object_new (cspi_keystroke_listener_get_type (), NULL);
260
261   return CORBA_Object_duplicate (BONOBO_OBJREF (listener), cspi_ev ());
262 }
263
264 void
265 cspi_keystroke_listener_add_cb (AccessibleKeystrokeListener  *al,
266                                 AccessibleKeystrokeListenerCB callback,
267                                 void                         *user_data)
268 {
269   CSpiKeystrokeListener *listener = bonobo_object (
270     ORBit_small_get_servant (CSPI_OBJREF (al)));
271
272   g_return_if_fail (CSPI_IS_KEYSTROKE_LISTENER (listener));
273
274   listener->callbacks = g_list_prepend (listener->callbacks,
275                                         event_handler_new (callback, user_data));
276 }
277
278 void
279 cspi_keystroke_listener_remove_cb (AccessibleKeystrokeListener  *al,
280                                    AccessibleKeystrokeListenerCB callback)
281 {
282   CSpiKeystrokeListener *listener = bonobo_object (
283     ORBit_small_get_servant (CSPI_OBJREF (al)));
284
285   g_return_if_fail (CSPI_IS_KEYSTROKE_LISTENER (listener));
286
287   listener->callbacks = event_list_remove_by_cb (listener->callbacks, callback);
288 }