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