912bb26baea34ec1d9b2a7d5d7e529b085b9decf
[platform/core/uifw/at-spi2-atk.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   Accessible        *source;
72
73   source = cspi_object_add_check (bonobo_object_dup_ref (event->source, cspi_ev ()));
74
75   aevent.type    = event->type;
76   aevent.source  = source;
77   aevent.detail1 = event->detail1;
78   aevent.detail2 = event->detail2;
79
80   /* FIXME: re-enterancy hazard on this list */
81   for (l = clistener->callbacks; l; l = l->next)
82     {
83       EventHandler *eh = l->data;
84
85       eh->cb.event (&aevent, eh->user_data);
86     }
87
88   cspi_object_unref (source);
89 }
90
91 static void
92 cspi_event_listener_instance_init (CSpiEventListener *listener)
93 {
94 }
95
96 static void
97 cspi_event_listener_finalize (GObject *object)
98 {
99   CSpiEventListener *listener = (CSpiEventListener *) object;
100   GList *l;
101   
102   for (l = listener->callbacks; l; l = l->next)
103     {
104       event_handler_free (l->data);
105     }
106   
107   g_list_free (listener->callbacks);
108
109   event_parent_class->finalize (object);
110 }
111
112 static void
113 cspi_event_listener_class_init (CSpiEventListenerClass *klass)
114 {
115   GObjectClass *object_class = (GObjectClass *) klass;
116
117   event_parent_class = g_type_class_peek_parent (klass);
118   object_class->finalize = cspi_event_listener_finalize;
119
120   klass->event = cspi_event;
121 }
122
123 CSpiEventListener *
124 cspi_event_listener_new (void)
125 {
126   return g_object_new (cspi_event_listener_get_type (), NULL);
127 }
128
129 void
130 cspi_event_listener_add_callback (CSpiEventListener        *listener,
131                                   AccessibleEventListenerCB callback,
132                                   void                     *user_data)
133 {
134   g_return_if_fail (CSPI_IS_EVENT_LISTENER (listener));
135   listener->callbacks = g_list_prepend (listener->callbacks,
136                                         event_handler_new (callback, user_data));
137 }
138
139 void
140 cspi_event_listener_remove_callback (CSpiEventListener        *listener,
141                                      AccessibleEventListenerCB callback)
142 {
143   g_return_if_fail (CSPI_IS_EVENT_LISTENER (listener));
144   listener->callbacks = event_list_remove_by_callback (listener->callbacks, callback);
145 }
146
147 /*
148  * Key event dispatcher
149  */
150
151 static gboolean
152 cspi_key_event (SpiKeystrokeListener          *listener,
153                 const Accessibility_KeyStroke *keystroke)
154 {
155   GList *l;
156   CSpiKeystrokeListener *clistener = (CSpiKeystrokeListener *) listener;
157   AccessibleKeystroke akeystroke;
158   gboolean handled = FALSE;
159
160 #ifdef SPI_KEYEVENT_DEBUG
161   fprintf (stderr, "%s%c",
162            (keystroke->modifiers & SPI_KEYMASK_ALT)?"Alt-":"",
163            ((keystroke->modifiers & SPI_KEYMASK_SHIFT)^(keystroke->modifiers & SPI_KEYMASK_SHIFTLOCK))?
164            (char) toupper((int) keystroke->keyID) : (char) tolower((int) keystroke->keyID));
165   
166   fprintf (stderr, "Key:\tsym %ld\n\tmods %x\n\tcode %d\n\ttime %ld\n",
167            (long) keystroke->keyID,
168            (unsigned int) keystroke->modifiers,
169            (int) keystroke->keycode,
170            (long int) keystroke->timestamp);
171 #endif
172
173   switch (keystroke->type)
174     {
175       case Accessibility_KEY_PRESSED:
176         akeystroke.type = SPI_KEY_PRESSED;
177         break;
178       case Accessibility_KEY_RELEASED:
179         akeystroke.type = SPI_KEY_RELEASED;
180         break;
181       default:
182         akeystroke.type = 0;
183         break;
184     }
185   akeystroke.keyID     = keystroke->keyID;
186   akeystroke.keycode   = keystroke->keycode;
187   akeystroke.timestamp = keystroke->timestamp;
188   akeystroke.modifiers = keystroke->modifiers;
189
190   /* FIXME: re-enterancy hazard on this list */
191   for (l = clistener->callbacks; l; l = l->next)
192     {
193       EventHandler *eh = l->data;
194
195       if ((handled = eh->cb.key_event (&akeystroke, eh->user_data)))
196         {
197           break;
198         }
199     }
200   
201   return handled;
202 }
203
204 static void
205 cspi_keystroke_listener_init (CSpiKeystrokeListener *listener)
206 {
207 }
208
209
210 static void
211 cspi_keystroke_listener_finalize (GObject *object)
212 {
213   CSpiKeystrokeListener *listener = (CSpiKeystrokeListener *) object;
214   GList *l;
215   
216   for (l = listener->callbacks; l; l = l->next)
217     {
218       event_handler_free (l->data);
219     }
220   
221   g_list_free (listener->callbacks);
222
223   keystroke_parent_class->finalize (object);
224 }
225
226 static void
227 cspi_keystroke_listener_class_init (CSpiKeystrokeListenerClass *klass)
228 {
229   GObjectClass *object_class = (GObjectClass *) klass;
230
231   keystroke_parent_class = g_type_class_peek_parent (klass);
232   object_class->finalize = cspi_keystroke_listener_finalize;
233
234   klass->key_event = cspi_key_event;
235 }
236
237 BONOBO_TYPE_FUNC (CSpiKeystrokeListener, 
238                   spi_keystroke_listener_get_type (),
239                   cspi_keystroke_listener);
240
241 CSpiKeystrokeListener *
242 cspi_keystroke_listener_new (void)
243 {
244   return g_object_new (cspi_keystroke_listener_get_type (), NULL);
245 }
246
247 void
248 cspi_keystroke_listener_add_callback (CSpiKeystrokeListener        *listener,
249                                       AccessibleKeystrokeListenerCB callback,
250                                       void                         *user_data)
251 {
252   g_return_if_fail (CSPI_IS_KEYSTROKE_LISTENER (listener));
253   listener->callbacks = g_list_prepend (listener->callbacks,
254                                         event_handler_new (callback, user_data));
255 }
256
257 void
258 cspi_keystroke_listener_remove_callback (CSpiKeystrokeListener        *listener,
259                                          AccessibleKeystrokeListenerCB callback)
260 {
261   g_return_if_fail (CSPI_IS_KEYSTROKE_LISTENER (listener));
262   listener->callbacks = event_list_remove_by_callback (listener->callbacks, callback);
263 }